Add GitHub workflow to automate release tag creation - #2753
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NpWWjywQsozhFp7pgsz1Cy
📝 WalkthroughWalkthroughAdded a manual release workflow for patch and minor versions. It validates ChangesManual release and workflow dispatch
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubActions as GitHub Actions
participant GitHubRepository as GitHub repository
participant ReleaseWorkflows as Release workflows
participant DockerJob as Docker production job
GitHubActions->>GitHubRepository: Push master commit and generated tag atomically
GitHubActions->>ReleaseWorkflows: Dispatch release workflows on the tag
ReleaseWorkflows->>DockerJob: Run production build only for refs/tags/v
GitHubActions->>GitHubActions: Write release details to job summary
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Stale comment
Review: Create release tag workflow
Useful automation that matches the existing manual release pattern (
npm versionbump of rootpackage.json+package-lock.json, commit message like4.84.1, tagv*.*.*→docker-release-build.yml). Master-only guard, patch/minor-only choices, and bot commit identity look good.Not approving yet — please address the silent
GITHUB_TOKENfallback (and ideally concurrency) before merge. WithoutRELEASE_PAT, a green run creates a tag that does not trigger the production release workflows this PR exists to drive.No Gladys runtime / device-constants impact → no
risk:high/needs:human-review.Sent by Cursor Automation: Automatic PR review
|
🐳 A Docker image has been built for this branch and pushed to the GitHub Container Registry. You can test this pull request (AMD64 only) by pulling the image below: For example, run it with: sudo docker run -d \
--log-driver json-file \
--log-opt max-size=10m \
--cgroupns=host \
--restart=always \
--privileged \
--network=host \
--name gladys-claude-github-action-release-tag-ht845u \
-e NODE_ENV=production \
-e SERVER_PORT=80 \
-e TZ=Europe/Paris \
-e SQLITE_FILE_PATH=/var/lib/gladysassistant/gladys-production.db \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/gladysassistant:/var/lib/gladysassistant \
-v /dev:/dev \
-v /run/udev:/run/udev:ro \
ghcr.io/gladysassistant/gladys-preview:claude-github-action-release-tag-ht845uThis comment and the image are automatically updated on every new commit pushed to this pull request. Need an ARM64 image (Raspberry Pi, Apple Silicon, …)? Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
.github/workflows/create-release-tag.yml (3)
53-58: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winKeep dynamic values out of the shell source.
The summary expands step outputs and workflow metadata directly into Bash. Pass these values through
envand use quotedprintfarguments. GitHub evaluates context expressions before the runner executes the script. (docs.github.com)📝 Proposed fix
- name: 📝 Job summary + env: + VERSION: ${{ steps.bump.outputs.version }} + RELEASE_TYPE: ${{ inputs.release_type }} + SERVER_URL: ${{ github.server_url }} + REPOSITORY: ${{ github.repository }} run: | - echo "### 🚀 Release ${{ steps.bump.outputs.version }} created" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "- Bump type: \`${{ inputs.release_type }}\`" >> "$GITHUB_STEP_SUMMARY" - echo "- Tag: [\`${{ steps.bump.outputs.version }}\`](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ steps.bump.outputs.version }})" >> "$GITHUB_STEP_SUMMARY" + printf '### 🚀 Release %s created\n' "$VERSION" >> "$GITHUB_STEP_SUMMARY" + printf '\n' >> "$GITHUB_STEP_SUMMARY" + printf -- '- Bump type: `%s`\n' "$RELEASE_TYPE" >> "$GITHUB_STEP_SUMMARY" + printf -- '- Tag: [`%s`](%s/%s/releases/tag/%s)\n' \ + "$VERSION" "$SERVER_URL" "$REPOSITORY" "$VERSION" >> "$GITHUB_STEP_SUMMARY"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/create-release-tag.yml around lines 53 - 58, Update the “📝 Job summary” step to pass the release version, release type, server URL, and repository through an env block, then write the summary using quoted printf arguments instead of interpolating GitHub expressions directly in the Bash source. Preserve the existing headings, bump type, and release-tag link output.Source: Linters/SAST tools
44-49: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winMake the version bump deterministic.
The downstream workflow matches only
v*.*.*tags. npm 10 defaults to thevprefix, but npm configuration can overridetag-version-prefix. Pass the input throughenv, validatepatchorminor, and set--tag-version-prefix=vexplicitly. (docs.npmjs.com)🏷️ Proposed fix
- name: 🔖 Bump version and create tag id: bump + env: + RELEASE_TYPE: ${{ inputs.release_type }} run: | - NEW_VERSION=$(npm version ${{ inputs.release_type }}) + case "$RELEASE_TYPE" in + patch|minor) ;; + *) echo "Unsupported release type" >&2; exit 1 ;; + esac + NEW_VERSION=$(npm version --tag-version-prefix=v "$RELEASE_TYPE")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/create-release-tag.yml around lines 44 - 49, Update the “Bump version and create tag” step to pass the release type through its environment, validate that it is only patch or minor, and invoke npm version with an explicit v tag-version prefix so generated tags always match v*.*.*.
29-35: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winLimit the PAT to the push operation.
actions/checkout@v4persists the supplied token for later Git commands by default. This makes the write-capable PAT available to later steps, including package lifecycle scripts. Setpersist-credentials: falseand configure a temporary credential only in the push step. Do not add the flag without updating the push authentication. (github.com)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/create-release-tag.yml around lines 29 - 35, Update the checkout configuration in the “⬇️ Checkout Gladys code” step to set persist-credentials to false, then update the later tag-push step to authenticate explicitly with the release PAT only for that push operation, preserving the existing fallback behavior where applicable.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/create-release-tag.yml:
- Around line 19-22: Add a workflow-level concurrency configuration for
create-release-tag, using a release-specific group and setting
cancel-in-progress to false so manually dispatched release runs queue instead of
overlapping. Keep the existing create-release-tag job configuration unchanged.
- Around line 29-35: Update the checkout step in the release workflow to require
secrets.RELEASE_PAT directly, removing the fallback to secrets.GITHUB_TOKEN.
Preserve the existing token usage so checkout and subsequent git push operations
fail when RELEASE_PAT is unavailable.
- Around line 24-28: Move the master-branch restriction from the “🛑 Ensure
workflow runs on master” step to the job-level if condition, preventing the job
from starting for other refs. Update the checkout action to explicitly target
refs/heads/master, and remove the shell-based github.ref_name interpolation and
late branch guard.
- Around line 50-52: Update the “🚀 Push commit and tag” step to use Git’s
atomic push option so the release commit and tags succeed or fail together. Also
ensure this workflow is serialized with other release or branch-update workflows
using the repository’s existing concurrency mechanism, preventing simultaneous
ref updates.
---
Nitpick comments:
In @.github/workflows/create-release-tag.yml:
- Around line 53-58: Update the “📝 Job summary” step to pass the release
version, release type, server URL, and repository through an env block, then
write the summary using quoted printf arguments instead of interpolating GitHub
expressions directly in the Bash source. Preserve the existing headings, bump
type, and release-tag link output.
- Around line 44-49: Update the “Bump version and create tag” step to pass the
release type through its environment, validate that it is only patch or minor,
and invoke npm version with an explicit v tag-version prefix so generated tags
always match v*.*.*.
- Around line 29-35: Update the checkout configuration in the “⬇️ Checkout
Gladys code” step to set persist-credentials to false, then update the later
tag-push step to authenticate explicitly with the release PAT only for that push
operation, preserving the existing fallback behavior where applicable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b17cbd1b-71dc-4a9b-ad78-9d1a38fe3db3
📒 Files selected for processing (1)
.github/workflows/create-release-tag.yml
| - name: 🛑 Ensure workflow runs on master | ||
| if: github.ref != 'refs/heads/master' | ||
| run: | | ||
| echo "This workflow can only be run on master, got ${{ github.ref_name }}." | ||
| exit 1 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files '.github/workflows/*' || true
echo "== target workflow =="
if [ -f .github/workflows/create-release-tag.yml ]; then
cat -n .github/workflows/create-release-tag.yml
else
echo "target file missing"
fi
echo "== package lifecycle scripts / npm version config =="
if [ -f package.json ]; then
python3 - <<'PY'
import json
p=json.load(open('package.json'))
for k in ['scripts','version']: print(k, p.get(k))
PY
fiRepository: GladysAssistant/Gladys
Length of output: 4472
🌐 Web query:
GitHub Actions run workflow button select branch workflow_dispatch manual runs on branch security bash injection github.ref_name
💡 Result:
Using ${{ github.ref_name }} or workflow inputs directly within a bash run block is a significant security risk, classified as template or shell command injection [1][2][3]. When you place these expressions directly into a run block, the GitHub Actions runner replaces the placeholders with their raw string values before the shell executes the command [4][2][5]. An attacker can craft a branch name or workflow input containing shell meta-characters (such as ;, &, |, or backticks) to break out of your intended command and execute arbitrary code on the runner [1][6][3]. To secure your workflows, you must never interpolate untrusted values directly into run scripts [1][2][5]. Instead, follow these industry-standard defensive practices: 1. Use Environment Variables: Map all untrusted inputs (including github.ref_name and workflow_dispatch inputs) to environment variables at the step level [4][6][7]. This ensures the values are treated as data, not code, by the shell [2][6][8]. Example of secure implementation: - name: Process branch name env: BRANCH_NAME: ${{ github.ref_name }} run: | # Use the variable in quotes to prevent shell interpretation echo "Processing branch:
Citations:
- 1: https://docs.github.com/en/actions/concepts/security/script-injections
- 2: https://github.blog/security/supply-chain-security/four-tips-to-keep-your-github-actions-workflows-secure/
- 3: Harden shell interpolation of github.head_ref / github.ref_name in workflow scripts WillBooster/reusable-workflows#433
- 4: https://osv.dev/vulnerability/GHSA-3g6g-gq4r-xjm9
- 5: https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/
- 6: GHSA-3g6g-gq4r-xjm9
- 7: Use intermediate env variables for bash script runners in github workflows containerd/containerd#13434
- 8: feat: auto-extract shell injection expressions from run: steps into env vars github/gh-aw#28998
- 9: https://actsense.dev/vulnerabilities/code_injection_via_input/
🌐 Web query:
npm version lifecycle scripts runs lifecycle scripts prepublish preversion version postversion
💡 Result:
In the npm lifecycle, scripts are triggered by specific commands to manage package preparation, versioning, and publishing [1][2]. Version Lifecycle Scripts When running the npm version command, the lifecycle scripts execute in the following fixed order [1][2]: 1. preversion: Runs before the package version is bumped [3][4]. 2. version: Runs after the version is bumped, but before the commit [3][4]. 3. postversion: Runs after the version is bumped and after the commit [3][4]. Prepublish and Related Scripts The prepublish script is considered deprecated because its behavior can be confusing; it runs both before the package is packed/published and during a local npm install without arguments [3][1]. To replace this, npm introduced other lifecycle events [3][1]: - prepublishOnly: Runs only before the package is prepared and packed, specifically during npm publish [3][1]. - prepare: Runs after prepublish, but before prepublishOnly. It executes during both npm publish and local npm install, serving as a reliable alternative for build steps [3][1]. General Note For any script (e.g., myscript), npm automatically looks for pre- and post- counterparts (premyscript and postmyscript) if they are defined in your package.json [1][2]. Additionally, the environment variable npm_lifecycle_event is always set to the name of the script currently being executed, allowing you to use a single script to handle multiple lifecycle stages [3][1].
Citations:
- 1: https://docs.npmjs.com/cli/v10/using-npm/scripts/
- 2: https://docs.npmjs.com/cli/v11/using-npm/scripts/
- 3: https://github.com/npm/cli/blob/e2346e7702acccefe6d711168c2b0e0e272e194a/doc/misc/npm-scripts.md
- 4: https://manpages.debian.org/testing/npm/npm-scripts.7.en.html
🌐 Web query:
GitHub Actions workflow_dispatch manual run select workflow branch if condition github.ref jobs job if
💡 Result:
When using workflow_dispatch to run a GitHub Actions workflow manually, the GitHub UI allows you to select any branch in the repository as the target for the workflow execution [1][2]. For the manual branch selection to function, the workflow file must exist in the default branch of the repository [1][3]. Once triggered, the workflow execution context identifies the selected branch through standard GitHub context variables [2]. You can use the github.ref or github.ref_name context variables within your workflow to dynamically handle the selected branch [2]. To restrict or control job execution based on the branch selected during the manual run, you can use the jobs.<job_id>.if condition [4][3]. Example implementation using a conditional job: jobs: deploy: runs-on: ubuntu-latest # This job will only run if the branch selected in the manual UI is 'main' if: ${{ github.ref_name == 'main' }} steps: - uses: actions/checkout@v4 - run: echo "Running on ${{ github.ref_name }}" If you need to control the branch used by the actions/checkout step itself (for example, to support scheduled runs alongside manual runs), you can use a ternary expression to dynamically set the ref [2]: jobs: checkout-job: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: # Use 'main' for scheduled runs, or the selected branch for manual runs ref: ${{ github.event_name == 'schedule' && 'main' || github.ref_name }}
Citations:
- 1: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow?tool=webui
- 2: https://stackoverflow.com/questions/78721097/set-branch-for-scheduled-runs-retain-ability-to-select-branch-for-manual-runs
- 3: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 4: https://github.com/github/docs/blob/main/content/actions/how-tos/write-workflows/choose-when-workflows-run/control-jobs-with-conditions.md
Move the branch restriction and checkout target outside untrusted output.
.github/workflows/create-release-tag.yml allows manual dispatch on any branch. Interpolating github.ref_name into the shell can allow command injection, and npm version can run lifecycle scripts from the selected repository state before the guard exits. Apply the check at job level and force checkout to refs/heads/master.
🧰 Tools
🪛 zizmor (1.28.0)
[error] 27-27: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/create-release-tag.yml around lines 24 - 28, Move the
master-branch restriction from the “🛑 Ensure workflow runs on master” step to
the job-level if condition, preventing the job from starting for other refs.
Update the checkout action to explicitly target refs/heads/master, and remove
the shell-based github.ref_name interpolation and late branch guard.
Source: Linters/SAST tools
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2753 +/- ##
==========================================
- Coverage 99.16% 99.15% -0.01%
==========================================
Files 1189 1189
Lines 24973 24979 +6
==========================================
+ Hits 24764 24768 +4
- Misses 209 211 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Require the RELEASE_PAT secret instead of silently falling back to GITHUB_TOKEN, which would create a tag that never triggers the release build - Add a concurrency group so two dispatches cannot bump from the same tip - Checkout the current tip of master rather than the dispatch-time commit - Push the commit and the tag atomically - Pass refs and inputs through env vars instead of interpolating them in shell Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NpWWjywQsozhFp7pgsz1Cy
Deploying gladys-plus with
|
| Latest commit: |
a25fc84
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://24f4d05f.gladys-plus.pages.dev |
| Branch Preview URL: | https://claude-github-action-release.gladys-plus.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/create-release-tag.yml:
- Around line 46-55: Update the checkout step in the release workflow to use
github.token for its token and set persist-credentials to false. Remove
RELEASE_PAT from actions/checkout, then pass it only to the final atomic git
push via a one-shot http.extraheader.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 108f6938-19a5-4a20-82b1-a3de0f950ffe
📒 Files selected for processing (1)
.github/workflows/create-release-tag.yml
Checkout now runs with the default GITHUB_TOKEN and persist-credentials disabled. RELEASE_PAT is only passed to the final push, through a one-shot masked authentication header. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NpWWjywQsozhFp7pgsz1Cy
There was a problem hiding this comment.
Stale comment
Re-review: ready to merge
Hard blockers from the previous pass are addressed in
7e13fcf/f35e27a:
RELEASE_PATis required — early fail if the secret is empty; noGITHUB_TOKENfallback, so tag pushes can actually triggerdocker-release-build.yml- Concurrency (
create-release-tag,cancel-in-progress: false) serializes overlapping dispatches- Checkout tip of
masterwithpersist-credentials: false, PAT only on the final atomic push via one-shothttp.extraheader- Atomic push of the version commit +
v*.*.*tagThis matches the existing manual release pattern (root
package.json/ lockfile bump, bare-semver commit,v-prefixed tag → production image pipeline). No Gladys runtime / device-taxonomy changes; notrisk:high/ notneeds:human-review.Ops reminder (not a merge blocker): ensure
RELEASE_PATcan push to protectedmasterand create tags. An optional GitHub Environment with required reviewers remains a nice hardening if you want a second human checkpoint before shipping production images.Sent by Cursor Automation: Automatic PR review
A tag pushed with the default GITHUB_TOKEN does not start the workflows listening on `push: tags`, which is why a PAT was required. workflow_dispatch is one of the two events GitHub does start from a GITHUB_TOKEN, so the release workflows are now dispatched explicitly on the new tag instead. - Drop the RELEASE_PAT secret entirely - Add workflow_dispatch to the production image and demo website workflows - Only publish production images from a release tag, never from a branch a manual dispatch could have been started on Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NpWWjywQsozhFp7pgsz1Cy
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/docker-release-build.yml:
- Around line 127-129: Update the Docker publish condition around the docker job
to require the prerelease validation job and an exact supported release-tag
format, rather than only the refs/tags/v prefix. Allow production publishing
only for vMAJOR.MINOR.PATCH tags, while permitting prerelease jobs to publish
supported forms such as vMAJOR.MINOR.PATCH-next.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: bb2bb359-33ce-462a-b8dc-81ab7f5fec7b
📒 Files selected for processing (3)
.github/workflows/build-demo-website.yml.github/workflows/create-release-tag.yml.github/workflows/docker-release-build.yml
| # Production images are only published from a release tag, never from a | ||
| # branch a manual dispatch could have been started on. | ||
| if: startsWith(github.ref, 'refs/tags/v') |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate workflow =="
fd -a 'docker-release-build\.yml$' . || true
echo "== workflow relevant sections =="
if [ -f .github/workflows/docker-release-build.yml ]; then
wc -l .github/workflows/docker-release-build.yml
sed -n '1,220p' .github/workflows/docker-release-build.yml
fi
echo "== occurrences of docker job and ref usage =="
rg -n "name: docker|docker-run|docker release|github\.ref|prerelease|on:|workflow_dispatch|pull_request|push:" .github/workflows/docker-release-build.yml || trueRepository: GladysAssistant/Gladys
Length of output: 7939
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== inspect release workflow context =="
python3 - <<'PY'
from pathlib import Path
p=Path('.github/workflows/docker-release-build.yml')
if not p.exists():
print('missing')
raise SystemExit
lines=p.read_text().splitlines()
for i,l in enumerate(lines,1):
if 'workflow_dispatch' in l or 'push:' in l or 'pull_request:' in l or any(kw in l for kw in ['if:', 'refs/tags', 'docker', 'needs:']):
print(f"{i}: {l}")
PYRepository: GladysAssistant/Gladys
Length of output: 1652
🌐 Web query:
GitHub Actions workflow_dispatch workflow ref input github.ref tags values examples
💡 Result:
In GitHub Actions, the workflow_dispatch event allows you to manually trigger a workflow [1][2]. While you can define custom inputs for this event, the ref (reference) is a distinct parameter used to specify which branch, tag, or commit SHA the workflow should run against [1][3]. Key Concepts regarding Ref and Inputs: 1. The Ref Parameter: The ref is not defined as an input within your YAML workflow file's inputs section [4]. Instead, it is a required parameter provided when triggering the workflow via the GitHub UI, GitHub CLI, or REST API [1][2][3]. - GitHub UI: You select the branch or tag from a dropdown menu after clicking the Run workflow button [2]. - GitHub CLI: You use the --ref flag (e.g., gh workflow run WORKFLOW --ref BRANCH_OR_TAG) [1][2]. - REST API: You include it as a mandatory field in the request body (e.g., "ref": "main") [5][3]. 2. Inputs: You can define up to 25 custom inputs in your workflow YAML file under the on.workflow_dispatch.inputs key [1][4][3]. These inputs are separate from the Git ref [4][3]. Example of triggering via REST API: You must provide the ref as a top-level key in the JSON payload, while custom inputs reside within their own inputs object [3]. curl -L -X POST https://api.github.com/repos/OWNER/REPO/actions/workflows/WORKFLOW_ID/dispatches \ -d '{ "ref": "main", "inputs": { "logLevel": "warning", "tags": "production-release" } }' If you need to pass a tag or branch dynamically as an input, you must define a string input in your YAML (e.g., named target_ref) and manually handle that value within your workflow steps, as the system-level ref parameter used by the trigger mechanism is not automatically mapped to custom input fields [4].
Citations:
- 1: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow
- 2: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow?tool=webui
- 3: https://docs.github.com/en/rest/actions/workflows?apiVersion=2026-03-10
- 4: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 5: https://stackoverflow.com/questions/70151645/how-can-i-trigger-a-workflow-dispatch-from-the-github-api
Require an exact release-tag format before publishing images.
The Docker job runs when workflow_dispatch is invoked with any refs/tags/v* ref because startsWith(github.ref, 'refs/tags/v') only checks the prefix. Gate docker on a prerelease job that validates github.ref against the release tag grammar, such as vMAJOR.MINOR.PATCH, and let prerelease jobs publish only vMAJOR.MINOR.PATCH-next or another supported prerelease form.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/docker-release-build.yml around lines 127 - 129, Update
the Docker publish condition around the docker job to require the prerelease
validation job and an exact supported release-tag format, rather than only the
refs/tags/v prefix. Allow production publishing only for vMAJOR.MINOR.PATCH
tags, while permitting prerelease jobs to publish supported forms such as
vMAJOR.MINOR.PATCH-next.
There was a problem hiding this comment.
Re-review @ a25fc84: approve
The design shift away from a long-lived RELEASE_PAT is a solid improvement. Pushing the version commit + tag with GITHUB_TOKEN, then explicitly gh workflow run … --ref <tag> on the three release workflows, correctly works around GitHub’s “GITHUB_TOKEN pushes do not start push workflows” rule without storing a write PAT.
What looks good:
- Master-only gate, concurrency (
cancel-in-progress: false), tip-of-mastercheckout, atomic push workflow_dispatchadded todocker-release-build.yml/build-demo-website.yml(apidoc already had it)- Production Docker publish gated with
startsWith(github.ref, 'refs/tags/v')so a branch dispatch cannot ship images - Matches existing manual release shape (root
package.json/ lockfile vianpm version, bare-semver commit,v*.*.*tag)
No Gladys runtime / device-constants impact → not risk:high / not needs:human-review. Soft residuals called out inline (demo branch dispatch; confirm GITHUB_TOKEN can push protected master).
Sent by Cursor Automation: Automatic PR review
| on: | ||
| # Dispatched on the new tag by the "Create release tag" workflow: a tag pushed | ||
| # with the default GITHUB_TOKEN does not trigger the `push` event below. | ||
| workflow_dispatch: |
There was a problem hiding this comment.
Soft (parity with Docker): workflow_dispatch here has no tag/ref guard, so anyone with Actions write can publish the demo site from an arbitrary branch via the UI. docker-release-build.yml correctly skips publishing unless github.ref is a refs/tags/v* ref. Apidoc already had the same ungated dispatch before this PR, so this is not a merge blocker — consider mirroring the Docker-style if: on the deploy job if you want demo publishes limited to release tags.
| env: | ||
| NEW_VERSION: ${{ steps.bump.outputs.version }} | ||
| run: | | ||
| git push --atomic origin master "refs/tags/${NEW_VERSION}" |
There was a problem hiding this comment.
Ops reminder (not a merge blocker): this push now uses the default GITHUB_TOKEN (contents: write) instead of a PAT. Confirm branch protection / rulesets allow GitHub Actions to push commits and tags to master; if not, the job fails closed (atomic push), but the workflow will not ship until that is allowed (or an Environment with a bypass actor is configured).
Optional hardening still stands: pin this job to a GitHub Environment with required reviewers so “Create release tag” is not a one-click production ship for every collaborator with write access.


Description
This PR adds a new GitHub Actions workflow that automates the creation of release tags with semantic versioning. The workflow allows maintainers to manually trigger a patch or minor version bump, which automatically:
package.jsonusingnpm versionThe workflow includes proper git configuration, Node.js setup, and provides a summary of the created release in the GitHub Actions job summary.
Checklist
https://claude.ai/code/session_01NpWWjywQsozhFp7pgsz1Cy
Summary by CodeRabbit