ci: upload junod binaries on GitHub Releases (#1220) - #1221
ci: upload junod binaries on GitHub Releases (#1220)#1221fraserbrownirl wants to merge 1 commit into
Conversation
Restore release assets (junod + sha256) for published tags and allow workflow_dispatch backfill for v30.0.0 (CosmosContracts#1220).
WalkthroughThe pull request adds automated ChangesRelease assets
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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.
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-binaries.yml:
- Around line 16-18: Add a concurrency configuration to the
upload-release-binaries job keyed by the repository and resolved release tag,
and set cancel-in-progress to false so concurrent runs queue rather than cancel
or race. Apply the same configuration to the additional upload job section
identified by the review.
- Line 35: Update the actions/checkout and actions/setup-go references in the
release workflow to approved immutable 40-character commit SHAs instead of
version tags, preserving their existing action versions and workflow behavior.
- Around line 26-32: Validate the resolved tag in the release-tag setup block
before writing release_tag to GITHUB_OUTPUT, allowing only the expected safe
release-tag format and rejecting crafted shell syntax. In the steps that invoke
the commands at lines 45 and 55, pass the validated tag through env rather than
interpolating it into shell or Makefile arguments, while preserving the existing
release flow for valid tags.
- Around line 13-14: Separate the workflow into build and upload jobs, granting
read-only contents permission to build and write permission only to upload.
Validate the release tag before checkout, disable checkout credential
persistence, and pass the validated tag through RELEASE_TAG for both upload
commands. Add concurrency keyed by the release tag, and pin actions/checkout and
actions/setup-go to full commit SHAs.
In @.github/workflows/release-dispatch.yml:
- Around line 47-49: Update the release-event handling near releaseTag, isDraft,
and isPrerelease so an explicitly set inputs.is_prerelease takes precedence,
while tags sourced from context.payload.release derive isPrerelease from
context.payload.release?.prerelease. Preserve the boolean normalization and
ensure the juno-release payload forwards this value for downstream consumption
as client_payload.is_prerelease.
In `@RELEASES.md`:
- Around line 19-22: Update the release installation instructions in RELEASES.md
to document checksum verification after downloading junod and junod_sha256.txt
from the same release. Add the sha256sum check before installation, preserving
the existing asset download flow.
🪄 Autofix
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: ASSERTIVE
Plan: Pro Plus
Run ID: 6dfb350f-d5c5-48a6-a84f-7b49edd2e1f9
📒 Files selected for processing (3)
.github/workflows/release-binaries.yml.github/workflows/release-dispatch.ymlRELEASES.md
| permissions: | ||
| contents: write |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Expected: read-only build job, write-scoped upload job, and disabled checkout credentials.
rg -n -C 3 'contents: (read|write)|persist-credentials|make build|gh release upload' .github/workflowsRepository: CosmosContracts/juno
Length of output: 3014
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/release-binaries.yml
printf '%s\n' '--- tag resolution and checkout references ---'
rg -n -C 5 'resolve-tag|release_tag|checkout|github\\.event|workflow_dispatch|release:' .github/workflows/release-binaries.yml
printf '%s\n' '--- workflow history summary ---'
git diff --stat
git status --shortRepository: CosmosContracts/juno
Length of output: 3604
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- build entry points ---'
fd -H -t f '^(Makefile|makefile|GNUmakefile)$' .
rg -n -C 4 '(^|[[:space:]])build:|go (build|run|generate)|VERSION|LEDGER_ENABLED' Makefile makefile GNUmakefile 2>/dev/null || true
printf '%s\n' '--- workflow concurrency and action pinning ---'
rg -n -C 3 'concurrency:|actions/(checkout|setup-go)@|uses:' .github/workflows
printf '%s\n' '--- candidate tag syntax and shell interpolation probe ---'
python3 - <<'PY'
import subprocess
candidates = [
'v30.0.0',
'v30.0.0"; echo INJECTED; #',
'v30.0.0$(echo INJECTED)',
'v30.0.0`echo INJECTED`',
'v30.0.0;echo INJECTED',
]
for tag in candidates:
result = subprocess.run(
['git', 'check-ref-format', f'refs/tags/{tag}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
command = f'printf "VERSION=%s\\n" "{tag}"'
execution = subprocess.run(
['bash', '-c', command],
text=True,
capture_output=True,
)
print(f'tag={tag!r} valid_git_tag={result.returncode == 0} '
f'shell_stdout={execution.stdout!r} shell_stderr={execution.stderr!r}')
PYRepository: CosmosContracts/juno
Length of output: 18407
🌐 Web query:
GitHub Actions actions/checkout persist-credentials default GITHUB_TOKEN workflow expression injection run shell official documentation
💡 Result:
The actions/checkout action, which is used to check out repositories in GitHub Actions, has a configuration option called persist-credentials. By default, this option is set to true [1][2][3][4]. When persist-credentials is set to true (the default), the action configures the local Git environment with the GITHUB_TOKEN (or an SSH key, if provided) [1][2][4]. This allows subsequent steps in the same workflow job to perform authenticated Git commands, such as git fetch or git push, without needing to explicitly manage authentication [1][4]. While recent versions of actions/checkout have improved security by storing these credentials in a temporary file under
Citations:
- 1: https://github.com/actions/checkout
- 2: https://github.com/marketplace/actions/checkout?version=v3.6.0
- 3: https://github.com/actions/checkout/blob/cbb722410c2e876e24abbe8de2cc27693e501dcb/action.yml
- 4: https://github.com/actions/checkout/tree/v6.0.2
- 5: GHSA-3959-6v5q-45q2
- 6: Remove
persist-credentialsor change the default tofalseactions/checkout#485 - 7: https://codeql.github.com/codeql-query-help/actions/actions-code-injection-medium/
- 8: https://docs.github.com/en/actions/concepts/security/script-injections
- 9: https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/
- 10: https://docs.semgrep.dev/learn/vulnerabilities/command-injection/github-actions-injection
- 11: https://github.com/github/codeql/blob/main/actions/ql/src/Security/CWE-094/CodeInjectionMedium.md
🌐 Web query:
GitHub Actions concurrency workflow jobs official documentation release upload
💡 Result:
In GitHub Actions, you can control the execution of workflows and jobs using the concurrency key [1][2][3]. This allows you to limit concurrent runs, which is especially useful for tasks like deployments or releases where parallel execution could cause conflicts or corrupt states [4][5][6]. Key Concepts and Configuration: 1. Concurrency Groups: By defining a concurrency key, you assign a workflow or job to a specific group [1][2]. When multiple runs share the same group name, GitHub Actions ensures that only one such job or workflow is in progress at any given time [1][3]. Group names can be hard-coded strings or dynamic expressions (e.g., ${{ github.workflow }}-${{ github.ref }}) [1][2]. 2. Scope: You can define concurrency at the workflow level or the individual job level [1][3]. Note that workflow-level concurrency can only use contexts available at that scope, such as github, inputs, or vars, whereas job-level concurrency can access more specific contexts like matrix or needs [1][7]. 3. Handling Pending Jobs: - Default Behavior: By default, if a new run starts while another with the same concurrency group is in progress, the new run is marked as pending [1][4]. Any existing pending run in that group is automatically canceled [1][8][2]. - Cancel-in-progress: You can explicitly set cancel-in-progress: true to cancel the currently running job instead of just the pending one, which is a common pattern to ensure only the latest commit triggers a deployment [5][6]. - Queuing: If you prefer that runs execute sequentially rather than being canceled, you can use the queue property (e.g., queue: max) to allow multiple runs to wait in a queue [1][9][2]. Up to 100 runs can be queued per concurrency group [9][10]. Common Pitfalls: - Overly Unique Keys: Do not include github.sha or github.run_id in your concurrency group key [5][6]. These values are unique to every single run, which prevents jobs from ever sharing a concurrency group and effectively disables the feature [5][6]. - Incorrect Contexts: Attempting to use a job-specific context (like matrix) in a workflow-level concurrency block will result in an error [7]. Always ensure the contexts used in your expression are available at the chosen scope [7].
Citations:
- 1: https://docs.github.com/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs
- 2: https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions
- 3: https://github.blog/changelog/2021-04-19-github-actions-limit-workflow-run-or-job-concurrency/
- 4: https://docs.github.com/en/actions/concepts/workflows-and-actions/concurrency
- 5: https://gitspider.com/guides/github-actions-concurrency-cancel-in-progress
- 6: https://dev.to/ace2932/cancel-duplicate-github-actions-runs-with-one-block-and-the-one-place-you-shouldnt-2m3k
- 7: https://latchkey.dev/learn/github-actions/github-actions-concurrency-group-expression-error
- 8: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency
- 9: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 10: https://docs.github.com/en/actions/reference/limits
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import subprocess
candidates = [
'v30.0.0',
'v30.0.0";printf INJECTED;#',
'v30.0.0$(printf INJECTED)',
'v30.0.0`printf INJECTED`',
]
for tag in candidates:
valid = subprocess.run(
['git', 'check-ref-format', f'refs/tags/{tag}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode == 0
build_script = f'VERSION="{tag}" LEDGER_ENABLED=false printf BUILD_OK'
upload_script = f'printf UPLOAD_CMD gh release upload "{tag}" asset --clobber'
build = subprocess.run(['bash', '-c', build_script], text=True, capture_output=True)
upload = subprocess.run(['bash', '-c', upload_script], text=True, capture_output=True)
print(f'tag={tag!r}')
print(f' valid_git_tag={valid}')
print(f' build_script={build_script!r}')
print(f' build_stdout={build.stdout!r} build_stderr={build.stderr!r}')
print(f' upload_script={upload_script!r}')
print(f' upload_stdout={upload.stdout!r} upload_stderr={upload.stderr!r}')
PYRepository: CosmosContracts/juno
Length of output: 1431
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import subprocess
chars = ['"', "'", ';', '$', '`', '(', ')', '&', '|', '<', '>', '!', '#', '{', '}', '=', ',', '+', '@', '%']
for char in chars:
tag = f'v30.0.0{char}x'
valid = subprocess.run(
['git', 'check-ref-format', f'refs/tags/{tag}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode == 0
print(f'{char!r}: valid_git_tag={valid}')
print('--- valid tag corpus from repository ---')
tags = subprocess.run(
['git', 'for-each-ref', '--format=%(refname:strip=2)', 'refs/tags/'],
text=True,
capture_output=True,
check=True,
).stdout.splitlines()
print(f'count={len(tags)}')
for tag in tags:
print(repr(tag))
PYRepository: CosmosContracts/juno
Length of output: 687
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import subprocess
candidates = [
'v30.0.0";id;#',
'v30.0.0$(id)',
'v30.0.0`id`',
]
for tag in candidates:
valid = subprocess.run(
['git', 'check-ref-format', f'refs/tags/{tag}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode == 0
build_script = f'VERSION="{tag}" LEDGER_ENABLED=false printf BUILD_OK'
upload_script = f'printf UPLOAD_OK gh release upload "{tag}" asset --clobber'
build = subprocess.run(['bash', '-c', build_script], text=True, capture_output=True)
upload = subprocess.run(['bash', '-c', upload_script], text=True, capture_output=True)
print(f'tag={tag!r} valid_git_tag={valid}')
print(f' build_stdout={build.stdout!r} build_stderr={build.stderr!r}')
print(f' upload_stdout={upload.stdout!r} upload_stderr={upload.stderr!r}')
PYRepository: CosmosContracts/juno
Length of output: 647
Separate the build from the release upload and harden tag handling.
- Grant
contents: readto the build job andcontents: writeonly to the upload job. Setpersist-credentials: falseon checkout. - Validate the tag before checkout. A Git-valid tag such as
v30.0.0";id;#executes shell commands at lines 45 and 55. Pass the tag through an environment variable and use"$RELEASE_TAG"in both commands. - Add concurrency keyed by the release tag to prevent concurrent
--clobberuploads. - Pin
actions/checkoutandactions/setup-goto full commit SHAs.
🧰 Tools
🪛 zizmor (1.29.0)
[error] 14-14: overly broad permissions (excessive-permissions): contents: write is overly broad at the workflow level
(excessive-permissions)
[warning] 14-14: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-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-binaries.yml around lines 13 - 14, Separate the
workflow into build and upload jobs, granting read-only contents permission to
build and write permission only to upload. Validate the release tag before
checkout, disable checkout credential persistence, and pass the validated tag
through RELEASE_TAG for both upload commands. Add concurrency keyed by the
release tag, and pin actions/checkout and actions/setup-go to full commit SHAs.
Source: Linters/SAST tools
| jobs: | ||
| upload-release-binaries: | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
Serialize uploads for the same release tag.
A published event and a manual backfill can run concurrently for the same tag. Both runs use --clobber, so asset replacement can race and leave a failed workflow. Add a concurrency group keyed by repository and resolved tag, with cancel-in-progress: false.
Also applies to: 52-55
🧰 Tools
🪛 zizmor (1.29.0)
[info] 17-17: workflow or action definition without a name (anonymous-definition): this job
(anonymous-definition)
🤖 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-binaries.yml around lines 16 - 18, Add a
concurrency configuration to the upload-release-binaries job keyed by the
repository and resolved release tag, and set cancel-in-progress to false so
concurrent runs queue rather than cancel or race. Apply the same configuration
to the additional upload job section identified by the review.
Source: Linters/SAST tools
| tag="${RELEASE_TAG:-$INPUT_TAG}" | ||
| if [ -z "$tag" ]; then | ||
| echo "Release tag is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "release_tag=$tag" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/release-binaries.yml | sed -n '1,110p'
printf '%s\n' '--- Makefile references ---'
rg -n -C 6 'VERSION|build:' Makefile
printf '%s\n' '--- release tag sources and interpolation ---'
rg -n -C 4 'RELEASE_TAG|INPUT_TAG|release_tag|github\.event|steps\.resolve-tag|gh release' .github/workflows/release-binaries.ymlRepository: CosmosContracts/juno
Length of output: 5816
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- repository release tags ---'
git tag --list | python3 - <<'PY'
import sys
tags = [line.rstrip("\n") for line in sys.stdin]
print(f"count={len(tags)}")
for tag in tags[-20:]:
print(repr(tag))
PY
printf '%s\n' '--- Git ref-format probes ---'
python3 - <<'PY'
import subprocess
candidates = [
"v30.0.0",
'v30.0.0"; echo INJECTED #',
"v30.0.0;echo INJECTED",
"release/foo",
"release@candidate",
"release+build",
"release tag",
"release~candidate",
"release^{x}",
"release..candidate",
"release/@{x}",
]
for tag in candidates:
result = subprocess.run(
["git", "check-ref-format", "--allow-onelevel", f"refs/tags/{tag}"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
print(f"{tag!r}: {'valid-ref' if result.returncode == 0 else 'invalid-ref'}")
PY
printf '%s\n' '--- shell interpolation probes ---'
python3 - <<'PY'
import subprocess
template = 'VERSION="${TAG}" printf "VERSION=%s\\n" "$VERSION"'
candidates = [
'v30.0.0',
'v30.0.0"; printf "INJECTED\\n"; #',
'v30.0.0; printf "INJECTED\\n"',
]
for tag in candidates:
script = template.replace("${TAG}", tag)
result = subprocess.run(
["bash", "-c", script],
text=True,
capture_output=True,
)
print(f"tag={tag!r}")
print(f"returncode={result.returncode}")
print(f"stdout={result.stdout!r}")
print(f"stderr={result.stderr!r}")
PYRepository: CosmosContracts/juno
Length of output: 813
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- complete build flag definitions ---'
cat -n Makefile | sed -n '1,75p'
printf '%s\n' '--- release/version format references ---'
rg -n -i -C 3 'release tag|tag.*format|version.*regex|^v[0-9]|git tag|semantic.version|semver' \
.github README.md docs Makefile 2>/dev/null || true
printf '%s\n' '--- workflow validation and output handling patterns ---'
rg -n -C 4 'GITHUB_OUTPUT|github.event.release.tag_name|inputs.tag|VERSION=.*steps\.' .githubRepository: CosmosContracts/juno
Length of output: 7558
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- recent GitHub release tag names ---'
curl -fsSL 'https://api.github.com/repos/CosmosContracts/juno/releases?per_page=30' |
python3 -c '
import json, sys
for item in json.load(sys.stdin):
print(repr(item.get("tag_name")))
'
printf '%s\n' '--- standalone Makefile quoting probe ---'
python3 - <<'PY'
import subprocess
# This models the Makefile's single-quoted -ldflags recipe argument.
template = "printf '%s\\n' '-X path/version.Version=%s'"
for version in ["v30.0.0", "v30.0.0' ; printf INJECTED ; echo '"]:
script = template % version
result = subprocess.run(["bash", "-c", script], text=True, capture_output=True)
print(f"VERSION={version!r}")
print(f"returncode={result.returncode}")
print(f"stdout={result.stdout!r}")
print(f"stderr={result.stderr!r}")
PYRepository: CosmosContracts/juno
Length of output: 853
Validate release_tag before shell interpolation.
A crafted manual tag can execute shell commands at lines 45 and 55. Environment passing alone is insufficient because VERSION enters the Makefile’s single-quoted linker flags.
Reject invalid release tags before writing release_tag to GITHUB_OUTPUT, then pass the validated value through env in both steps.
🤖 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-binaries.yml around lines 26 - 32, Validate the
resolved tag in the release-tag setup block before writing release_tag to
GITHUB_OUTPUT, allowing only the expected safe release-tag format and rejecting
crafted shell syntax. In the steps that invoke the commands at lines 45 and 55,
pass the validated tag through env rather than interpolating it into shell or
Makefile arguments, while preserving the existing release flow for valid tags.
Source: Linters/SAST tools
| echo "release_tag=$tag" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Checkout release tag | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
awk '
/uses:[[:space:]]*actions\/(checkout|setup-go)`@/` &&
$0 !~ /@[0-9a-f]{40}([[:space:]]|#|$)/ {
print
bad=1
}
END { exit bad }
' .github/workflows/release-binaries.ymlRepository: CosmosContracts/juno
Length of output: 226
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/release-binaries.yml
printf '%s\n' '--- action references ---'
rg -n '^[[:space:]]*uses:|^[[:space:]]*permissions:|persist-credentials|contents:|concurrency:' .github/workflows/release-binaries.ymlRepository: CosmosContracts/juno
Length of output: 2122
Pin the action references to immutable commit SHAs.
actions/checkout@v4 and actions/setup-go@v5 run in a job with contents: write. Pin both references to approved 40-character commit SHAs.
🧰 Tools
🪛 zizmor (1.29.0)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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-binaries.yml at line 35, Update the
actions/checkout and actions/setup-go references in the release workflow to
approved immutable 40-character commit SHAs instead of version tags, preserving
their existing action versions and workflow behavior.
Source: Linters/SAST tools
| const releaseTag = inputs.release_tag || context.payload.release?.tag_name || ''; | ||
| const isDraft = String(inputs.is_draft || '').toLowerCase() === 'true'; | ||
| const isPrerelease = String(inputs.is_prerelease || '').toLowerCase() === 'true'; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 4 'releaseTag|isPrerelease|is_prerelease|release\.prerelease|createDispatchEvent' .github/workflowsRepository: CosmosContracts/juno
Length of output: 3184
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- workflow context ---'
sed -n '1,145p' .github/workflows/release-dispatch.yml
printf '%s\n' '--- downstream juno-release handlers and payload consumers ---'
rg -n -C 6 'juno-release|is_prerelease|isPrerelease|client_payload|release_tag' .github . 2>/dev/null | head -n 400Repository: CosmosContracts/juno
Length of output: 9786
🏁 Script executed:
#!/bin/bash
set -euo pipefail
node - <<'JS'
function current(payload) {
const inputs = (payload && payload.inputs) || {};
const releaseTag = inputs.release_tag || payload.release?.tag_name || '';
const isPrerelease = String(inputs.is_prerelease || '').toLowerCase() === 'true';
return { releaseTag, isPrerelease };
}
function proposed(payload) {
const inputs = (payload && payload.inputs) || {};
const releaseTag = inputs.release_tag || payload.release?.tag_name || '';
const hasManualPrerelease = inputs.is_prerelease !== undefined &&
inputs.is_prerelease !== null && inputs.is_prerelease !== '';
const isPrerelease = hasManualPrerelease
? String(inputs.is_prerelease).toLowerCase() === 'true'
: Boolean(payload.release?.prerelease);
return { releaseTag, isPrerelease };
}
const event = { release: { tag_name: 'v1.2.3', prerelease: true } };
const manual = { inputs: { release_tag: 'v1.2.3', is_prerelease: 'false' } };
console.log(JSON.stringify({
releaseEvent: { current: current(event), proposed: proposed(event) },
manualOverride: { current: current(manual), proposed: proposed(manual) }
}, null, 2));
JS
printf '%s\n' '--- local downstream workflow files ---'
git ls-files | rg '(^|/)\.github/workflows/|release|dispatch' | head -n 300
rg -n -C 5 'juno-release|is_prerelease|client_payload|release_tag' --glob '! .git/**' . 2>/dev/null | head -n 300Repository: CosmosContracts/juno
Length of output: 927
🌐 Web query:
CosmosContracts juno-std GitHub workflow "juno-release" "is_prerelease"
💡 Result:
Based on your query, there appears to be a conflation between two distinct projects [1][2][3]: 1. CosmosContracts/juno and juno-std: These relate to the Cosmos-based Juno blockchain, which uses CosmWasm [1][2][4]. The juno-std repository is a Rust-based standard library for Juno's Protobuffers [2][4]. There is no standard GitHub workflow configuration named juno-release or parameter is_prerelease associated with this organization's official public repositories [1][2][5]. 2. Junobuild (juno.build): This is a separate project for serverless functions on the Internet Computer [3][6]. It maintains a GitHub action (junobuild/juno-action) [7][8] used for building and publishing functions [3]. Regarding the specific terms "juno-release" and "is_prerelease": - These are common patterns found in community-created GitHub Actions to handle release logic (e.g., checking if a tag is a prerelease before running a job) [9]. - If you are looking for how to check if a release is a prerelease in a standard GitHub workflow, you typically use the github context [9]. For example: if: github.event.release.prerelease == true If you have a specific workflow file or private repository context where these terms are used, please verify if they are custom implementation details within that repository, as they are not standard identifiers in the CosmosContracts or Junobuild ecosystems [1][3][8].
Citations:
- 1: https://github.com/CosmosContracts/juno/actions
- 2: https://github.com/CosmosContracts/juno-std
- 3: https://juno.build/docs/guides/github-actions/publish-functions
- 4: https://crates.io/crates/juno-std
- 5: https://github.com/CosmosContracts/juno-std/pulls
- 6: https://github.com/junobuild/docs/releases
- 7: https://github.com/junobuild/juno-action/releases
- 8: https://github.com/marketplace/actions/github-action-for-juno
- 9: https://github.com/orgs/community/discussions/26281
Preserve prerelease status for release events.
When releaseTag comes from context.payload.release, derive isPrerelease from context.payload.release?.prerelease unless inputs.is_prerelease is set. The workflow forwards this value in the juno-release payload, so the current code can classify a prerelease as stable. Ensure the downstream handler consumes client_payload.is_prerelease.
🤖 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-dispatch.yml around lines 47 - 49, Update the
release-event handling near releaseTag, isDraft, and isPrerelease so an
explicitly set inputs.is_prerelease takes precedence, while tags sourced from
context.payload.release derive isPrerelease from
context.payload.release?.prerelease. Preserve the boolean normalization and
ensure the juno-release payload forwards this value for downstream consumption
as client_payload.is_prerelease.
| When `.github/workflows/release-binaries.yml` runs for a published GitHub release, it uploads two release assets for the tag: | ||
|
|
||
| - `junod` | ||
| - `junod_sha256.txt` |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
Document checksum verification.
After downloading both assets from the same release, instruct operators to verify the binary before installation.
Proposed documentation
- `junod`
- `junod_sha256.txt`
+
+After downloading both files into the same directory, verify the binary:
+
+```sh
+sha256sum -c junod_sha256.txt
+```📝 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.
| When `.github/workflows/release-binaries.yml` runs for a published GitHub release, it uploads two release assets for the tag: | |
| - `junod` | |
| - `junod_sha256.txt` | |
| When `.github/workflows/release-binaries.yml` runs for a published GitHub release, it uploads two release assets for the tag: | |
| - `junod` | |
| - `junod_sha256.txt` | |
| After downloading both files into the same directory, verify the binary: | |
🧰 Tools
🪛 LanguageTool
[uncategorized] ~19-~19: The official name of this software platform is spelled with a capital “H”.
Context: ...reaking.** ## Obtaining binaries When .github/workflows/release-binaries.yml runs fo...
(GITHUB)
🤖 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 `@RELEASES.md` around lines 19 - 22, Update the release installation
instructions in RELEASES.md to document checksum verification after downloading
junod and junod_sha256.txt from the same release. Add the sha256sum check before
installation, preserving the existing asset download flow.
Summary
.github/workflows/release-binaries.ymlto buildjunodand uploadjunod+junod_sha256.txton published releases (and viaworkflow_dispatchfor backfill).ghcr.io/cosmoscontracts/juno:v30.0.0ormake install) inRELEASES.md.release-dispatch.ymlto readrelease.tag_nameon release events (v30 dispatch failed with empty tag).Fixes #1220
Test plan
workflow_dispatchand tagv30.0.0junodandjunod_sha256.txtsha256sum -c junod_sha256.txtvalidates the binarySummary by CodeRabbit
New Features
junodbinaries and SHA-256 checksums.Documentation