Skip to content

Instantly share code, notes, and snippets.

@ufukty
Last active February 8, 2026 11:50
Show Gist options
  • Select an option

  • Save ufukty/f4e5d1a7e861a2b4973e6bde5a4204c3 to your computer and use it in GitHub Desktop.

Select an option

Save ufukty/f4e5d1a7e861a2b4973e6bde5a4204c3 to your computer and use it in GitHub Desktop.
Sync labels between repositories
#!/usr/bin/env bash
# run as: ./labels.sh path/to/source/repository path/to/target/repository
# first check if this is sufficient: gh label clone owner/source-repo
# make sure you won't miss the info of issues and PRs attached to the labels the script will delete
PS4='\033[31m$0:$LINENO: \033[0m'
set -eEo pipefail
test $# -eq 2
test -d "$1"
test -d "$2"
which bash
which comm
which gh
which jq
target="$(cd "$1" && gh label list --json name,description,color)"
current="$(cd "$2" && gh label list --json name,description,color)"
targetTags="$(echo "$target" | jq -r '.[].name' | sort)"
currentTags="$(echo "$current" | jq -r '.[].name' | sort)"
toCreateTags="$(comm -23 <(echo "$targetTags") <(echo "$currentTags"))"
toDeleteTags="$(comm -13 <(echo "$targetTags") <(echo "$currentTags"))"
toUpdateTags="$(comm -12 <(echo "$targetTags") <(echo "$currentTags"))"
if test "$toCreateTags"; then
echo "Will be created:"
echo "$toCreateTags"
echo
fi
if test "$toUpdateTags"; then
echo "Will be checked to update:"
echo "$toUpdateTags"
echo
fi
if test "$toDeleteTags"; then
echo "Will be deleted:"
echo "$toDeleteTags"
echo
fi
read -rn 1 -p "Press any key..."
(
cd "$2"
# create new
echo "$toCreateTags" | while read -r TAG; do
if test -z "$TAG"; then continue; fi
DESC="$(echo "$target" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .description')"
COLR="$(echo "$target" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .color')"
set -x
gh label create "$TAG" --description "$DESC" --color "$COLR"
set +x
done
# delete irrelevant
echo "$toDeleteTags" | while read -r TAG; do
if test -z "$TAG"; then continue; fi
set -x
gh label delete --yes "$TAG"
set +x
done
# update existing
echo "$toUpdateTags" | while read -r TAG; do
if test -z "$TAG"; then continue; fi
CURRNT_DESC="$(echo "$current" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .description')"
TARGET_DESC="$(echo "$target" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .description')"
if test -z "$CURRNT_DESC"; then CURRNT_DESC=" "; fi
if test -z "$TARGET_DESC"; then TARGET_DESC=" "; fi # gh prevents deleting description
if test "$TARGET_DESC" != "$CURRNT_DESC"; then
set -x
gh label edit "$TAG" --description "$TARGET_DESC"
set +x
fi
CURRNT_COLR="$(echo "$current" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .color')"
TARGET_COLR="$(echo "$target" | jq -jr --arg TAG "$TAG" '.[] | select(.name == $TAG) | .color')"
if test "$TARGET_COLR" != "$CURRNT_COLR"; then
set -x
gh label edit "$TAG" --color "$TARGET_COLR"
set +x
fi
done
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment