Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/skills/sync-upstream-tags/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: sync-upstream-tags
description: Compare local release tags with git/git tags and create+push each missing version tag in ascending order.
---

# Sync Upstream Git Release Tags

Use this skill when you need to synchronize this repository's release tags with upstream Git releases.

## Steps

1. Identify the latest local semantic version tag (`X.Y.Z`) in this repository.
2. Fetch upstream release tags from `https://github.com/git/git/tags`.
3. Compute missing semantic version tags not present locally.
4. Process missing tags in ascending version order (oldest to newest).
5. For each missing tag, run:
- `git tag <version>`
- `git push origin <version>`
6. Stop immediately if any command fails, and report which tag failed.

## Run

```bash
bash .github/skills/sync-upstream-tags/scripts/sync-upstream-tags.sh
```

## Verify

- [ ] Missing tags were handled from oldest to newest
- [ ] Every created tag was pushed individually
- [ ] No non-semver tags were created
51 changes: 51 additions & 0 deletions .github/skills/sync-upstream-tags/scripts/sync-upstream-tags.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -euo pipefail

UPSTREAM_REPO_URL="https://github.com/git/git.git"
SEMVER_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+$'

mapfile -t local_tags < <(git tag --list | grep -E "$SEMVER_PATTERN" | sort -V || true)
mapfile -t upstream_tags < <(
git ls-remote --tags --refs "$UPSTREAM_REPO_URL" \
| awk '{print $2}' \
| sed 's#refs/tags/##' \
| sed 's/^v//' \
| grep -E "$SEMVER_PATTERN" \
| sort -uV
)

latest_local_tag=""
if ((${#local_tags[@]} > 0)); then
latest_local_tag="${local_tags[-1]}"
fi

printf 'Latest local semver tag: %s\n' "${latest_local_tag:-<none>}"

declare -A local_tag_lookup=()
for tag in "${local_tags[@]}"; do
local_tag_lookup["$tag"]=1
done

missing_tags=()
for tag in "${upstream_tags[@]}"; do
if [[ -z "${local_tag_lookup[$tag]:-}" ]]; then
missing_tags+=("$tag")
fi
done

if ((${#missing_tags[@]} == 0)); then
echo "No missing upstream semver tags found."
exit 0
fi

printf 'Missing tags to create/push (%d): %s\n' "${#missing_tags[@]}" "${missing_tags[*]}"

for tag in "${missing_tags[@]}"; do
echo "Creating tag: $tag"
git tag "$tag"

echo "Pushing tag: $tag"
git push origin "$tag"
done

echo "Tag synchronization complete."