Skip to content

Commit cce5f36

Browse files
committed
GHA release workflow supports multiple tags via github-tag-templates input field
1 parent da90332 commit cce5f36

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

.github/actions/release/action.yaml

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,14 @@ inputs:
140140
os: linux
141141
arch: x86_64
142142
```
143-
github-tag-template:
143+
github-tag-templates:
144144
default: '${version}'
145145
type: string
146146
description: |
147-
GitHub tag template to use for the created release tag. Currently only supported template-var:
147+
Comma-separated list of GitHub tag templates to use for the created release tags. Each template can use
148148
${version} (bash-syntax): Version read from local component descriptor (i.e. previous version
149149
operations are honoured).
150+
The first tag in the list will be used to create the GitHub release.
150151
on-existing-component-descriptor:
151152
default: fail
152153
type: choice
@@ -201,10 +202,42 @@ runs:
201202
EOF
202203
version=$(yq .component.version /tmp/component-descriptor.yaml)
203204
echo "version=${version}" >> $GITHUB_OUTPUT
204-
tag_name="${{ inputs.github-tag-template }}"
205-
tag_ref="refs/tags/${tag_name}"
206-
echo "tag-ref=${tag_ref}" >> $GITHUB_OUTPUT
207-
echo "tag-name=${tag_name}" >> $GITHUB_OUTPUT
205+
# Parse github-tag-templates string into array
206+
IFS=',' read -ra tag_templates <<< "${{ inputs.github-tag-templates }}"
207+
tag_names=()
208+
tag_refs=()
209+
for template in "${tag_templates[@]}"; do
210+
template=$(echo "$template" | xargs) # trim whitespace
211+
tag_name=$(echo "$template" | sed "s/\\${version}/$version/g")
212+
tag_names+=("$tag_name")
213+
tag_refs+=("refs/tags/$tag_name")
214+
done
215+
if [ "${#tag_names[@]}" -eq 0 ]; then
216+
echo "Error: github-tag-templates must contain at least one item." >&2
217+
exit 1
218+
fi
219+
# Validate uniqueness
220+
unique_tags=$(printf "%s\n" "${tag_names[@]}" | sort | uniq)
221+
if [ $(printf "%s\n" "${tag_names[@]}" | wc -l) -ne $(printf "%s\n" "$unique_tags" | wc -l) ]; then
222+
echo "Error: Duplicate tag names found in github-tag-templates: ${tag_names[*]}" >&2
223+
exit 1
224+
fi
225+
# Validate tag names (must not be empty, must match valid git tag pattern)
226+
for tag in "${tag_names[@]}"; do
227+
if [[ -z "$tag" ]]; then
228+
echo "Error: Tag name must not be empty." >&2
229+
exit 1
230+
fi
231+
# Git tag name rules: no spaces, no ASCII control chars, no ~^:?*[\, must not start with -
232+
if [[ "$tag" =~ [~^:?*\\[\]@\s] || "$tag" =~ ^- ]]; then
233+
echo "Error: Invalid tag name '$tag'." >&2
234+
exit 1
235+
fi
236+
done
237+
echo "tag-names=${tag_names[*]}" >> $GITHUB_OUTPUT
238+
echo "tag-refs=${tag_refs[*]}" >> $GITHUB_OUTPUT
239+
# Set first tag as main release tag
240+
echo "release-tag-name=${tag_names[0]}" >> $GITHUB_OUTPUT
208241
cat <<"EOF" > /tmp/assets.yaml
209242
${{ inputs.assets }}
210243
EOF
@@ -352,16 +385,21 @@ runs:
352385
path: /tmp/component-descriptor.tar.gz
353386
name: component-descriptor
354387

355-
- name: push release-tag
388+
- name: push tag-refs
356389
shell: bash
357390
run: |
358391
set -eu
392+
for tag_ref in ${{ steps.preprocess.outputs.tag-refs }}; do
393+
push_spec="@:$$tag_ref"
394+
echo "pushing release-commit using ${push_spec}"
395+
git push origin "${push_spec}"
396+
done
359397
398+
- name: push release-commit
399+
shell: bash
400+
run: |
401+
set -eu
360402
orig_ref="$(git rev-parse @)"
361-
push_spec="@:${{ steps.preprocess.outputs.tag-ref }}"
362-
echo "pushing release-commit using ${push_spec}"
363-
git push origin "${push_spec}"
364-
365403
case "${{ inputs.release-commit-target }}" in
366404
tag)
367405
echo "chose to not push tag to source-branch: exiting now"
@@ -440,12 +478,11 @@ runs:
440478
441479
repository = github_api.repository(org, repo)
442480
443-
444481
release_notes_markdown = '''\
445482
${{ inputs.full-release-notes }}
446483
'''
447484
448-
release_tag_name = '${{ steps.preprocess.outputs.tag-name }}'
485+
release_tag_name = '${{ steps.preprocess.outputs.release-tag-name }}'
449486
draft_tag_name = f'{release_tag_name}-draft'
450487
451488
if not (gh_release := github.release.find_draft_release(

.github/workflows/release.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,14 @@ on:
9696
description: |
9797
If set to `true`, the workflow will create a new GitHub release (or convert an existing
9898
draft release to an actual release).
99-
github-tag-template:
99+
github-tag-templates:
100100
default: '${version}'
101101
type: string
102102
description: |
103-
GitHub tag template to use for the created release tag. Currently only supported
104-
template-var: ${version} (bash-syntax).
103+
Comma-separated list of GitHub tag templates to use for the created release tags. Each template can use
104+
${version} (bash-syntax): Version read from local component descriptor (i.e. previous version
105+
operations are honoured).
106+
The first tag in the list will be used to create the GitHub release.
105107
assets:
106108
type: string
107109
required: false
@@ -214,7 +216,7 @@ jobs:
214216
github-token: ${{ secrets.GITHUB_TOKEN }}
215217
git-push-token: ${{ steps.app-token.outputs.token }}
216218
release-on-github: ${{ inputs.release-on-github }}
217-
github-tag-template: ${{ inputs.github-tag-template }}
219+
github-tag-templates: ${{ inputs.github-tag-templates }}
218220
assets: ${{ inputs.assets }}
219221

220222
- name: write-release-notes-to-file

0 commit comments

Comments
 (0)