fix: separate build and release jobs with proper artifact upload - #137
Conversation
- build job: creates tt-rss.tar.gz and tt-rss.zip - release job: downloads artifacts and uploads to release - Uses --clobber flag for gh release upload - Based on nextcloud-cad-viewer release workflow
✅ Deploy Preview for feeddony ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe release workflow now uses separate build and release jobs. The build job creates and stores tar.gz and zip archives, while the release job validates them, runs semantic-release, and uploads them to the tagged GitHub release. ChangesRelease packaging pipeline
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Up to standards ✅🟢 Issues
|
|
Queued — the merge queue status continues in this comment ↓. |
PR Summary by QodoFix release workflow by splitting build/release jobs and uploading artifacts
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review ✅ ApprovedSeparates the build and release workflow jobs to reliably upload release assets and adds --ignore-scripts to npm ci for improved security. No issues found. OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Important Your trial ends in 6 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
|
Merge Queue Status
This pull request spent 22 seconds in the queue, including 2 seconds running CI. Required conditions to merge |
Code Review by Qodo
Context used✅ Compliance rules (platform):
11 rules 1. Archives bundle node_modules
|
| - name: Install Dependencies | ||
| run: npm ci --ignore-scripts | ||
|
|
||
| - name: Ensure zip available | ||
| run: | | ||
| if ! command -v zip >/dev/null 2>&1; then | ||
| sudo apt-get update && sudo apt-get install -y zip | ||
| fi | ||
|
|
||
| - name: Create tar.gz | ||
| run: tar --exclude='.git' --exclude='.github' -czf tt-rss.tar.gz . | ||
|
|
||
| - name: Create zip | ||
| run: zip -r tt-rss.zip . -x '.git/*' -x '.github/*' |
There was a problem hiding this comment.
1. Archives bundle node_modules 🐞 Bug ≡ Correctness
The build job runs npm ci and then archives . while excluding only .git/.github, so the generated node_modules/ (and other generated files) are bundled into the release assets; additionally the later zip command will include the already-created tt-rss.tar.gz inside tt-rss.zip. This bloats assets and ships unintended dependencies/content, increasing the chance of artifact/release upload failures and confusing release contents.
Agent Prompt
## Issue description
The build job archives the entire workspace after `npm ci`, so `node_modules/` and other generated files end up inside `tt-rss.tar.gz`/`tt-rss.zip`; also `tt-rss.zip` will include `tt-rss.tar.gz` because it is created first and not excluded.
## Issue Context
- `npm ci` creates `node_modules/`.
- `.gitignore` indicates `node_modules/` and `dist/` are not intended to be committed/distributed.
## Fix Focus Areas
- .github/workflows/release.yml[29-42]
## Suggested fix
- Exclude `node_modules/` (and other build outputs) in both tar and zip steps, e.g.:
- tar: add `--exclude='node_modules' --exclude='dist' --exclude='tt-rss.tar.gz' --exclude='tt-rss.zip'`
- zip: add `-x 'node_modules/*' -x 'dist/*' -x 'tt-rss.tar.gz' -x 'tt-rss.zip'`
- Alternatively, build/package from a clean staging directory containing only the files intended for release (copy/rsync with an allowlist), then archive that directory.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| - name: Upload artifacts to release | ||
| run: | | ||
| gh release upload ${{ steps.version.outputs.VERSION }} \ | ||
| tt-rss.tar.gz \ | ||
| tt-rss.zip \ | ||
| --repo ${{ github.repository }} | ||
| TAG=$(git describe --tags --abbrev=0) | ||
| echo "Uploading release assets for: $TAG" | ||
| gh release upload "$TAG" tt-rss.tar.gz --clobber | ||
| gh release upload "$TAG" tt-rss.zip --clobber | ||
| echo "=== Uploaded ===" | ||
| gh release view "$TAG" --json assets |
There was a problem hiding this comment.
2. Clobbers existing release assets 🐞 Bug ≡ Correctness
The workflow always runs gh release upload ... --clobber using `TAG=$(git describe --tags --abbrev=0)`; if semantic-release does not create a new release (e.g., rerun/workflow_dispatch on an already-released commit), this can target an existing tag and overwrite that release’s assets. This can silently mutate previously published artifacts for an existing version.
Agent Prompt
## Issue description
The upload step is unconditional and uses `--clobber` against the tag resolved via `git describe`. When semantic-release decides there is no new release to publish, the job can still overwrite assets on the latest existing release.
## Issue Context
The previous workflow gated asset creation/upload on a semantic-release output (`release_created == 'true'`). The new workflow removed that gating but kept `--clobber`.
## Fix Focus Areas
- .github/workflows/release.yml[87-103]
## Suggested fix
- Restore an explicit “new release created” gate before uploading assets. Options:
1) Capture the tag *before* and *after* semantic-release and only upload if it changed:
- `BEFORE=$(git describe --tags --abbrev=0 2>/dev/null || true)`
- run semantic-release
- `git fetch --tags`
- `AFTER=$(git describe --tags --abbrev=0 2>/dev/null || true)`
- if `AFTER` is empty or `AFTER == BEFORE`, skip upload.
2) Use a semantic-release plugin/hook (e.g., exec) to write `nextRelease.version` to a file or `$GITHUB_OUTPUT`, then upload only when that output is present.
- If overwriting is not desired, remove `--clobber` and fail when assets already exist.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| TAG=$(git describe --tags --abbrev=0) | ||
| echo "Uploading release assets for: $TAG" |
There was a problem hiding this comment.
3. Tag lookup may fail 🐞 Bug ☼ Reliability
The upload step relies on git describe --tags --abbrev=0, but the workflow checkout does not fetch full history/tags; if tags are absent in the local clone, git describe will fail and the release job will error out. This makes release asset uploads unreliable.
Agent Prompt
## Issue description
`git describe --tags --abbrev=0` requires tags to be present locally. The workflow currently performs a default checkout and then immediately relies on tags for TAG resolution.
## Issue Context
This repository already uses `fetch-depth: 0` in other workflows when it needs full git context.
## Fix Focus Areas
- .github/workflows/release.yml[64-66]
- .github/workflows/release.yml[96-101]
## Suggested fix
- Update `actions/checkout` in the release job to ensure tags are available, e.g.:
- `with: fetch-depth: 0`
- (optionally) `fetch-tags: true` if supported by the pinned checkout version
- Or add an explicit fetch before calling `git describe`:
- `git fetch --force --tags`
- Preferably, avoid `git describe` entirely and use an explicit version/tag output from semantic-release (and skip upload when none was created).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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/release.yml:
- Around line 16-19: Add an explicit minimal permissions block to the release
workflow’s build job, scoped to the build steps that check out code and upload
the transient artifact. Grant only the read access required for checkout, such
as contents read, and leave all other GITHUB_TOKEN permissions disabled.
- Around line 38-42: Update the “Create tar.gz” and “Create zip” steps to
exclude node_modules from both archives and exclude the generated tt-rss.tar.gz
from the zip archive. Also verify the release workflow’s packaging sequence and
add the frontend build using the package.json build script before creating
either archive if the release requires built frontend assets.
- Around line 20-21: Update both actions/checkout steps in
.github/workflows/release.yml at lines 20-21 and 64-65 to set
persist-credentials to false, while leaving the existing checkout configuration
and release token usage unchanged.
- Around line 96-105: Replace the manual “Upload artifacts to release” step’s
git describe and gh release upload logic with the native assets configuration on
the `@semantic-release/github` plugin. Configure both tt-rss.tar.gz and tt-rss.zip
as release assets so semantic-release uploads them to the release it creates,
and remove the redundant tag lookup and upload commands.
- Around line 55-62: Update the release job’s permissions block to retain
contents: write and add issues: write plus pull-requests: write, enabling
semantic-release GitHub success comments on resolved issues and pull requests.
- Around line 64-65: Update the actions/checkout step in the release job to
fetch the full repository history by configuring fetch-depth to 0. Keep the
existing pinned actions/checkout reference and checkout behavior unchanged.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b5a0341a-f981-46a1-82f9-4621dc59baf2
📒 Files selected for processing (1)
.github/workflows/release.yml
| build: | ||
| name: Build Assets | ||
| runs-on: ubuntu-latest | ||
| steps: |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Build job has no explicit permissions: block.
The job inherits default (potentially broad) GITHUB_TOKEN permissions even though it only checks out code and uploads a transient artifact — it doesn't need write access to anything. Add a minimal explicit block.
🔒 Proposed fix
build:
name: Build Assets
runs-on: ubuntu-latest
+ permissions:
+ contents: read
steps:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| build: | |
| name: Build Assets | |
| runs-on: ubuntu-latest | |
| steps: | |
| build: | |
| name: Build Assets | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 16-53: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
🤖 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/release.yml around lines 16 - 19, Add an explicit minimal
permissions block to the release workflow’s build job, scoped to the build steps
that check out code and upload the transient artifact. Grant only the read
access required for checkout, such as contents read, and leave all other
GITHUB_TOKEN permissions disabled.
Source: Linters/SAST tools
| - name: Checkout | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate file and workflow excerpt =="
if [ -f .github/workflows/release.yml ]; then
nl -ba .github/workflows/release.yml | sed -n '1,110p'
else
echo "missing .github/workflows/release.yml"
fi
echo
echo "== search for persist-credentials and semantic-release usage =="
rg -n "actions/checkout|persist-credentials|semantic-release|`@semantic-release/github`|git push|npm ci|semantic-release" .github/workflows/release.yml . . -g '!node_modules' -g '!dist' -g '!build' || true
echo
echo "== package metadata relevant to semantic-release =="
for f in package.json package-lock.json pnpm-lock.yaml yarn.lock; do
if [ -f "$f" ]; then
echo "--- $f ---"
rg -n '"`@semantic-release/`[^"]+"|`@semantic-release/github`|semantic-release|npm-ci|prepare|prepublish|postpublish|release:' "$f" || true
fi
doneRepository: ashcoft/tt-rss-non-dockerize
Length of output: 245
🌐 Web query:
actions/checkout v4 persist-credentials default true README
💡 Result:
In actions/checkout v4, the persist-credentials input defaults to true [1][2]. When set to true (the default), the action configures the GITHUB_TOKEN or SSH key into the local Git configuration [3][4]. This allows subsequent steps in the same job to execute authenticated Git commands [3]. The credentials are removed during the post-job cleanup process [3]. If you wish to prevent this behavior, you must explicitly set persist-credentials: false in your workflow step configuration [3]. While there have been community discussions and long-standing requests to change this default to false for security hardening, the default has remained true through version 4 [5][6][7]. Note: In later versions (e.g., v6), while the default remains true, the mechanism for storing credentials was updated to use $RUNNER_TEMP rather than the local .git/config file to enhance security [4][8].
Citations:
- 1: https://github.com/actions/checkout/blob/v4/action.yml
- 2: https://github.com/actions/checkout/blob/v4.1.1/action.yml
- 3: https://github.com/actions/checkout/blob/v4/README.md
- 4: https://github.com/actions/checkout/tree/v6.0.0
- 5: [security] Escalate concerning default
persist-credentials=trueplease actions/checkout#2312 - 6: Change the default value of persist-credentials to false actions/checkout#1687
- 7: Remove
persist-credentialsor change the default tofalseactions/checkout#485 - 8: actions/checkout@v5.0.1...v6.0.0
🌐 Web query:
@semantic-release/github publish API based GitHub releases git push persisted token
💡 Result:
The @semantic-release/github plugin primarily uses the GitHub REST API to publish releases, not standard git push commands for the release itself [1][2]. Authentication for this API is managed via the GH_TOKEN or GITHUB_TOKEN environment variable [1][3]. Regarding your query on "git push" and "persisted tokens": 1. Git Push vs. API: While the @semantic-release/github plugin uses the GitHub API for releases, other parts of the semantic-release ecosystem, particularly the @semantic-release/git plugin (used for committing generated files back to the repository), do use the git CLI and therefore perform git push operations [4][5]. 2. Persisted Tokens in GitHub Actions: In GitHub Actions, the default actions/checkout step automatically configures the git CLI with the provided GITHUB_TOKEN, which is then persisted in the local git config [4]. This can lead to authentication conflicts if you are attempting to use a different token for specific plugins, or if the default token lacks sufficient permissions for certain operations (like pushing to protected branches) [4][6]. 3. Recommended Mitigation: To prevent the CI environment from defaulting to an unwanted persisted token, you should explicitly set persist-credentials: false in your workflow's checkout step [4][6]. This prevents actions/checkout from writing the token to the git config, forcing you to rely on explicit environment variables (like GH_TOKEN) for authentication when performing git operations [4][6]. In summary, ensure that for any plugin requiring git-level access (like @semantic-release/git), you have disabled credential persistence in your checkout step if you are providing a separate authentication token, and ensure the token used has the necessary permissions (e.g., contents: write) [1][4][6].
Citations:
- 1: https://github.com/semantic-release/github
- 2: https://www.npmjs.com/package/@semantic-release/github
- 3: https://semantic-release.org/usage/ci-configuration/
- 4: semantic-release(/git) not using GH_TOKEN semantic-release/git#196
- 5: https://semantic-release.gitbook.io/semantic-release/recipes/ci-configurations/github-actions
- 6: https://zenn.dev/wakamsha/articles/semantic-release-and-protected-branches?locale=en
🌐 Web query:
github.com @semantic-release/github v23 v24 published releases use GitHub API no git push
💡 Result:
The @semantic-release/github plugin continues to use the GitHub API to manage releases rather than relying on git push for release creation [1][2]. Regarding the specific versions and changes: 1. Plugin Functionality: The plugin's core mechanism for publishing releases remains interacting with the GitHub API [1][2]. It does not use git push to create releases. 2. Versioning Context: You referenced v23 and v24, which correspond to versions of the semantic-release core, not the @semantic-release/github plugin itself. As of October 2025, the @semantic-release/github plugin released version 12.0.0, which includes a breaking change: the removal of GitHub Search API consumption [3][4]. 3. Minimum Requirements: As of this update, the plugin requires a minimum of Node.js v22.14 and a minimum semantic-release core version of v24.1.0 [3][4][5]. The plugin still requires a GitHub token (GH_TOKEN or GITHUB_TOKEN) with appropriate permissions to authenticate with the GitHub API for publishing releases and performing related actions (such as commenting on issues or PRs) [2][6].
Citations:
- 1: https://www.npmjs.com/package/@semantic-release/github
- 2: https://github.com/semantic-release/github
- 3: https://github.com/semantic-release/github/releases
- 4: https://github.com/semantic-release/github/releases/tag/v12.0.0
- 5: https://npmx.dev/package-changelog/@semantic-release/github/v/12.0.8
- 6: https://registry.npmjs.org/@semantic-release/github
🌐 Web query:
github.com semantic-release/release-notes-generator use @semantic-release/github releaseName releaseNotes GitPushes commits?
💡 Result:
The @semantic-release/release-notes-generator plugin does not directly use releaseName, push commits to Git, or interact with @semantic-release/github. Instead, it serves a specific role within the semantic-release pipeline: 1. Function: The sole purpose of @semantic-release/release-notes-generator is to generate release notes by parsing commit messages since the last release [1][2][3]. It utilizes the conventional-changelog library for this task [1][2]. 2. Relationship with other plugins: - Pipeline Orchestration: In a typical semantic-release configuration, plugins are executed in a specific sequence [4][5]. The release notes generated by @semantic-release/release-notes-generator are passed to other plugins later in the pipeline that need them (such as @semantic-release/github for release descriptions or @semantic-release/git for commit messages) [4][5][6]. - @semantic-release/github: This plugin is responsible for creating releases on GitHub [6]. It may use the notes generated by the release-notes-generator to populate the release body. Options like releaseName are configured specifically within the @semantic-release/github plugin configuration, not the generator [7][8]. - Git Pushes: The @semantic-release/release-notes-generator does not perform Git operations. Pushing commits, tags, or release artifacts to a Git repository is the responsibility of plugins like @semantic-release/git or other publishing plugins [4][5][6]. In summary, the release-notes-generator only produces text; it does not control release names, execute Git pushes, or manage the GitHub API interactions [1][2][4].
Citations:
- 1: https://github.com/semantic-release/release-notes-generator
- 2: https://www.npmjs.com/package/@semantic-release/release-notes-generator
- 3: https://github.com/semantic-release/release-notes-generator-v3
- 4: https://github.com/semantic-release/semantic-release/blob/HEAD/docs/usage/plugins.md
- 5: https://semantic-release.gitbook.io/semantic-release/usage/plugins.md
- 6: https://blog.devops.dev/semantic-release-automates-release-workflow-with-github-actions-ab09f1f4041f
- 7: https://github.com/LippyyDev/Agate-Antigravity-Helper-/blob/main/release.config.cjs
- 8: https://jianmiau.ddns.net/CocosPlugin/esengine/compare/v2.2.1..mergify/esengine/config-update
Disable credential persistence in checkout steps that do not perform authenticated Git commands.
actions/checkout keeps the GitHub token in the local Git config by default (persist-credentials: true). Set persist-credentials: false in both checkout steps; the release job can still use tokens via environment variables/API plugins without keeping them persisted on disk.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 20-21: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
📍 Affects 1 file
.github/workflows/release.yml#L20-L21(this comment).github/workflows/release.yml#L64-L65
🤖 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/release.yml around lines 20 - 21, Update both
actions/checkout steps in .github/workflows/release.yml at lines 20-21 and 64-65
to set persist-credentials to false, while leaving the existing checkout
configuration and release token usage unchanged.
Source: Linters/SAST tools
| - name: Create tar.gz | ||
| run: tar --exclude='.git' --exclude='.github' -czf tt-rss.tar.gz . | ||
|
|
||
| - name: Create zip | ||
| run: zip -r tt-rss.zip . -x '.git/*' -x '.github/*' |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow release.yml =="
if [ -f .github/workflows/release.yml ]; then
cat -n .github/workflows/release.yml
else
echo "missing"
fi
echo
echo "== package files =="
for f in package.json package-lock.json yarn.lock pnpm-lock.yaml; do
if [ -f "$f" ]; then
echo "--- $f ---"
if [ "$f" = "package.json" ]; then
cat -n "$f"
else
sed -n '1,120p' "$f"
fi
fi
done
echo
echo "== workspace file list relevant =="
git ls-files | sed -n '1,200p'
echo
echo "== zip/tar exclusion behavior probe =="
python3 - <<'PY'
import os, tarfile, io, subprocess, tempfile, shutil
with tempfile.TemporaryDirectory() as d:
os.makedirs(os.path.join(d, "node_modules"))
with open(os.path.join(d, "node_modules", "x.js"), "w") as f:
f.write("x=1")
with open(os.path.join(d, ".gitignore"), "w") as f:
f.write("ignored")
p = subprocess.run(
["bash", "-c", "tar --exclude=.git --exclude=.github -czf tt-rss.tar.gz . && zip -r tt-rss.zip . -x '.git/*' -x '.github/*'"],
cwd=d, capture_output=True, text=True
)
print("zip/tar exit codes:", p.returncode, "--")
print("zip stdout:", p.stdout)
print("zip stderr:", p.stderr)
print("files:", sorted(os.listdir(d)))
with tarfile.open(os.path.join(d, "tt-rss.tar.gz")) as tf:
print("tar members:")
for m in tf.getmembers():
print(" ", m.name)
with zipimport.ZipFile(os.path.join(d, "tt-rss.zip")) as zf:
print("zip members:")
for n in sorted(zf.namelist()):
print(" ", n)
PYRepository: ashcoft/tt-rss-non-dockerize
Length of output: 19275
Exclude the tarball and node_modules from both release archives.
The zip command runs after creating tt-rss.tar.gz and excludes only .git/* and .github/*, so the tarball gets uploaded inside the zip. Both archives also include the node_modules directory installed by npm ci, adding unnecessary release artifact size. Add --exclude='node_modules' to the tar step and -x 'node_modules/*' -x 'tt-rss.tar.gz' to the zip step.
Also confirm whether the release should run a frontend build before packaging: this workflow only runs npm ci --ignore-scripts, while package.json defines npm run build via Vite.
🤖 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/release.yml around lines 38 - 42, Update the “Create
tar.gz” and “Create zip” steps to exclude node_modules from both archives and
exclude the generated tt-rss.tar.gz from the zip archive. Also verify the
release workflow’s packaging sequence and add the frontend build using the
package.json build script before creating either archive if the release requires
built frontend assets.
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| needs: build | ||
| if: github.repository_owner == 'ashcoft' | ||
| permissions: | ||
| contents: write | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
git ls-files | rg '(^\.github/workflows/release\.yml$|releaserc|package\.json|README|semantic-release)' || true
echo
echo "== release workflow relevant lines =="
if [ -f .github/workflows/release.yml ]; then
nl -ba .github/workflows/release.yml | sed -n '1,140p'
fi
echo
echo "== releaserc release branches/plugins =="
if [ -f .releaserc.json ]; then
nl -ba .releaserc.json | sed -n '1,220p'
fi
echo
echo "== semantic release config searches =="
rg -n "`@semantic-release/github`|issues|pullRequest|githubRepo|Branches|branches" . -S --glob '!node_modules' --glob '!dist' --glob '!build' || trueRepository: ashcoft/tt-rss-non-dockerize
Length of output: 1377
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== release workflow =="
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/release.yml | sed -n '1,140p'
echo
echo "== .releaserc.json =="
awk '{printf "%6d\t%s\n", NR, $0}' .releaserc.json | sed -n '1,220p'
echo
echo "== all workflow permissions/greeting/comment configuration =="
rg -n "permissions:|contents:|issues:|pull-requests|`@semantic-release/github`|githubRepo|branches|comments|issue|pull" .github .releaserc.json package.json README.md -S --glob '!node_modules' --glob '!dist' --glob '!build' || trueRepository: ashcoft/tt-rss-non-dockerize
Length of output: 10354
🌐 Web query:
semantic-release @semantic-release/github default behavior addChannels comments issues pull-requests permissions
💡 Result:
The @semantic-release/github plugin manages GitHub release artifacts, issue/pull-request comments, and release channels through specific lifecycle steps. Lifecycle Steps and Behavior: 1. addChannel: This step updates the pre-release status of a GitHub release [1][2]. It is responsible for associating the release with a specific distribution channel (e.g., updating a GitHub release's pre-release field) [1][3]. 2. success: This step executes after a successful release to add comments to GitHub issues and pull requests resolved by the release [1][2]. It also closes issues previously opened by the fail step [1][3]. 3. fail: This step opens or updates a GitHub issue with information about the errors that caused a release failure [1][2]. Permissions Required: When using the GITHUB_TOKEN in GitHub Actions, the plugin requires the following minimum permissions to function correctly [1][4][5]: - contents: write: Necessary to publish the GitHub release [1][4]. - issues: write: Necessary to add comments to resolved issues [1][4]. - pull-requests: write: Necessary to add comments to resolved pull requests [4][5]. Configuration for Comments: The behavior of adding comments can be customized using the successComment option [1][2]. - To disable all comments: Set successComment to false [1][6]. - To control where comments are posted: You can use templates or conditional logic within the successComment setting [2][6]. For example, to only comment on issues, you can use: "<% return!issue.pull_request; %>" [6]. To only comment on pull requests, you can use: "<% return issue.pull_request; %>" [6]. The plugin is included in the default semantic-release configuration [7][8]. If you override the plugins list in your configuration, you must explicitly include @semantic-release/github if you wish to retain this functionality [9].
Citations:
- 1: https://www.npmjs.com/package/@semantic-release/github
- 2: https://github.com/semantic-release/github
- 3: https://npmx.dev/package/@semantic-release/github/v/12.0.8
- 4: fix(ci): grant pull-requests: write so release success step can comment on PRs adobe/skills#145
- 5: https://semantic-release.org/recipes/ci-configurations/github-actions/
- 6: https://registry.npmjs.org/@semantic-release/github
- 7: https://github.com/semantic-release/semantic-release/blob/master/docs/recipes/release-workflow/distribution-channels.md
- 8: https://github.com/semantic-release/semantic-release/blob/HEAD/docs/usage/configuration.md
- 9: https://github.com/semantic-release/semantic-release/blob/HEAD/docs/usage/plugins.md
Grant release permissions for GitHub release comments.
.releaserc.json enables @semantic-release/github with only addChannels, so its success step can still comment on resolved issues/PRs and needs issues: write and pull-requests: write in addition to contents: write.
🤖 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/release.yml around lines 55 - 62, Update the release job’s
permissions block to retain contents: write and add issues: write plus
pull-requests: write, enabling semantic-release GitHub success comments on
resolved issues and pull requests.
| - name: Checkout | ||
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.2.2 | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files =="
git ls-files | sed -n '1,120p'
echo
echo "== workflow excerpt =="
if [ -f .github/workflows/release.yml ]; then
cat -n .github/workflows/release.yml | sed -n '1,140p'
else
echo "missing .github/workflows/release.yml"
fi
echo
echo "== semantic-release config files =="
git ls-files | rg '(^|/)(package\.json|\.releaserc(\..*)?|release\.config\.(js|ts|mjs|cjs)|semantic-release|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$' || true
echo
echo "== semantic-release references =="
rg -n "semantic-release|fetch-depth|git describe|tagMode|branches|plugins" .github package.json release.config.* .releaserc* . 2>/dev/null | head -200 || trueRepository: ashcoft/tt-rss-non-dockerize
Length of output: 23017
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== release config =="
cat -n .releaserc.json
echo
echo "== package semantic-release deps =="
node - <<'JS'
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json','utf8'));
for (const section of ['dependencies','devDependencies']) {
if (pkg[section]) {
for (const [name, version] of Object.entries(pkg[section])) {
if (name.includes('semantic-release') || name.includes('`@semantic-release`')) {
console.log(`${section}.${name}=${version}`);
}
}
}
}
JS
echo
echo "== local checkout workflow examples with fetch-depth =="
rg -n "fetch-depth|actions/checkout|semantic-release|git describe" .github/workflows -C 3 || trueRepository: ashcoft/tt-rss-non-dockerize
Length of output: 10001
🌐 Web query:
semantic-release GitHub actions checkout fetch-depth 0 CI setup
💡 Result:
To use semantic-release effectively with GitHub Actions, setting fetch-depth: 0 is required in the actions/checkout step [1][2]. By default, GitHub Actions' actions/checkout performs a shallow clone (fetch-depth: 1) [2][3], which fetches only the most recent commit [2][4]. Semantic-release requires the full Git history and tags to function correctly [2][3]. Specifically, it needs this history to: 1. Analyze all commits since the last release to determine the correct version bump (major, minor, or patch) based on conventional commits [2]. 2. Generate accurate release notes by reviewing the commit history [2]. 3. Identify the last release tag to calculate the delta for the next version [2]. Without the full history, semantic-release may fail to identify the correct version, skip releases, or generate incomplete changelogs [2]. Recommended GitHub Actions configuration: - uses: actions/checkout@v4 with: fetch-depth: 0 fetch-tags: true # Recommended for reliable tag access [3][5] If you encounter issues with credentials when using a custom token, you may also need to set persist-credentials to false [6]: - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false
Citations:
- 1: https://semantic-release.org/recipes/ci-configurations/github-actions/
- 2: semantic-release requires fetch-depth: 0 peerigon/template-public-package#2
- 3: https://deadends.dev/cicd/gha-shallow-clone-missing-history/
- 4: RFC:
fetch-depth: 1and not cloning tags are dangerous defaults actions/checkout#217 - 5: https://github.com/mortezamasumi/test-gh-action/blob/25dab7e1238ed1ead09da62257923622c073688e/.github/workflows/release.yml
- 6: https://semantic-release.gitbook.io/semantic-release/recipes/ci-configurations/github-actions
🌐 Web query:
github actions checkout fetch-tags default true v4 fetch-depth
💡 Result:
In the actions/checkout v4 action, the fetch-tags input defaults to false [1][2]. The fetch-depth input defaults to 1 [1][2]. When fetch-depth is set to the default of 1, only a single commit is fetched for the specific reference (SHA) that triggered the workflow [1][3]. Setting fetch-tags to true is intended to allow fetching tags even when fetch-depth is greater than 0, but users have reported that this does not always behave as expected or fetch all available tags in certain configurations [4][5][6]. To ensure all tags and the complete commit history are fetched, it is standard practice to set fetch-depth to 0 [1][7].
Citations:
- 1: https://github.com/actions/checkout/blob/v4/README.md
- 2: https://github.com/actions/checkout/blob/v4/action.yml
- 3: https://github.com/actions/checkout?tab=readme-ov-file
- 4: fetch-tags is not working according to the docs with v4 actions/checkout#1781
- 5: fetch-tags: true doesn't actually fetch any tags actions/checkout#1471
- 6: fetch-tags is not working according to the docs with v4 actions/checkout#1781
- 7: https://github.com/actions/checkout
Use full Git history for the release checkout.
actions/checkout defaults to fetch-depth: 1, so the release job only has the triggering commit and not the tags/previous release history that semantic-release and the later git describe --tags --abbrev=0 need.
🔧 Proposed fix
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ fetch-depth: 0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.2.2 | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 64-65: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 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/release.yml around lines 64 - 65, Update the
actions/checkout step in the release job to fetch the full repository history by
configuring fetch-depth to 0. Keep the existing pinned actions/checkout
reference and checkout behavior unchanged.
| - name: Upload artifacts to release | ||
| run: | | ||
| gh release upload ${{ steps.version.outputs.VERSION }} \ | ||
| tt-rss.tar.gz \ | ||
| tt-rss.zip \ | ||
| --repo ${{ github.repository }} | ||
| TAG=$(git describe --tags --abbrev=0) | ||
| echo "Uploading release assets for: $TAG" | ||
| gh release upload "$TAG" tt-rss.tar.gz --clobber | ||
| gh release upload "$TAG" tt-rss.zip --clobber | ||
| echo "=== Uploaded ===" | ||
| gh release view "$TAG" --json assets | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow outline =="
sed -n '1,140p' .github/workflows/release.yml
echo
echo "== releaserc =="
cat .releaserc.json
echo
fd -a '.releaserc.*|release\.yml' .
echo
echo "== package config/release deps =="
if [ -f package.json ]; then
jq '.devDependencies, .dependencies, .scripts' package.json
fi
echo
echo "== git status diff stats =="
git status --short
git diff --stat -- .github/workflows/release.yml .releaserc.json || trueRepository: ashcoft/tt-rss-non-dockerize
Length of output: 6207
🌐 Web query:
@semantic-release/github publish plugin GitHub Release API releases/tags create local git tag push
💡 Result:
The @semantic-release/github plugin is responsible for publishing a release to the GitHub Releases page, not for creating or pushing local git tags [1][2][3]. In the standard semantic-release workflow, the responsibility for managing Git tags and commits is as follows: 1. Core Workflow (Tagging): The semantic-release core automatically creates a Git tag locally for the new release version [3]. This tag identifies the commit associated with that specific version [4][3]. 2. Git Plugin (Pushing Tags/Commits): The @semantic-release/git plugin is typically used in conjunction with the other plugins to handle the pushing of these locally created tags and any automated changes (such as updated package.json files or changelogs) back to your remote Git repository [5][6][7]. Without this plugin, semantic-release may create a tag in your local CI environment, but that tag will not be automatically pushed to the remote repository [4]. To summarize, if you want your release process to include creating and pushing a Git tag to your remote repository, you should include the @semantic-release/git plugin in your configuration [5][6]. The @semantic-release/github plugin focuses exclusively on interacting with the GitHub Releases API to create the release entity on GitHub itself [1][2][8].
Citations:
- 1: https://github.com/semantic-release/github
- 2: https://www.npmjs.com/package/@semantic-release/github
- 3: https://github.com/semantic-release/semantic-release
- 4: How to create the tag after `semantic-release`'s changes to package.json and changelog have been committed semantic-release/semantic-release#2202
- 5: https://github.com/semantic-release/semantic-release/blob/HEAD/docs/usage/plugins.md
- 6: https://semantic-release.gitbook.io/semantic-release/support/faq
- 7: https://github.com/semantic-release/semantic-release/blob/6b5b02ea755b74e1c2ea9a2dfff6576f5f15e870/docs/recipes/github-actions.md
- 8: https://registry.npmjs.org/@semantic-release/github
🌐 Web query:
actions/checkout default fetch depth shallow fetch tags false
💡 Result:
In the actions/checkout GitHub Action, the default behavior for shallow fetching and tag fetching is as follows: - Default fetch-depth: The default value for fetch-depth is 1 [1][2]. This means the action performs a shallow clone, fetching only a single commit for the specific ref or SHA that triggered the workflow [1][3]. To fetch all history (including all branches and tags), you must explicitly set fetch-depth to 0 [1][4]. - Default fetch-tags: The default value for fetch-tags is false [1][2]. When set to false, the action does not fetch tags during the initial clone/fetch, even if the fetch-depth is greater than 1 [2][5]. Note that while setting fetch-depth: 0 ensures all history and tags are fetched, some users have reported complexities when attempting to use fetch-tags: true in combination with shallow clones (fetch-depth > 0), as specific Git configurations or repository states may sometimes require fetch-depth: 0 to ensure all tags are properly accessible for commands like git describe [6][7].
Citations:
- 1: https://github.com/actions/checkout?tab=readme-ov-file
- 2: https://github.com/actions/checkout/blob/cbb722410c2e876e24abbe8de2cc27693e501dcb/action.yml
- 3: https://github.com/actions/checkout/blob/main/README.md
- 4: https://github.com/actions/checkout
- 5: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 6: fetch-tags: true doesn't actually fetch any tags actions/checkout#1471
- 7: fetch-tags is not working according to the docs with v4 actions/checkout#1781
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== release.yml checkout inputs =="
rg -n "uses: actions/checkout|fetch-depth|fetch-tags|persist-credentials" .github/workflows/release.yml
echo
echo "== root config files that might affect semantic-release =="
fd -a '^(package\.json|\.releaserc.*|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$' . | sed 's#^\./##' | sortRepository: ashcoft/tt-rss-non-dockerize
Length of output: 757
Use semantic-release’s native asset upload instead of git describe.
actions/checkout does a shallow checkout with tags fetched separately, and @semantic-release/github creates the GitHub Release tag via the Releases API rather than pushing a local tag. This makes git describe --tags --abbrev=0 unreliable: it can miss the newly published tag (or resolve to an old one), so assets may be uploaded to the wrong release or the job can fail. Let @semantic-release/github upload the assets atomically by adding the assets option instead of looking up the tag in the following step.
🤖 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/release.yml around lines 96 - 105, Replace the manual
“Upload artifacts to release” step’s git describe and gh release upload logic
with the native assets configuration on the `@semantic-release/github` plugin.
Configure both tt-rss.tar.gz and tt-rss.zip as release assets so
semantic-release uploads them to the release it creates, and remove the
redundant tag lookup and upload commands.



Summary
Fix release workflow to reliably upload assets to releases.
Changes
Based on nextcloud-cad-viewer release workflow
Workflow Structure
Build Job:
npm ci --ignore-scripts)tt-rss.tar.gzandtt-rss.zipRelease Job:
gh release upload --clobberRelease Assets