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
60 changes: 50 additions & 10 deletions .github/workflows/main-post-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,42 @@ jobs:
git fetch origin --tags --force
git fetch upstream main --tags --force

- name: Detect releasable upstream tags
- name: Detect new upstream tags
id: upstream_tag
shell: bash
run: |
set -euo pipefail

# 获取 fork 当前最高版本
FORK_LATEST=$(git tag --list 'v[0-9]*' --sort=-v:refname | head -1 || echo "v0.0.0")
FORK_VERSION=${FORK_LATEST#v}

echo "Fork latest version: $FORK_VERSION"

# 收集高于当前版本的上游 tag
TAGS=()
while read -r tag; do
[ -z "$tag" ] && continue
TAG_COMMIT="$(git rev-list -n 1 "$tag")"
if git merge-base --is-ancestor "$TAG_COMMIT" HEAD; then
if ! git ls-remote --tags origin "refs/tags/$tag" | grep -q .; then
TAGS+=("$tag")
TAG_VERSION=${tag#v}

# 版本比较:只收集比 fork 更新的版本
if [ "$(printf '%s\n' "$FORK_VERSION" "$TAG_VERSION" | sort -V | tail -1)" = "$TAG_VERSION" ] && [ "$TAG_VERSION" != "$FORK_VERSION" ]; then
TAG_COMMIT="$(git rev-list -n 1 "$tag")"
if git merge-base --is-ancestor "$TAG_COMMIT" HEAD; then
if ! git ls-remote --tags origin "refs/tags/$tag" | grep -q .; then
TAGS+=("$tag")
echo "Found new tag: $tag (newer than $FORK_VERSION)"
fi
fi
fi
done < <(git tag --list 'v[0-9]*' --sort=v:refname)

if [ ${#TAGS[@]} -eq 0 ]; then
echo "found=false" >> "$GITHUB_OUTPUT"
echo "No new tags to sync"
exit 0
fi

# Use the highest version tag as the primary
LATEST="${TAGS[-1]}"
MESSAGE_FILE="$(mktemp)"
git for-each-ref "refs/tags/$LATEST" --format='%(contents)' > "$MESSAGE_FILE"
Expand All @@ -129,16 +143,42 @@ jobs:
echo "all_tags=${TAGS[*]}"
} >> "$GITHUB_OUTPUT"

- name: Push upstream release tags to fork
echo "Will sync ${#TAGS[@]} tag(s): ${TAGS[*]}"

- name: Push upstream release tags sequentially
if: steps.upstream_tag.outputs.found == 'true'
env:
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
run: |
# Push tags in ascending version order so the highest version is pushed last
# This ensures GitHub marks the highest version as "Latest"
for tag in ${{ steps.upstream_tag.outputs.all_tags }}; do
echo "Pushing tag: $tag"
echo "=== Processing tag: $tag ==="

MSG_FILE="$(mktemp)"
git for-each-ref "refs/tags/$tag" --format='%(contents)' > "$MSG_FILE" 2>/dev/null || echo "$tag" > "$MSG_FILE"
git tag -d "$tag"
git tag -a "$tag" -F "$MSG_FILE" HEAD
git push origin "refs/tags/$tag"

echo "Waiting for release workflow to start..."
sleep 60

# 等待 release workflow 完成(最多 40 分钟)
for i in {1..40}; do
RUNS=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow=release.yml --json status,conclusion,createdAt --limit 5)
LATEST_RUN=$(echo "$RUNS" | jq -r 'first(.[] | select(.createdAt > (now - 3600 | todate)))')

if [ -n "$LATEST_RUN" ] && [ "$LATEST_RUN" != "null" ]; then
STATUS=$(echo "$LATEST_RUN" | jq -r '.status')
if [ "$STATUS" = "completed" ]; then
CONCLUSION=$(echo "$LATEST_RUN" | jq -r '.conclusion')
echo "Release workflow completed with: $CONCLUSION"
break
fi
fi

echo "Waiting... ($i/40)"
sleep 60
done

echo "=== Finished processing $tag ==="
done
13 changes: 11 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
type: string

concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
group: release-global
cancel-in-progress: false

permissions:
Expand Down Expand Up @@ -170,6 +170,9 @@ jobs:

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
timeout-minutes: 30
continue-on-error: true
id: goreleaser
with:
version: '~> v2'
args: release --clean --skip=validate --config=.goreleaser.yaml
Expand Down Expand Up @@ -298,12 +301,18 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add backend/cmd/server/VERSION

if git diff --cached --quiet; then
echo "No changes to commit - VERSION already matches $VERSION"
exit 0
fi

git commit -m "chore: sync VERSION to ${VERSION} [skip ci]"
git push origin HEAD:${{ github.event.repository.default_branch }}

ensure-latest:
needs: [release]
if: ${{ needs.release.result == 'success' }}
if: always()
runs-on: ubuntu-latest
steps:
- name: Ensure latest points to highest version
Expand Down
104 changes: 52 additions & 52 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,38 +87,38 @@ dockers:
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}"

# GHCR images (owner must be lowercase)
- id: ghcr-amd64
goos: linux
goarch: amd64
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
dockerfile: Dockerfile.goreleaser
use: buildx
extra_files:
- deploy/docker-entrypoint.sh
- backend/resources
build_flag_templates:
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}"
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}"

- id: ghcr-arm64
goos: linux
goarch: arm64
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
dockerfile: Dockerfile.goreleaser
use: buildx
extra_files:
- deploy/docker-entrypoint.sh
- backend/resources
build_flag_templates:
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}"
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}"
# GHCR images (disabled due to timeout issues)
# - id: ghcr-amd64
# goos: linux
# goarch: amd64
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
# dockerfile: Dockerfile.goreleaser
# use: buildx
# extra_files:
# - deploy/docker-entrypoint.sh
# - backend/resources
# build_flag_templates:
# - "--platform=linux/amd64"
# - "--label=org.opencontainers.image.version={{ .Version }}"
# - "--label=org.opencontainers.image.revision={{ .Commit }}"
# - "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}"

# - id: ghcr-arm64
# goos: linux
# goarch: arm64
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
# dockerfile: Dockerfile.goreleaser
# use: buildx
# extra_files:
# - deploy/docker-entrypoint.sh
# - backend/resources
# build_flag_templates:
# - "--platform=linux/arm64"
# - "--label=org.opencontainers.image.version={{ .Version }}"
# - "--label=org.opencontainers.image.revision={{ .Commit }}"
# - "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}"

# Docker manifests for multi-arch support
docker_manifests:
Expand Down Expand Up @@ -147,26 +147,26 @@ docker_manifests:
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"

# GHCR manifests (owner must be lowercase)
- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"

- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:latest"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"

- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}.{{ .Minor }}"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"

- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
# GHCR manifests (disabled due to timeout issues)
# - name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}"
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
#
# - name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:latest"
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
#
# - name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}.{{ .Minor }}"
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"
#
# - name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}"
# image_templates:
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64"
# - "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64"

release:
github:
Expand Down