-
Notifications
You must be signed in to change notification settings - Fork 4
ci: release workflow — tag-triggered per-tool ZIPs on GitHub Releases #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,69 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| name: Release | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Publishes a GitHub Release when a v* tag is pushed (the release process in | ||||||||||||||||||||||||||||||||||||||||||||||||
| # CONTRIBUTING.md): validates every manifest, packages each tool folder as a | ||||||||||||||||||||||||||||||||||||||||||||||||
| # ZIP shaped for chrome://extensions → Load unpacked (the archive contains the | ||||||||||||||||||||||||||||||||||||||||||||||||
| # tool folder itself), and attaches checksums. Uses the preinstalled gh CLI | ||||||||||||||||||||||||||||||||||||||||||||||||
| # instead of a third-party release action. There is no Chrome Web Store | ||||||||||||||||||||||||||||||||||||||||||||||||
| # distribution, and extensions loaded unpacked never auto-update. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||
| tags: ['v*'] | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Default every job to read-only. The release job grants itself write because | ||||||||||||||||||||||||||||||||||||||||||||||||
| # creating a GitHub Release requires it. | ||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||
| release: | ||||||||||||||||||||||||||||||||||||||||||||||||
| name: Package and publish | ||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Pin third-party actions to a full commit SHA, not a tag, and keep the | ||||||||||||||||||||||||||||||||||||||||||||||||
| # version comment for readability (same policy as ci.yml). | ||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Checkout | ||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Set up Node | ||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | ||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||
| node-version-file: ".nvmrc" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Validate manifests | ||||||||||||||||||||||||||||||||||||||||||||||||
| run: node scripts/validate-manifests.mjs | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Package tools | ||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p dist-release | ||||||||||||||||||||||||||||||||||||||||||||||||
| for tool in ghl-*/; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| tool="${tool%/}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| version=$(node -p "require('./${tool}/manifest.json').version") | ||||||||||||||||||||||||||||||||||||||||||||||||
| zip -r -X "dist-release/${tool}-${version}.zip" "${tool}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/release.yml | sed -n '1,75p'
printf '%s\n' '--- generated source and Node evaluation probe ---'
node - <<'JS'
const tool = 'ghl-x\' , console.log("PWNED") , \'safe';
const source = `require('./${tool}/manifest.json').version`;
console.log(source);
const { spawnSync } = require('node:child_process');
const result = spawnSync(process.execPath, ['-p', source], { encoding: 'utf8' });
console.log(JSON.stringify({
status: result.status,
stdout: result.stdout,
executedPayload: result.stdout.includes('PWNED'),
}));
JSRepository: legioncodeinc/ghl-toolset Length of output: 3289 Injection (CWE-95): Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection') Reachability: External Do not interpolate A repository-controlled directory name can execute JavaScript on the release runner. Pass the manifest path through an environment variable and parse it in a fixed Node script. Proposed safe change- version=$(node -p "require('./${tool}/manifest.json').version")
+ manifest_path="./${tool}/manifest.json"
+ version=$(MANIFEST_PATH="$manifest_path" node -e '
+ const fs = require("node:fs");
+ const manifest = JSON.parse(
+ fs.readFileSync(process.env.MANIFEST_PATH, "utf8")
+ );
+ process.stdout.write(manifest.version);
+ ')📝 Committable suggestion
Suggested change
🧰 Tools🪛 actionlint (1.7.12)[error] 40-40: shellcheck reported issue in this script: SC2035:info:8:31: Use ./glob or -- glob so names with dashes won't become options (shellcheck) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| (cd dist-release && sha256sum *.zip > checksums.txt && cat checksums.txt) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Extract release notes | ||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||
| ver="${GITHUB_REF_NAME#v}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| awk -v sec="## [${ver}]" ' | ||||||||||||||||||||||||||||||||||||||||||||||||
| index($0, sec) == 1 { found = 1; next } | ||||||||||||||||||||||||||||||||||||||||||||||||
| found && (/^## \[/ || /^\[/) { exit } | ||||||||||||||||||||||||||||||||||||||||||||||||
| found { print } | ||||||||||||||||||||||||||||||||||||||||||||||||
| ' CHANGELOG.md | sed '/^[[:space:]]*$/d' > release-notes.md | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+50
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Preserve internal blank lines in release notes. The 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Create GitHub Release | ||||||||||||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ github.token }} | ||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -s release-notes.md ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh release create "$GITHUB_REF_NAME" dist-release/* --title "$GITHUB_REF_NAME" -F release-notes.md | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh release create "$GITHUB_REF_NAME" dist-release/* --title "$GITHUB_REF_NAME" --generate-notes | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+60
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
file=.github/workflows/release.yml
sed -n '1,90p' "$file"Repository: legioncodeinc/ghl-toolset Length of output: 2610 🌐 Web query:
💡 Result: The --verify-tag flag in the GitHub CLI command gh release create is used to prevent the automatic creation of git tags [1][2]. By default, if you run gh release create and specify a tag that does not yet exist in the repository, the GitHub CLI will automatically create that tag on the remote repository based on the latest state of the default branch [1][3]. When you include the --verify-tag flag, the command will instead query the repository via the GitHub API to check if the specified git tag already exists [2][4]. If the tag is not found, the command will abort and return an error, preventing the release creation process from proceeding [1][2]. This flag was introduced in version 2.21.0 of the GitHub CLI to provide a safeguard against unintended tag creation [2]. It is particularly useful in automated workflows or release processes where a tag must be explicitly created or validated before a release can be published [4][5]. Citations:
Require the pushed tag to exist before publishing. If the tag is missing, 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,7 +131,7 @@ Passing looks like one `ok` line per tool manifest and exit code 0. This is the | |
|
|
||
| ## Deployment | ||
|
|
||
| There is no pipeline to ship: tools are loaded unpacked straight from a checkout of this repo. Distributing via the Chrome Web Store is a future decision; until then, pin consumers to a tag of this repo. Exported data never transits any server — it goes from the browser tab to the ZIP on disk. | ||
| Releases are published by pushing a `v<x.y.z>` tag: the [Release workflow](./.github/workflows/release.yml) validates every manifest, packages each tool folder as a ZIP (with a `checksums.txt`), and publishes a GitHub Release using that version's CHANGELOG section as the notes. To install from a release: download the tool's ZIP, unzip it, and load the resulting folder via `chrome://extensions` → **Load unpacked**. Extensions loaded unpacked never auto-update — a new release means downloading the new ZIP and replacing the folder. Chrome Web Store distribution is out of scope for this project. Exported data never transits any server — it goes from the browser tab to the ZIP on disk. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Correct the exported-data statement.
🧰 Tools🪛 LanguageTool[uncategorized] ~134-~134: The official name of this software platform is spelled with a capital “H”. (GITHUB) 🤖 Prompt for AI Agents |
||
|
|
||
| ## Contributing | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: legioncodeinc/ghl-toolset
Length of output: 15330
🏁 Script executed:
Repository: legioncodeinc/ghl-toolset
Length of output: 3080
Reject non-semantic release tags.
v*triggers the workflow for tags such asvtestandv1. Add an early check for^v[0-9]+\.[0-9]+\.[0-9]+$. Otherwise, the workflow can publish a release without the required CHANGELOG section and use generated notes.🤖 Prompt for AI Agents