Skip to content

fix(version)!: resolve CLI version from reusable workflow ref#5357

Open
rh-hemartin wants to merge 1 commit into
mainfrom
hemartin/resolve-sha-to-release
Open

fix(version)!: resolve CLI version from reusable workflow ref#5357
rh-hemartin wants to merge 1 commit into
mainfrom
hemartin/resolve-sha-to-release

Conversation

@rh-hemartin

@rh-hemartin rh-hemartin commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Default fullsend_version to "" across reusable workflows so callers that omit it fall through to job.workflow_sha instead of latest, preventing version skew between the workflow ref and the CLI binary (fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369)
  • Add SHA-to-tag resolution in both the install action (.github/actions/install-fullsend-cli/action.yml) and the root action.yml, so a 40-char commit SHA is mapped to its release tag before download, avoiding unnecessary source builds
  • Paginate tag lookups, use safe jq parameterization (--arg), derive OS/arch from runner context instead of hardcoding linux, and add a source-build fallback when the release download fails
  • When no tag matches, the existing source-build fallback is preserved

Breaking change

fullsend_version in reusable workflows now defaults to the workflow SHA instead of "latest". Callers that omit fullsend_version and want the previous behavior should pass fullsend_version: "latest" explicitly.

Closes #3369

Test plan

  • Tested on rh-hemartin-fullsendai/standalone-fullsend run 29739450357 — confirmed the source-build fallback triggers when SHA resolution is missing
  • Re-run the same caller with this branch to verify the SHA resolves to v0.31.0 and downloads the pre-built binary
  • Verify a non-tagged SHA still falls back to source build
  • Verify version: latest and version: v0.31.0 paths are unaffected

🤖 Generated with Claude Code

@rh-hemartin
rh-hemartin requested a review from a team as a code owner July 20, 2026 13:49
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

CI: resolve workflow SHA to release tag for Fullsend CLI installs

🐞 Bug fix ✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Default reusable workflow fullsend_version to empty to avoid latest skew.
• Resolve 40-char SHAs to release tags to download GoReleaser binaries.
• Preserve source-build fallback when no matching tag exists.
Diagram

graph TD
  A["Caller workflow"] --> B["Reusable workflows"] --> C["Fullsend action (action.yml)"] --> D["Install decision"]
  D --> E["Resolve SHA->tag"] --> F["GitHub API (tags/releases)"] --> G["Release artifact"]
  D --> H["Source build"]
  subgraph Legend
    direction LR
    _wf["Workflow"] ~~~ _act["Composite action"] ~~~ _ext["GitHub API"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Resolve SHA via git tags after shallow fetch
  • ➕ No dependence on GitHub tags API page size (100) or pagination logic
  • ➕ Can precisely detect tags pointing at the fetched commit
  • ➖ Requires cloning/fetching tags even when a release artifact exists
  • ➖ More network and time cost; defeats some of the optimization goal
2. Paginate tag resolution (API loop) until match or exhaustion
  • ➕ Keeps the fast-path download approach while avoiding 100-tag blind spots
  • ➕ More robust as tag history grows
  • ➖ More scripting complexity and API calls (rate limits)
  • ➖ Needs careful handling of retries/fail-open behavior

Recommendation: The PR’s approach (best-effort SHA→tag resolution with a preserved source-build fallback) is the right default for CI: it improves performance without breaking untagged SHAs. Consider a follow-up enhancement to paginate tag lookup (or switch to a git-based tag check) if the repository’s tag count makes the current per_page=100 approach unreliable over time.

Files changed (9) +82 / -24

Enhancement (2) +62 / -4
action.ymlPrefer release artifact when workflow SHA matches a tag +48/-4

Prefer release artifact when workflow SHA matches a tag

• Adds a SHA-to-tag resolution step for upstream installs and downloads the corresponding GoReleaser release asset when found. Gates Go setup and source build steps behind the 'no tag found' condition while preserving the original build-from-source fallback.

.github/actions/install-fullsend-cli/action.yml

action.ymlResolve SHA version inputs to release tags before install +14/-0

Resolve SHA version inputs to release tags before install

• Enhances the top-level composite action’s install detection to map 40-character SHAs to matching 'v*' tags via the GitHub API. This allows the action to take the existing release-download path instead of falling back to source builds when a release exists.

action.yml

Other (7) +20 / -20
reusable-code.ymlDefault CLI version to workflow SHA when input omitted +2/-2

Default CLI version to workflow SHA when input omitted

• Changes 'fullsend_version' default from 'latest' to empty and updates the Fullsend action invocation to use 'inputs.fullsend_version || job.workflow_sha'. This prevents callers that omit the version from unintentionally pinning the CLI to 'latest'.

.github/workflows/reusable-code.yml

reusable-dispatch.ymlUse workflow SHA as implicit CLI version across dispatch stages +8/-8

Use workflow SHA as implicit CLI version across dispatch stages

• Sets 'fullsend_version' input default to empty and updates all stage invocations to fall back to 'job.workflow_sha' when the input is unset. Aligns the CLI binary version with the workflow ref to avoid version skew.

.github/workflows/reusable-dispatch.yml

reusable-fix.ymlAlign fix workflow CLI version with workflow SHA by default +2/-2

Align fix workflow CLI version with workflow SHA by default

• Defaults 'fullsend_version' to empty and passes 'inputs.fullsend_version || job.workflow_sha' into the Fullsend action. Ensures fix runs use the CLI corresponding to the workflow ref unless explicitly overridden.

.github/workflows/reusable-fix.yml

reusable-prioritize.ymlAlign prioritize workflow CLI version with workflow SHA by default +2/-2

Align prioritize workflow CLI version with workflow SHA by default

• Defaults 'fullsend_version' to empty and updates the action call to fall back to 'job.workflow_sha'. Reduces unexpected upgrades caused by implicit 'latest' installs.

.github/workflows/reusable-prioritize.yml

reusable-retro.ymlAlign retro workflow CLI version with workflow SHA by default +2/-2

Align retro workflow CLI version with workflow SHA by default

• Defaults 'fullsend_version' to empty and ensures the invoked action uses 'job.workflow_sha' when the input is not set. Keeps workflow ref and CLI binary consistent.

.github/workflows/reusable-retro.yml

reusable-review.ymlAlign review workflow CLI version with workflow SHA by default +2/-2

Align review workflow CLI version with workflow SHA by default

• Defaults 'fullsend_version' to empty and updates the Fullsend action invocation to use 'inputs.fullsend_version || job.workflow_sha'. Avoids accidental 'latest' installs when callers omit the input.

.github/workflows/reusable-review.yml

reusable-triage.ymlAlign triage workflow CLI version with workflow SHA by default +2/-2

Align triage workflow CLI version with workflow SHA by default

• Defaults 'fullsend_version' to empty and passes 'inputs.fullsend_version || job.workflow_sha' to the Fullsend action. Ensures triage uses the CLI corresponding to the workflow revision.

.github/workflows/reusable-triage.yml

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 1:51 PM UTC · Ended 1:53 PM UTC
Commit: 586fd4f · View workflow run →

@rh-hemartin
rh-hemartin force-pushed the hemartin/resolve-sha-to-release branch from 586fd4f to a738f3a Compare July 20, 2026 13:53
@rh-hemartin rh-hemartin changed the title feat(ci): resolve SHA to release tag for CLI install fix(version): resolve CLI version from reusable workflow ref Jul 20, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 1:55 PM UTC · Ended 2:03 PM UTC
Commit: a738f3a · View workflow run →

@qodo-code-review

qodo-code-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 54 rules

Grey Divider


Remediation recommended

1. Unpaged tags lookup ✓ Resolved 🐞 Bug ➹ Performance
Description
Both the composite installer and the root action’s SHA→tag resolution fetch only the first 100 tags
(per_page=100) without pagination, so repositories with more than 100 tags can fail to find an
existing matching release tag. When that happens, the action incorrectly falls back to the
source-build path instead of using the pre-built release artifact.
Code

.github/actions/install-fullsend-cli/action.yml[R59-62]

+        TAG=$(gh api "repos/${WORKFLOW_REPOSITORY}/tags?per_page=100" \
+          --jq ".[] | select(.commit.sha == \"${WORKFLOW_SHA}\") | .name" \
+          | grep '^v[0-9]' | head -1) || true
+        echo "tag=${TAG}" >> "${GITHUB_OUTPUT}"
Relevance

⭐⭐⭐ High

Team has accepted pagination fixes for per_page=100 truncation (added --paginate) in PR #225 and
#2398.

PR-#225
PR-#2398

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The cited implementations perform a single tags API request capped at 100 items and then search only
within that truncated response, which cannot reliably resolve a SHA to a tag once the repository has
more than 100 tags. The repo already demonstrates an established approach for complete API
enumeration by using gh api --paginate in other workflows, indicating pagination is the expected
pattern when correctness depends on scanning all results.

.github/actions/install-fullsend-cli/action.yml[49-67]
.github/workflows/e2e.yml[115-130]
action.yml[118-130]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
SHA→tag resolution is implemented with a single `.../tags?per_page=100` request and no pagination, so if the matching tag is beyond the first page the lookup fails and the action unnecessarily takes the source-build path (skipping the pre-built release artifact even though it exists).

## Issue Context
- The composite installer currently uses `gh api` for the tags request, but it limits results to 100 and does not paginate.
- The repo already uses `gh api --paginate` elsewhere when complete results are required, showing pagination is an established pattern.
- The root action’s SHA→tag resolution currently uses `curl` (not `gh`) for API calls, so pagination either needs to be implemented in bash (e.g., looping over `page=`) or the action needs to intentionally add/standardize on a `gh` dependency.
- Optional hardening noted in the findings: normalize/validate `WORKFLOW_SHA` (e.g., lowercase + 40-hex check) to reduce surprising lookup failures.

## Fix Focus Areas
- .github/actions/install-fullsend-cli/action.yml[49-67]
- .github/workflows/e2e.yml[115-130]
- action.yml[118-130]

## Suggested fix
1. **Add pagination to tag fetching so the lookup is complete**
  - For the composite action (using `gh`): switch to `gh api "repos/${WORKFLOW_REPOSITORY}/tags?per_page=100" --paginate`.
  - Because `--paginate` returns multiple JSON arrays, combine pages before filtering (e.g., `jq -s 'add | ...'`), or use `jq -rs` to read/merge all pages.
  - For the root action (using `curl`): implement a bounded `page=1..N` loop fetching `tags?per_page=100&page=$page`, stopping when a match is found or when the returned array is empty.
2. **Make the SHA matching/filtering more robust**
  - Avoid string interpolation inside a jq program; pass the SHA as an argument (e.g., `jq ... --arg sha "$WORKFLOW_SHA" '... select(.commit.sha == $sha) ...'`).
3. **(Optional hardening + debuggability)**
  - Normalize/validate the SHA prior to lookup (accept `[0-9a-fA-F]{40}` then lowercase).
  - Preserve non-fatal behavior when no match is found (keep existing `|| true` behavior where applicable), and add a short log line when pagination exhausts without a match to aid debugging.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Linux-only release download ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new install-release step in the composite installer hard-codes a Linux asset name
(..._linux_${ARCH}.tar.gz), so running the reusable workflow on a non-Linux runner_image will
download the wrong artifact and fail the job (no source-build fallback runs once a tag is resolved).
Code

.github/actions/install-fullsend-cli/action.yml[R79-88]

+        VERSION="${TAG#v}"
+        ARCH="$(uname -m)"
+        [[ "${ARCH}" == "x86_64" ]] && ARCH="amd64"
+        [[ "${ARCH}" == "aarch64" ]] && ARCH="arm64"
+        ASSET="fullsend_${VERSION}_linux_${ARCH}.tar.gz"
+        mkdir -p "${RUNNER_TEMP}/fullsend"
+        echo "Downloading ${ASSET} from release ${TAG}"
+        gh release download "${TAG}" -R "${WORKFLOW_REPOSITORY}" -p "${ASSET}" -D "${RUNNER_TEMP}/fullsend"
+        tar -xzf "${RUNNER_TEMP}/fullsend/${ASSET}" -C "${RUNNER_TEMP}/fullsend"
+        rm -f "${RUNNER_TEMP}/fullsend/${ASSET}"
Relevance

⭐⭐ Medium

No clear historical evidence on enforcing cross-runner OS asset naming in composite installers.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The composite action constructs a Linux-only asset name, while the reusable workflow explicitly
allows choosing the runner image. The repo’s root action already demonstrates the intended
cross-platform OS/arch mapping logic, highlighting the inconsistency.

.github/actions/install-fullsend-cli/action.yml[69-91]
.github/workflows/reusable-dispatch.yml[57-62]
action.yml[171-217]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The composite action `.github/actions/install-fullsend-cli` downloads `fullsend_${VERSION}_linux_${ARCH}.tar.gz` when a release tag is resolved. This is Linux-specific and can break installs on non-Linux runners (or custom runner images), and because the source-build steps are gated on `steps.resolve-tag.outputs.tag == ''`, there is no fallback if the download step fails.

## Issue Context
- Reusable workflows allow selecting `runner_image` (default `ubuntu-24.04`), so non-Linux runners are possible.
- The root `action.yml` already implements correct OS/arch mapping for release assets.

## Fix Focus Areas
- .github/actions/install-fullsend-cli/action.yml[69-91]
- .github/workflows/reusable-dispatch.yml[57-62]
- action.yml[171-223]

## Suggested fix
1. In `install-release`, derive `os` and `arch` similarly to the root action (use `${{ runner.os }}` / `${{ runner.arch }}` passed via `env`, or `uname -s` + `uname -m`) and construct `ASSET_NAME="fullsend_${VERSION}_${os}_${arch}.tar.gz"`.
2. Alternatively, explicitly gate the release-download step to Linux only (and keep source build for other OSes).
3. Consider adding a guarded fallback: if download/extract fails, run the source-build path (e.g., via `continue-on-error: true` on download and a subsequent conditional build step) if that behavior is desired.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

3. Direct api.github.com call 📘 Rule violation ⌂ Architecture
Description
The root action.yml adds a direct GitHub REST API call (including GitHub-specific headers) outside
internal/forge/github/, which violates the repository policy to centralize GitHub API interactions
in the forge GitHub layer.
Code

action.yml[R120-125]

+          TAG=$(retry_curl -fsSL \
+            -H "Accept: application/vnd.github+json" \
+            -H "Authorization: Bearer ${GH_TOKEN}" \
+            "https://api.github.com/repos/fullsend-ai/fullsend/tags?per_page=100" \
+            | jq -r --arg sha "${VERSION}" '.[] | select(.commit.sha == $sha) | .name' \
+            | grep '^v[0-9]' | head -1) || true
Relevance

⭐ Low

Similar “avoid direct api.github.com / centralize in forge” suggestions were rejected previously (PR
#4901, #1333).

PR-#4901
PR-#1333

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1062054 restricts direct GitHub API calls (including hardcoded api.github.com
URLs and GitHub-specific headers) to internal/forge/github/. The change in action.yml adds a
retry_curl call to https://api.github.com/repos/fullsend-ai/fullsend/tags... with `Accept:
application/vnd.github+json and Authorization: Bearer ...`, which is outside the allowed
directory.

Rule 1062054: Restrict direct GitHub API calls to internal/forge/github
action.yml[118-130]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`action.yml` makes a direct request to `https://api.github.com/...` and sets GitHub-specific headers outside `internal/forge/github/`, which violates the rule restricting direct GitHub API calls.

## Issue Context
The new logic resolves a 40-char SHA to a release tag using the GitHub tags API. The compliance requirement is that GitHub API specifics (URLs/headers) should live in `internal/forge/github/` and be consumed via an abstraction.

## Fix Focus Areas
- action.yml[118-130]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread .github/actions/install-fullsend-cli/action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml Outdated
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@rh-hemartin
rh-hemartin force-pushed the hemartin/resolve-sha-to-release branch from a738f3a to eedfa3e Compare July 20, 2026 14:02
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:04 PM UTC · Completed 2:19 PM UTC
Commit: eedfa3e · View workflow run →

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

Site preview

Preview: https://ca78803d-site.fullsend-ai.workers.dev

Commit: 0e86cb3a076b5f7b85023883c6f2d7cea1acf66b

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Multi-agent review (3 agents: Claude ×2, Grok). 2 unique findings posted inline; 2 additional MEDIUM findings (Linux-only asset name, tags pagination) already covered by existing qodo comments — not re-posted.

Comment thread .github/actions/install-fullsend-cli/action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [input-default-change] .github/workflows/reusable-code.yml (and 7 other reusable workflows) — The fullsend_version input default changed from "latest" to "" across all reusable workflows. Callers that omit this input will now receive the CLI version matching job.workflow_sha instead of the latest release. This is a properly documented breaking change: the PR title uses the ! suffix (fix(version)!:) and the PR body includes migration guidance ("pass fullsend_version: 'latest' explicitly").

  • [protected-path] .github/ — This PR modifies 8 files under .github/ (a protected path). The PR links to issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 and explains the rationale for the changes. Human approval is required for protected-path changes regardless of context.

Low

  • [error-handling-gap] action.yml — Adding continue-on-error: true to the download-release step means OS/arch validation errors (exit 1 for unsupported OS or architecture) are swallowed, and the workflow falls through to source build. The job will still fail at later Linux-specific steps (Install Podman), so the impact is limited to delayed/confusing error messages rather than incorrect artifacts. Consider moving OS/arch validation into the detect step.

  • [injection-pattern] .github/actions/install-fullsend-cli/action.yml${{ steps.install-release.outcome }} is interpolated directly into the run: script body rather than via an env: variable. The equivalent code in action.yml correctly uses DOWNLOAD_OUTCOME env var indirection. Exploitation is infeasible (GHA-controlled values), but the inconsistency should be aligned.

  • [code-duplication-divergence] .github/actions/install-fullsend-cli/action.yml — SHA-to-tag resolution logic uses gh api --paginate + jq in this file vs manual pagination with retry_curl in action.yml. The different HTTP clients and pagination strategies serve different execution contexts but create maintenance burden. Add cross-reference comments to aid future sync.

  • [os-arch-normalization-divergence] .github/actions/install-fullsend-cli/action.yml — OS/arch normalization uses case-insensitive matching with broader platform support (macos→darwin, x86→386) while action.yml uses strict case-sensitive matching (X64, ARM64 only) with hard errors. The divergence is intentional (action.yml requires Linux for Podman) but should be documented.

  • [stale-doc] docs/plans/automatic-updates.md — While action.yml's inputs.version default remains "latest", the new SHA-to-tag resolution behavior and the reusable workflow fullsend_version default change are not reflected in this plan document. Consider adding an amendment section about the new version resolution flow.

Previous run

Review

Findings

Medium

  • [breaking-change-input-default] .github/workflows/reusable-code.yml (and 6 other reusable workflows) — Changing the fullsend_version input default from "latest" to "" alters the version resolution path for callers that omit the input: they shift from receiving the latest GitHub Release to receiving the CLI version at job.workflow_sha. Issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 documents the old "latest" behavior as a bug causing version skew — the new behavior is the intended contract (callers referencing @v0 get the CLI matching that ref). The behavioral change is from broken to correct, but callers who relied on the "latest" default will observe different behavior. Consider whether fix(version)!: with a BREAKING CHANGE: trailer is warranted per COMMITS.md, or document in the PR description why the ! suffix is not needed.

  • [protected-path] .github/ — This PR modifies 8 files under .github/ (a protected path). The PR links to issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 and explains the rationale for the changes. Human approval is required for protected-path changes regardless of context.

Low

  • [code-duplication-divergence] .github/actions/install-fullsend-cli/action.yml — The SHA-to-tag resolution logic is duplicated between this file (gh api --paginate + jq) and action.yml (manual pagination with retry_curl). The two implementations use different HTTP clients and pagination strategies. Both serve different execution contexts, but the divergence creates maintenance burden. Add cross-reference comments to aid future sync.

  • [os-arch-normalization-duplication] .github/actions/install-fullsend-cli/action.yml — OS/arch normalization logic (macos→darwin, x64→amd64, etc.) is duplicated between this file and action.yml. Add cross-reference comments to keep implementations in sync.

Previous run

Review

Findings

Medium

  • [breaking-change-input-default] .github/workflows/reusable-code.yml (and 6 other reusable workflows) — Changing the fullsend_version input default from "latest" to "" alters the version resolution path for callers that omit the input: they shift from receiving the latest GitHub Release to receiving the CLI version at job.workflow_sha. Issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 documents the old "latest" behavior as a bug causing version skew — the new behavior is the intended contract (callers referencing @v0 get the CLI matching that ref). The behavioral change is from broken to correct, but callers who relied on the "latest" default will observe different behavior. Consider whether fix(version)!: with a BREAKING CHANGE: trailer is warranted per COMMITS.md, or document in the PR description why the ! suffix is not needed.

  • [protected-path] .github/ — This PR modifies 8 files under .github/ (a protected path). The PR links to issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 and explains the rationale for the changes. Human approval is required for protected-path changes regardless of context.

Low

  • [code-duplication-divergence] .github/actions/install-fullsend-cli/action.yml — The SHA-to-tag resolution logic is duplicated between this file (gh api --paginate + jq) and action.yml (manual pagination with retry_curl). The two implementations use different HTTP clients and pagination strategies. Both serve different execution contexts, but the divergence creates maintenance burden. Add cross-reference comments to aid future sync.

  • [os-arch-normalization-duplication] .github/actions/install-fullsend-cli/action.yml — OS/arch normalization logic (macos→darwin, x64→amd64, etc.) is duplicated between this file and action.yml. Add cross-reference comments to keep implementations in sync.

Previous run (2)

Review

Findings

Medium

  • [error-handling-gap] .github/actions/install-fullsend-cli/action.yml — The "Download pre-built binary from release" step runs whenever a tag matching the SHA is found (steps.resolve-tag.outputs.tag != ''), but does not verify that a GitHub release with assets exists for that tag. If a version tag (e.g., v0.5.2) exists as a lightweight tag without a corresponding GitHub release, gh release download will fail with a non-zero exit and set -euo pipefail will hard-fail the job. The source-build fallback steps are skipped because their condition requires tag == ''. By contrast, the parallel change in action.yml correctly checks the release API status (HTTP 200 vs 404) before attempting download, and falls through to source build on 404.
    Remediation: Add a release existence check before downloading (similar to the HTTP status check in action.yml), or catch the gh release download failure and fall through to the source build steps.

  • [breaking-change-default-input] .github/workflows/reusable-code.yml (and 6 other reusable workflows) — The fullsend_version input default changes from "latest" to "" across all 7 reusable workflows. Downstream callers that omit fullsend_version shift from resolving the latest GitHub Release to resolving job.workflow_sha. Per COMMITS.md, "Default values change in ways that alter existing behavior" is a breaking change indicator, and "a missing ! is an important-severity review finding." The PR title fix(version): lacks the ! suffix. Issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 documents that the old "latest" behavior was a bug causing version skew — the change is an intentional fix. Consider whether fix(version)!: is warranted per COMMITS.md, or document why the ! suffix is not needed.

  • [protected-path] .github/ — This PR modifies 8 files under .github/ (a protected path). The PR links to issue fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags #3369 and explains the rationale for the changes. Human approval is required for protected-path changes regardless of context.

Low

  • [injection] .github/actions/install-fullsend-cli/action.ymlWORKFLOW_SHA is interpolated directly into a jq expression via shell string interpolation in the --jq flag, unlike the equivalent code in action.yml which uses jq --arg sha for safe parameterization. The default input (github.sha) and typical callers (job.workflow_sha) are constrained 40-char hex strings, making exploitation impractical, but the pattern should be aligned with the safer approach already used in action.yml.
    Remediation: Use jq -r --arg sha "${WORKFLOW_SHA}" '.[] | select(.commit.sha == $sha) | .name' instead of inlining into the --jq expression.

Labels: PR modifies CI workflows, dispatch version resolution, and CLI install logic to fix a version skew bug.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/ci CI pipelines and checks component/dispatch Workflow dispatch and triggers component/install CLI install and app setup type/bug Confirmed defect in existing behavior labels Jul 20, 2026
@rh-hemartin
rh-hemartin force-pushed the hemartin/resolve-sha-to-release branch from eedfa3e to a8886ed Compare July 21, 2026 11:58
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 21, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:59 AM UTC · Completed 12:16 PM UTC
Commit: a8886ed · View workflow run →

@rh-hemartin rh-hemartin changed the title fix(version): resolve CLI version from reusable workflow ref fix(version)!: resolve CLI version from reusable workflow ref Jul 21, 2026

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Multi-agent review (3 agents: Claude ×2, Grok). The 5 previously-flagged issues from the earlier review round are confirmed fixed in this diff and not re-flagged. 3 unique findings posted inline; the following medium+ findings don't anchor to a diff hunk in this repo, so noted here:

[HIGH] — Root action.yml's "Download release binary" step (~line 187-239) has no fallback if the resolved release lacks the runner's OS/arch asset. install-fullsend-cli/action.yml's equivalent step got continue-on-error: true + a source-build fallback in the prior review round; this step wasn't touched by this PR but is now reached far more often since the default version resolves to an arbitrary historical job.workflow_sha instead of always-well-covered "latest". Suggest mirroring the same continue-on-error + outcome-gated fallback here.

[MEDIUM] — The primary production caller, fullsend-ai/.fullsend, hardcodes fullsend_version: main in all 6 stage workflows (code/triage/review/fix/retro/prioritize), so inputs.fullsend_version || job.workflow_sha always evaluates to "main" there — this PR's stated fix for #3369 has no effect on the org's actual production install path unless .fullsend is separately updated to drop that override. Worth a follow-up PR/issue against fullsend-ai/.fullsend.

[MEDIUM] (premature-decision) — SHA→tag resolution and OS/arch mapping logic are duplicated verbatim across action.yml and install-fullsend-cli/action.yml with no shared source. This is the second time in this PR's own review history the same bug had to be patched in both places (the jq-injection fix was one bug fixed twice in the prior round). Suggest extracting a shared script both action files can source.

[MEDIUM] (premature-decision) — Only 1 of 4 items in the PR's own test plan is checked off. The core new behavior (a real SHA resolving to its tag and downloading the prebuilt binary) hasn't been demonstrated end-to-end — only the "no match, fall back to source" path has been exercised. Suggest completing the checklist before merge.

Comment thread action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
@rh-hemartin

Copy link
Copy Markdown
Member Author

Opened #5511 to address the duplication and the creation of a shared lib.

@rh-hemartin
rh-hemartin force-pushed the hemartin/resolve-sha-to-release branch from a8886ed to ad0c08b Compare July 23, 2026 08:53
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 23, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 8:55 AM UTC · Ended 8:56 AM UTC
Commit: ad0c08b · View workflow run →

Default fullsend_version to "" across all reusable workflows so callers
that omit it resolve to job.workflow_sha instead of "latest". In the
install action, resolve the SHA to a release tag via the GitHub API and
download the GoReleaser artifact, falling back to source build for
untagged commits or download failures.

Harden the install action: paginate tag lookups, use safe jq
parameterization, derive OS/arch from runner context instead of
hardcoding linux, and add a source-build fallback when the release
download fails.

Closes #3369

BREAKING CHANGE: fullsend_version in reusable workflows now defaults to
the workflow SHA instead of "latest". Callers that omit fullsend_version
and want the previous behavior should pass fullsend_version: "latest"
explicitly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Hector Martinez <hemartin@redhat.com>
@rh-hemartin
rh-hemartin force-pushed the hemartin/resolve-sha-to-release branch from ad0c08b to 0e86cb3 Compare July 23, 2026 08:56
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 23, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:58 AM UTC · Completed 9:15 AM UTC
Commit: 0e86cb3 · View workflow run →

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.

Comment thread action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ci CI pipelines and checks component/dispatch Workflow dispatch and triggers component/install CLI install and app setup requires-manual-review Review requires human judgment type/bug Confirmed defect in existing behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fullsend_version defaulting to 'latest' in reusable workflows creates version skew with action tags

2 participants