Skip to content

ci: upload junod binaries on GitHub Releases (#1220) - #1221

Open
fraserbrownirl wants to merge 1 commit into
CosmosContracts:mainfrom
fraserbrownirl:fix/1220-release-binaries
Open

ci: upload junod binaries on GitHub Releases (#1220)#1221
fraserbrownirl wants to merge 1 commit into
CosmosContracts:mainfrom
fraserbrownirl:fix/1220-release-binaries

Conversation

@fraserbrownirl

@fraserbrownirl fraserbrownirl commented Aug 12, 2026

Copy link
Copy Markdown

Summary

  • Adds .github/workflows/release-binaries.yml to build junod and upload junod + junod_sha256.txt on published releases (and via workflow_dispatch for backfill).
  • Documents interim install for v30.0.0 (Docker ghcr.io/cosmoscontracts/juno:v30.0.0 or make install) in RELEASES.md.
  • Fixes release-dispatch.yml to read release.tag_name on release events (v30 dispatch failed with empty tag).

Fixes #1220

Test plan

Summary by CodeRabbit

  • New Features

    • Release builds now automatically produce downloadable junod binaries and SHA-256 checksums.
    • Release assets can be generated for published releases or manual requests.
  • Documentation

    • Added instructions for obtaining release binaries, including guidance for older releases and alternative installation methods.

Restore release assets (junod + sha256) for published tags and allow
workflow_dispatch backfill for v30.0.0 (CosmosContracts#1220).
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The pull request adds automated junod binary publication for releases and manual dispatches. It validates and checks out release tags, builds with Go 1.25.10, uploads binaries and checksums, aligns release dispatch handling, and documents installation options.

Changes

Release assets

Layer / File(s) Summary
Binary build and publication
.github/workflows/release-binaries.yml
Adds a workflow that resolves a release tag, checks out the tag, builds junod, creates a SHA-256 checksum, and uploads both assets to the GitHub release.
Release dispatch alignment
.github/workflows/release-dispatch.yml
Uses the release event tag when no manual tag is provided and removes the trailing comma from the Cosmos SDK exclusion list.
Release acquisition documentation
RELEASES.md
Documents binary and checksum downloads, manual v30.0.0 asset generation, Docker installation, and source installation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the CI change to upload junod binaries to GitHub Releases.
Linked Issues check ✅ Passed The workflow builds junod and its SHA-256 checksum and supports manual backfilling for release v30.0.0.
Out of Scope Changes check ✅ Passed The workflow, release-event update, and installation documentation directly support binary release assets and v30.0.0 backfilling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between c0b3a8d and a22af8c.

📒 Files selected for processing (3)
  • .github/workflows/release-binaries.yml
  • .github/workflows/release-dispatch.yml
  • RELEASES.md

Comment on lines +13 to +14
permissions:
contents: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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/workflows

Repository: 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 --short

Repository: 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}')
PY

Repository: 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 $RUNNER_TEMP rather than directly in.git/config, the token remains accessible to any script or action executed within that specific job [1][4]. If an attacker can inject code into the job, they may potentially access this token [5][6][7]. Workflow expression injection is a distinct, critical security vulnerability that occurs when untrusted input (such as pull request titles, issue comments, or branch names) is evaluated within a GitHub Actions expression context (${{... }}) and then used directly in a run shell command [8][9][10]. If the workflow uses the expression syntax directly inside a run block, an attacker can escape the intended command string and execute arbitrary commands on the runner [8][7]. To prevent workflow expression injection and protect credentials: 1. Never use expression syntax (${{... }}) directly within run commands [9][7]. 2. Always assign untrusted input to an intermediate environment variable, and then reference that environment variable using the standard syntax of the shell (e.g., "$VAR" in Bash) [9][7][11][10]. 3. Set persist-credentials: false in your actions/checkout step if your workflow does not require authenticated Git operations, as this prevents the token from being made available to the local Git configuration [1][5]. 4. Follow the principle of least privilege by explicitly defining permissions for your GITHUB_TOKEN at the job or workflow level, ensuring it only has the permissions necessary for the task [6][9][10].

Citations:


🌐 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:


🏁 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}')
PY

Repository: 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))
PY

Repository: 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}')
PY

Repository: CosmosContracts/juno

Length of output: 647


Separate the build from the release upload and harden tag handling.

  • Grant contents: read to the build job and contents: write only to the upload job. Set persist-credentials: false on 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 --clobber uploads.
  • Pin actions/checkout and actions/setup-go to 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

Comment on lines +16 to +18
jobs:
upload-release-binaries:
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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

Comment on lines +26 to +32
tag="${RELEASE_TAG:-$INPUT_TAG}"
if [ -z "$tag" ]; then
echo "Release tag is required"
exit 1
fi

echo "release_tag=$tag" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.yml

Repository: 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}")
PY

Repository: 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\.' .github

Repository: 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}")
PY

Repository: 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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

awk '
  /uses:[[:space:]]*actions\/(checkout|setup-go)`@/` &&
  $0 !~ /@[0-9a-f]{40}([[:space:]]|#|$)/ {
    print
    bad=1
  }
  END { exit bad }
' .github/workflows/release-binaries.yml

Repository: 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.yml

Repository: 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

Comment on lines +47 to 49
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';

Copy link
Copy Markdown

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:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'releaseTag|isPrerelease|is_prerelease|release\.prerelease|createDispatchEvent' .github/workflows

Repository: 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 400

Repository: 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 300

Repository: 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:


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.

Comment thread RELEASES.md
Comment on lines +19 to +22
When `.github/workflows/release-binaries.yml` runs for a published GitHub release, it uploads two release assets for the tag:

- `junod`
- `junod_sha256.txt`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

there is no binary available for download on version v30.0.0

1 participant