11# This Action will run when a release is published from the LTS branches
2- # and create new LTS tag, release and publish the image in GHCR
2+ # and create new LTS tag, release and tag the existing image in GHCR
33
44name : Tag and Recreate LTS Release
55
66on :
7- release :
8- types : [published]
7+ workflow_run :
8+ workflows : ["Publish ACA-Py Image"]
9+ types : [completed]
10+ workflow_dispatch :
11+ inputs :
12+ release_tag :
13+ description : ' Release tag to create LTS from (e.g., 1.2.3)'
14+ required : true
15+ type : string
916
1017permissions :
1118 contents : write
1219 packages : write
1320
1421jobs :
1522 recreate-lts-release :
16- # This job is disabled by default for main, should be enabled for LTS branches and tags.
17- # To enable it, you can set the condition in the `if` statement below.
18- # The condition should check if the release tag starts with the LTS version prefix.
19- # For example, if your LTS versions are prefixed with '1.2.', you can use:
20- # if: startsWith(github.event.release.tag_name, '1.2.')
21- # This will ensure that the job only runs for releases that are tagged with LTS versions.
22- if : false
23+ # LTS versions are now configured in .github/lts-versions.txt
24+ # Add version patterns (major.minor format) to that file to enable LTS processing
25+ if : |
26+ (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
27+ (github.event_name == 'workflow_dispatch')
2328 name : Recreate LTS Release
2429 runs-on : ubuntu-latest
2530 outputs :
26- lts_tag : ${{ steps.vars.outputs.LTS_TAG }}
31+ lts_tag : ${{ steps.set_outputs.outputs.lts_tag }}
32+ release_tag : ${{ steps.set_outputs.outputs.release_tag }}
2733
2834 steps :
2935 - name : Checkout repository
3036 uses : actions/checkout@v6
3137 with :
3238 fetch-depth : 0
3339
40+ - name : Get Release Tag
41+ id : get_release
42+ if : github.event_name == 'workflow_run'
43+ env :
44+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
45+ run : |
46+ SHA="${{ github.event.workflow_run.head_sha }}"
47+ echo "Looking for release associated with commit: $SHA"
48+
49+ # Try to find release by target_commitish first (fast path)
50+ RELEASE_TAG=$(gh api /repos/${{ github.repository }}/releases --paginate | \
51+ jq -r --arg sha "$SHA" \
52+ '.[] | select(.target_commitish == $sha) | .tag_name' | head -1)
53+
54+ # If not found, try to find tags pointing to this commit and check for releases
55+ if [ -z "$RELEASE_TAG" ]; then
56+ echo "No release found by target_commitish, checking tags pointing to commit..."
57+ TAGS=$(git tag --points-at "$SHA" 2>/dev/null || echo "")
58+
59+ if [ -n "$TAGS" ]; then
60+ echo "Tags found: $TAGS"
61+ # Fetch all releases once
62+ ALL_RELEASES=$(gh api /repos/${{ github.repository }}/releases --paginate | jq -r '.[].tag_name')
63+
64+ # Check each tag to see if it has a release
65+ for TAG in $TAGS; do
66+ if echo "$ALL_RELEASES" | grep -q "^${TAG}$"; then
67+ RELEASE_TAG="$TAG"
68+ echo "Found release for tag: $TAG"
69+ break
70+ fi
71+ done
72+ fi
73+ fi
74+
75+ if [ -z "$RELEASE_TAG" ]; then
76+ echo "No release found for commit $SHA"
77+ echo "skip=true" >> "$GITHUB_OUTPUT"
78+ elif [[ "$RELEASE_TAG" =~ rc ]]; then
79+ echo "Release $RELEASE_TAG is an RC release - skipping LTS tagging"
80+ echo "skip=true" >> "$GITHUB_OUTPUT"
81+ else
82+ echo "Found release: $RELEASE_TAG"
83+ echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
84+ echo "skip=false" >> "$GITHUB_OUTPUT"
85+ fi
86+
87+ - name : Check if Release is LTS
88+ id : check_lts
89+ if : steps.get_release.outputs.skip != 'true' || github.event_name == 'workflow_dispatch'
90+ run : |
91+ # Get release tag based on trigger type
92+ if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
93+ RELEASE_TAG="${{ inputs.release_tag }}"
94+ else
95+ RELEASE_TAG="${{ steps.get_release.outputs.release_tag }}"
96+ fi
97+
98+ # Read LTS versions from config file (remove comments and empty lines)
99+ LTS_VERSIONS=$(grep -v '^#' .github/lts-versions.txt | grep -v '^$' | tr '\n' '|' | sed 's/|$//')
100+
101+ if [ -z "$LTS_VERSIONS" ]; then
102+ echo "No LTS versions configured in .github/lts-versions.txt"
103+ echo "skip=true" >> "$GITHUB_OUTPUT"
104+ exit 0
105+ fi
106+
107+ echo "Configured LTS versions: $LTS_VERSIONS"
108+ echo "Checking release: $RELEASE_TAG"
109+
110+ # Extract major.minor from release tag
111+ SHORT_TAG=$(echo "$RELEASE_TAG" | cut -d. -f1,2)
112+
113+ # Check if it matches any LTS version pattern
114+ if echo "$SHORT_TAG" | grep -qE "^($LTS_VERSIONS)$"; then
115+ echo "Release $RELEASE_TAG matches LTS version $SHORT_TAG"
116+ echo "skip=false" >> "$GITHUB_OUTPUT"
117+ else
118+ echo "Release $RELEASE_TAG (version $SHORT_TAG) is not configured as LTS"
119+ echo "skip=true" >> "$GITHUB_OUTPUT"
120+ fi
121+
122+ - name : Set Release Tag for Output
123+ id : set_release_tag
124+ run : |
125+ if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
126+ RELEASE_TAG="${{ inputs.release_tag }}"
127+ else
128+ RELEASE_TAG="${{ steps.get_release.outputs.release_tag }}"
129+ fi
130+
131+ # Validate semantic versioning format (semver 2.0)
132+ if ! echo "$RELEASE_TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
133+ echo "Error: Release tag '$RELEASE_TAG' does not match semantic versioning format (X.Y.Z[-prerelease][+build])"
134+ exit 1
135+ fi
136+
137+ echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
138+ echo "Validated release tag: $RELEASE_TAG"
139+
140+ - name : Determine if workflow should proceed
141+ id : should_proceed
142+ run : |
143+ if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
144+ # workflow_dispatch: check LTS validation result
145+ if [ "${{ steps.check_lts.outputs.skip }}" == "true" ]; then
146+ echo "proceed=false" >> "$GITHUB_OUTPUT"
147+ echo "Skipping: Release is not configured as LTS"
148+ else
149+ echo "proceed=true" >> "$GITHUB_OUTPUT"
150+ echo "Proceeding with workflow_dispatch"
151+ fi
152+ elif [ "${{ steps.get_release.outputs.skip }}" == "true" ] || [ "${{ steps.check_lts.outputs.skip }}" == "true" ]; then
153+ # workflow_run: skip if either check failed
154+ echo "proceed=false" >> "$GITHUB_OUTPUT"
155+ echo "Skipping: release check or LTS check failed"
156+ else
157+ # workflow_run: proceed if both checks passed
158+ echo "proceed=true" >> "$GITHUB_OUTPUT"
159+ echo "Proceeding with workflow_run"
160+ fi
161+
34162 - name : Set up Git identity
163+ if : steps.should_proceed.outputs.proceed == 'true'
35164 run : |
36165 git config user.name "github-actions"
37166 git config user.email "github-actions@github.com"
38167
39168 - name : Determine LTS tag and update
169+ if : steps.should_proceed.outputs.proceed == 'true'
40170 id : vars
41171 env :
42- BRANCH_REF : ${{ github.event.release.target_commitish }}
43- RELEASE_TAG : ${{ github.event.release.tag_name }}
44- RELEASE_BODY : ${{ github.event.release.body }}
172+ RELEASE_TAG : ${{ steps.set_release_tag.outputs.release_tag }}
173+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
45174 run : |
46- echo "Release published from branch : $BRANCH_REF "
175+ echo "Processing release : $RELEASE_TAG "
47176
48- # Creating a LTS tag from the branch name
177+ # Creating a LTS tag from the release tag
49178 SHORT_TAG=$(echo "$RELEASE_TAG" | cut -d. -f1,2)
50179 LTS_TAG="${SHORT_TAG}-lts"
51180 echo "LTS_TAG=$LTS_TAG" >> "$GITHUB_OUTPUT"
52181
53- # Force update the tag to the current commit
54- git tag -f "$LTS_TAG" $GITHUB_SHA
55- git push origin -f "$LTS_TAG"
182+ # Get the commit SHA that the release tag points to
183+ RELEASE_SHA=$(git rev-parse "$RELEASE_TAG^{}")
184+ echo "Release tag $RELEASE_TAG points to commit: $RELEASE_SHA"
185+
186+ # Force update the LTS tag to point to the same commit as the release
187+ git tag -f "$LTS_TAG" "$RELEASE_SHA"
188+ git push origin -f "$LTS_TAG"
189+
190+ # Get release body from the original release
191+ RELEASE_BODY=$(gh release view "$RELEASE_TAG" --json body -q .body)
56192
57193 # Write release notes into env (for multiline input)
58194 echo "RELEASE_BODY<<EOF" >> "$GITHUB_ENV"
59195 echo "${RELEASE_BODY}" >> "$GITHUB_ENV"
60196 echo "EOF" >> "$GITHUB_ENV"
61197
62198 - name : Delete existing LTS release (if any)
199+ if : steps.should_proceed.outputs.proceed == 'true'
63200 continue-on-error : true
64201 env :
65202 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
@@ -69,18 +206,63 @@ jobs:
69206 gh release delete "$LTS_TAG" -y
70207
71208 - name : Create fresh LTS release
209+ if : steps.should_proceed.outputs.proceed == 'true'
72210 env :
73211 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
74212 LTS_TAG : ${{ steps.vars.outputs.LTS_TAG }}
75213 RELEASE_BODY : ${{ env.RELEASE_BODY }}
76214 run : |
77215 echo "Creating new GitHub release for $LTS_TAG"
78216 gh release create "$LTS_TAG" --title "$LTS_TAG" --notes "$RELEASE_BODY"
217+
218+ - name : Set Job Outputs
219+ id : set_outputs
220+ if : steps.should_proceed.outputs.proceed == 'true'
221+ run : |
222+ echo "lts_tag=${{ steps.vars.outputs.LTS_TAG }}" >> "$GITHUB_OUTPUT"
223+ echo "release_tag=${{ steps.set_release_tag.outputs.release_tag }}" >> "$GITHUB_OUTPUT"
224+ echo "Set job outputs for downstream job"
79225
80- call-publish-image :
81- name : Publish LTS Image in GHCR
226+ tag-lts-images :
227+ name : Tag Existing Images with LTS
82228 needs : recreate-lts-release
83- uses : ./.github/workflows/publish.yml
84- with :
85- tag : ${{ needs.recreate-lts-release.outputs.lts_tag }}
86- ref : ${{ github.event.release.tag_name }}
229+ if : |
230+ needs.recreate-lts-release.outputs.lts_tag != '' &&
231+ needs.recreate-lts-release.outputs.release_tag != ''
232+ runs-on : ubuntu-latest
233+ strategy :
234+ matrix :
235+ python-version : ["3.12"]
236+ image-name : ["acapy-agent", "acapy-agent-bbs"]
237+
238+ steps :
239+ - name : Log in to the GitHub Container Registry
240+ uses : docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
241+ with :
242+ registry : ghcr.io
243+ username : ${{ github.repository_owner }}
244+ password : ${{ secrets.GITHUB_TOKEN }}
245+
246+ - name : Lowercase Repo Owner
247+ id : lower
248+ run : echo "owner=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_OUTPUT
249+
250+ - name : Tag Images with LTS
251+ env :
252+ SOURCE_TAG : py${{ matrix.python-version }}-${{ needs.recreate-lts-release.outputs.release_tag }}
253+ LTS_TAG : py${{ matrix.python-version }}-${{ needs.recreate-lts-release.outputs.lts_tag }}
254+ IMAGE_NAME : ghcr.io/${{ steps.lower.outputs.owner }}/${{ matrix.image-name }}
255+ run : |
256+ echo "Tagging \"$IMAGE_NAME:$SOURCE_TAG\" with \"$LTS_TAG\""
257+
258+ # Pull the source image
259+ docker pull "$IMAGE_NAME:$SOURCE_TAG"
260+
261+ # Tag it with the LTS tag
262+ docker tag "$IMAGE_NAME:$SOURCE_TAG" "$IMAGE_NAME:$LTS_TAG"
263+
264+ # Push the new tag
265+ docker push "$IMAGE_NAME:$LTS_TAG"
266+
267+ echo "Successfully tagged \"$IMAGE_NAME\" with \"$LTS_TAG\""
268+
0 commit comments