Skip to content

refactor(install): moved logic from action.yml to composite action - #5792

Closed
rh-hemartin wants to merge 1 commit into
mainfrom
refactor/5511-install-lib
Closed

refactor(install): moved logic from action.yml to composite action#5792
rh-hemartin wants to merge 1 commit into
mainfrom
refactor/5511-install-lib

Conversation

@rh-hemartin

Copy link
Copy Markdown
Member

Summary

Moved logic from the base action.yml that installed the Fullsend CLI to the composite action 'install-fullsend-cli'.

Related Issue

Related to #5511 .

Changes

  • Moved logic from the base action.yml that installed the Fullsend CLI to the composite action 'install-fullsend-cli'.

Testing

  • Manual test required, not done for now. Review as usual. I will include results another day.

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — human and human-directed agent sessions only
  • I wrote this contribution myself and can explain all changes in it

@rh-hemartin
rh-hemartin requested a review from a team as a code owner July 31, 2026 10:16
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Refactor Fullsend CLI install into install-fullsend-cli composite action

✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Delegate Fullsend CLI installation to the install-fullsend-cli composite action.
• Add explicit version input and improve tag/SHA resolution for upstream installs.
• Simplify root action.yml to only decide vendored vs upstream mode.
Diagram

graph TD
  A["Fullsend action (action.yml)"] --> B{Vendored binary?} -->|"yes"| C["install-fullsend-cli (vendored)"] --> D["fullsend on PATH"]
  B -->|"no"| E["install-fullsend-cli (upstream)"] --> F[/"GitHub API"/] --> G["Download release or build"] --> D

  subgraph Legend
    direction LR
    _act["Action step"] ~~~ _dec{Decision} ~~~ _ext[/"External API"/]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extract install logic into a versioned bash script
  • ➕ Improves readability vs large inline YAML heredocs
  • ➕ Easier local testing and reuse across actions/workflows
  • ➕ Simpler diffs for future changes
  • ➖ Requires packaging/distribution decisions (pathing, permissions)
  • ➖ Still limited testability compared to a compiled/JS action
2. Convert installer to a JS action
  • ➕ Better structure and unit test support
  • ➕ Clearer error handling and cross-platform logic
  • ➖ Adds Node runtime dependency and maintenance surface
  • ➖ May be overkill for incremental refactor

Recommendation: The PR’s approach (delegate from root action.yml into a dedicated composite action) is a good incremental refactor that reduces duplication and centralizes install behavior. Consider a follow-up to move the long bash logic into a script for maintainability/testing, and confirm whether removing the previously-defined fullsend-path output is acceptable for any existing consumers of the composite action.

Files changed (2) +55 / -267

Refactor (2) +55 / -267
action.ymlAdd version input and expand upstream tag/SHA resolution +34/-20

Add version input and expand upstream tag/SHA resolution

• Adds a version input and updates upstream resolution to handle 'latest', explicit tags, and 40-char SHAs. Adjusts release asset naming to derive from the resolved tag and removes the previously exposed fullsend-path output wiring.

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

action.ymlReplace inline Fullsend CLI install flow with composite action call +21/-247

Replace inline Fullsend CLI install flow with composite action call

• Removes the large inline install implementation and replaces it with a small mode detector (vendored vs upstream). Delegates installation to the install-fullsend-cli composite action, passing mode, vendored path, workflow repo/SHA, token, and version.

action.yml

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:18 AM UTC · Completed 10:39 AM UTC
Commit: 1386169 · View workflow run →

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@qodo-code-review

qodo-code-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 54 rules

Grey Divider


Action required

1. Broken nested action path ✗ Dismissed 🐞 Bug ≡ Correctness
Description
The main composite action references a local action at
./defaults/.github/actions/install-fullsend-cli, but that directory does not exist in this repo.
This will fail action execution because the nested action cannot be resolved.
Code

action.yml[R90-92]

+    - name: Install Fullsend CLI with mode
+      uses: ./defaults/.github/actions/install-fullsend-cli
      with:
-        go-version-file: ${{ runner.temp }}/fullsend-src/go.mod
-        cache-dependency-path: ${{ runner.temp }}/fullsend-src/go.sum
-
-    - name: Build fullsend from source
-      if: steps.detect.outputs.install-method == 'source' || steps.download-release.outcome == 'failure'
-      shell: bash
-      run: |
-        set -euo pipefail
-        mkdir -p "${RUNNER_TEMP}/fullsend"
-        cd "${RUNNER_TEMP}/fullsend-src"
-        make go-build
-        cp bin/fullsend "${RUNNER_TEMP}/fullsend/fullsend"
-        echo "${RUNNER_TEMP}/fullsend" >> "${GITHUB_PATH}"
-
-    - name: Print fullsend version
-      shell: bash
-      run: fullsend --version
Relevance

●●● Strong

Broken local action paths/.defaults wiring has been flagged before; fixes to ensure referenced paths
exist are typically accepted.

PR-#2919
PR-#586

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
action.yml points to ./defaults/... while the installer action in this repo lives under
.github/actions/install-fullsend-cli/, so the referenced path cannot be found.

action.yml[88-99]
.github/actions/install-fullsend-cli/action.yml[1-35]

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` calls a local composite action via `uses: ./defaults/.github/actions/install-fullsend-cli`, but the repository contains the installer action at `.github/actions/install-fullsend-cli/` and has no `defaults/` directory. This makes the Fullsend action fail when it reaches the install step.

### Issue Context
The repo contains the installer action at `.github/actions/install-fullsend-cli/action.yml`.

### Fix Focus Areas
- action.yml[90-92]

### Suggested fix
Change the `uses:` path to the actual location, e.g.:
- `uses: ./.github/actions/install-fullsend-cli`

Then verify that the nested action resolves correctly in a workflow run.

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


2. Bare version tag mismatch ✓ Resolved 🐞 Bug ≡ Correctness
Description
The installer treats any non-40-char version as an exact release tag (tag=${VERSION}), so a
documented input like 0.0.1 will attempt to download tag 0.0.1 instead of normalizing to
v0.0.1. This breaks the main action’s documented version contract and is inconsistent with the
installer’s own v-prefixed tag matching logic.
Code

.github/actions/install-fullsend-cli/action.yml[R101-106]

+        # If version does not resemble a long-form SHA, set it as tag
+        if [[ ! "${VERSION}" =~ ^[0-9a-f]{40}$ ]]; then
+          echo "::debug::Version '${VERSION}' is not latest' and it does not resemble a long-form SHA, passing it as s tag."
+          echo "tag=${VERSION}" >> "${GITHUB_OUTPUT}"
+          exit 0
+        fi
Relevance

●●● Strong

Likely treated as a correctness regression vs documented version inputs; normalization to v-prefixed
tags is low-risk.

PR-#5357

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The main action promises bare versions like 0.0.1, but the installer returns tag=${VERSION}
unchanged. The same installer only considers vX.Y.Z tags when mapping SHAs, indicating v-prefixed
tags are expected.

action.yml[15-18]
.github/actions/install-fullsend-cli/action.yml[101-106]
.github/actions/install-fullsend-cli/action.yml[120-124]

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

### Issue description
`install-fullsend-cli` emits `steps.resolve-tag.outputs.tag` as the provided `inputs.version` for any non-SHA value (except `latest`). This breaks the main action’s documented support for bare semver like `0.0.1`, because the repo’s canonical tags appear to be `vX.Y.Z`.

### Issue Context
The main action input docs explicitly say `0.0.1` is acceptable. The installer’s SHA→tag resolution filters tags using a `^v...$` semver pattern, implying v-prefixed tags are canonical.

### Fix Focus Areas
- .github/actions/install-fullsend-cli/action.yml[101-106]
- .github/actions/install-fullsend-cli/action.yml[120-124]
- action.yml[15-18]

### Suggested fix
In the non-SHA version branch:
1. If `VERSION` matches `^[0-9]+\.[0-9]+\.[0-9]+$`, prefix it to `v${VERSION}` before writing `tag=...`.
2. Consider guarding the branch with `-n "${VERSION}"` so empty version doesn’t get treated as an explicit tag.

Keep using `${TAG#v}` for asset naming so assets still use the non-v version component.

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


3. Wrong install repository 🐞 Bug ≡ Correctness
Description
The main action passes workflow_repository/workflow_sha from the job context into the installer,
which for documented direct usage (uses: fullsend-ai/fullsend@v0) refers to the caller
repo/workflow, not the Fullsend repo. The installer then queries/downloads releases (and possibly
clones/builds) from that wrong repository, breaking direct usage.
Code

action.yml[R95-97]

+        workflow_repository: ${{ job.workflow_repository }}
+        workflow_sha: ${{ job.workflow_sha }}
+        github_token: ${{ inputs.github_token }}
Relevance

●● Moderate

Could be intentional for per-org/per-repo defaults (caller repo), but may break direct uses; no
clear precedent.

PR-#2919

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The main action explicitly forwards job.workflow_repository/job.workflow_sha into the installer,
while docs show the action is intended to be used directly in arbitrary repos. The installer uses
WORKFLOW_REPOSITORY for gh api and gh release download, so passing the caller repo will query
the wrong releases/source.

action.yml[90-98]
docs/guides/user/building-custom-agents.md[504-508]
.github/actions/install-fullsend-cli/action.yml[50-55]
.github/actions/install-fullsend-cli/action.yml[85-99]
.github/actions/install-fullsend-cli/action.yml[136-177]

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` forwards `workflow_repository: ${{ job.workflow_repository }}` and `workflow_sha: ${{ job.workflow_sha }}` into the Fullsend CLI installer. In normal/direct action usage, these values describe the *caller* workflow repository, but the installer uses `workflow_repository` to fetch releases and to clone/build source.

### Issue Context
The documentation includes direct usage (`uses: fullsend-ai/fullsend@v0`). In that scenario, using the caller repo for releases/source is incorrect and will fail.

### Fix Focus Areas
- action.yml[93-98]

### Suggested fix
Pass the action repository/ref (or hardcode the Fullsend repo) instead of job workflow context. For example:
- `workflow_repository: ${{ github.action_repository }}`
- `workflow_sha: ${{ github.action_ref }}`

If you still need the reusable-workflow pin behavior, use `job.workflow_repository/sha` only when they are set to the Fullsend reusable workflow context, otherwise fall back to `github.action_repository/action_ref`.

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



Remediation recommended

4. Latest tag no retries ✓ Resolved 🐞 Bug ☼ Reliability
Description
Latest-tag resolution uses a single gh api call without the retry() helper defined in the same
step. Transient GitHub API/network failures will now fail the action instead of retrying, unlike
other API calls in this script.
Code

.github/actions/install-fullsend-cli/action.yml[R85-90]

+        if [[ "${VERSION}" == "latest" ]]; then
+          echo "::debug::Version received is latest, resolving it to a real tag"
+          TAG=$(gh api "repos/${WORKFLOW_REPOSITORY}/releases/latest" --jq '.tag_name') || {
+            echo "::error::Could not resolve latest release tag"
+            exit 1
+          }
Relevance

●●● Strong

Team tends to harden GHA scripts; adding retry to releases/latest matches existing retry pattern in
installer.

PR-#5357

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The step defines retry() but does not use it for the releases/latest call, while later gh api
calls are wrapped by retry.

.github/actions/install-fullsend-cli/action.yml[57-76]
.github/actions/install-fullsend-cli/action.yml[85-90]
.github/actions/install-fullsend-cli/action.yml[111-123]

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 `latest` resolution path calls `gh api .../releases/latest` once and hard-fails on errors, even though a `retry()` helper is defined and used elsewhere in the same script.

### Issue Context
The same step already wraps other `gh api` calls with `retry`, so this is an inconsistency that reduces resilience.

### Fix Focus Areas
- .github/actions/install-fullsend-cli/action.yml[57-90]

### Suggested fix
Change:
- `TAG=$(gh api "repos/${WORKFLOW_REPOSITORY}/releases/latest" --jq '.tag_name')`

To:
- `TAG=$(retry gh api "repos/${WORKFLOW_REPOSITORY}/releases/latest" --jq '.tag_name')`

and keep the existing error handling if `TAG` is empty.

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


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread action.yml
Comment thread action.yml Outdated
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 31, 2026

Copy link
Copy Markdown

Review

Findings

High

  • [logic-error] action.yml — The "Install Fullsend CLI with mode" step passes repository: ${{ job.workflow_repository }} and sha: ${{ job.workflow_sha }} without fallbacks. When the root action is used directly by an external repo (e.g., uses: fullsend-ai/fullsend@v0), job.workflow_repository and job.workflow_sha evaluate to empty strings. These explicitly-passed empty values override the composite action's defaults (${{ github.repository }} and ${{ github.sha }}), causing downstream API calls (e.g., gh api "repos//releases/latest") to fail. The checkout step in the same file correctly uses the fallback pattern: repository: ${{ job.workflow_repository || github.repository }}.
    Remediation: Add || github.repository and || github.sha fallbacks to match the checkout step pattern.

Medium

  • [breaking-change] .github/actions/install-fullsend-cli/action.yml:13 — The composite action inputs were renamed from workflow_repository/workflow_sha to repository/sha. This composite action is vendored into customer repos via the scaffold manifest. When customers upgrade, workflows passing old input names will silently receive default values instead of intended values, potentially building from the wrong repository or commit SHA.
    Remediation: Add backward-compatible input aliases or coordinate the rename with a vendor-content update cycle.

  • [protected-path] .github/actions/install-fullsend-cli/action.yml, .github/workflows/reusable-dispatch.yml — This PR modifies files under .github/, which is a protected path. The PR links to Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 and explains the rationale for the changes. Human approval is always required for protected-path changes.

Low

  • [scope-mismatch] action.yml — Issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 authorizes extracting shared install helpers into a shared library pattern. This PR implements one-way delegation where action.yml depends entirely on the composite action via .defaults/ sparse checkout — a different approach. The PR uses "Related to Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511" rather than "Fixes", signaling partial alignment.

  • [architectural-coherence] action.yml — The root action.yml now delegates to the composite action via .defaults/ sparse checkout, creating a new dependency direction. The .defaults/ sparse checkout pattern is already established in reusable workflows across the repository.

  • [input-naming-convention] .github/actions/install-fullsend-cli/action.yml — Renamed inputs use bare generic names (repository, sha) which differ from the qualified naming pattern used in sibling composite actions (source_repo, gcp_wif_provider, mint_url, install_mode).

  • [gha-workflow-command-injection] .github/actions/install-fullsend-cli/action.yml — The VERSION input is written to GITHUB_OUTPUT without newline sanitization at the catch-all branch. The semver and SHA code paths are protected by strict regex, but the catch-all path passes arbitrary VERSION strings directly. Current callers pass trusted values, but this violates defense-in-depth.

  • [api-documentation] action.yml:17 — The root action's version input description removed bare semver 0.0.1 as an accepted format, but the composite action code still handles it via regex that prepends v. Docs-code discrepancy.

  • [edge-case] .github/actions/install-fullsend-cli/action.yml — The resolve-tag step outputs sha only on the long-form-SHA code path. When VERSION is "latest" or semver, the step exits early without emitting a sha output. The clone step's steps.resolve-tag.outputs.sha || inputs.sha fallback prevents breakage, but a future change could miss this dependency.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run

Review

Findings

Critical

  • [logic-error] action.yml:96 — The composite action reference uses: ./defaults/.github/actions/install-fullsend-cli uses path defaults without a dot prefix. Every workflow in this repository checks out the fullsend repo to .defaults (with dot prefix, via path: .defaults). The root action.yml is invoked by stage jobs as uses: ./.defaults/, and the ./defaults/ path resolves to $GITHUB_WORKSPACE/defaults/ which does not exist. This causes an action-not-found error for every invocation of the root action.yml.
    Remediation: Change to uses: ./.defaults/.github/actions/install-fullsend-cli.

High

  • [logic-error] .github/actions/install-fullsend-cli/action.yml:124 — When VERSION is empty (the default for callers that don't pass version, including reusable-dispatch.yml's harness-dispatch job) and SHA is non-empty, the version resolution logic falls through all guards (lines 81, 87, 104, 117) to line 124 where SHA="${VERSION}" unconditionally overwrites SHA with the empty VERSION value. This wipes the valid SHA, causing tag resolution to fail and forcing every harness-dispatch upstream install into a source build instead of downloading the pre-built release binary.
    Remediation: Guard the SHA override: if [[ -n "${VERSION}" ]]; then SHA="${VERSION}"; fi.

Medium

  • [logic-error] .github/actions/install-fullsend-cli/action.yml:207 — When the version input is a 40-char SHA that differs from inputs.sha, the resolve-tag step overrides the script-local SHA variable, but the clone step uses SHA: ${{ inputs.sha }} — the original action input. If no release tag is found for the version SHA, the source build clones the wrong commit.
    Remediation: Output the resolved SHA from the resolve-tag step and consume it in the clone step.

  • [scope-mismatch] action.yml:95 — Issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 authorizes extracting shared install helpers into a shared library (.github/scripts/fullsend-install-lib.sh). This PR instead makes action.yml delegate entirely to the composite action — a fundamentally different approach (one-way delegation vs. shared library). No update to Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 documents or seeks authorization for the alternative approach.
    Remediation: Update issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 with the delegation approach or implement the shared-library approach.

  • [breaking-change] .github/actions/install-fullsend-cli/action.yml:8 — The composite action inputs workflow_repository and workflow_sha were renamed to repository and sha. The composite action is vendored into customer repos via the scaffold manifest. GitHub Actions silently ignores unrecognized inputs, so callers still passing old names will receive default values instead of their intended values, causing incorrect behavior.
    Remediation: Keep old names as aliases or coordinate the rename with a vendor-content update cycle.

  • [protected-path] .github/actions/install-fullsend-cli/action.yml, .github/workflows/reusable-dispatch.yml — This PR modifies files under .github/, which is a protected path. The PR links to Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 and explains the rationale for the changes. Human approval is always required for protected-path changes.

Low

  • [architectural-coherence] action.yml:95 — The root action.yml was a self-contained entry point. This PR inverts the dependency, making it delegate to the composite action via the .defaults/ sparse-checkout layer.

  • [scope-creep] .github/actions/install-fullsend-cli/action.yml:19 — A new version input and substantial version-resolution logic were added. Issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 does not explicitly authorize adding new inputs or restructuring version resolution.

  • [input-naming-convention] .github/actions/install-fullsend-cli/action.yml:13 — Renamed inputs use bare generic names (repository, sha, version) which break the naming convention established across sibling composite actions that use qualified names (source_repo, gcp_wif_provider, etc.).

  • [gha-workflow-command-injection] .github/actions/install-fullsend-cli/action.yml:119 — Raw VERSION input is written to GITHUB_OUTPUT without newline sanitization at lines 112 and 119. While current callers pass trusted values, this violates defense-in-depth for the composite action's input contract.

  • [breaking-change] .github/actions/install-fullsend-cli/action.yml:23 — The composite action's fullsend-path output was removed. No internal consumers reference this output (the binary is available via GITHUB_PATH), so impact is limited.

  • [api-documentation] action.yml:17 — The root action's version input description removed bare semver 0.0.1 as an accepted format, but the code still handles it via the regex that prepends v. Docs-code discrepancy.

  • [description-stale-reference] .github/actions/install-fullsend-cli/action.yml:3 — Top-level description says "from the reusable workflow repository at sha" — the text "reusable workflow repository" is inconsistent with the new generic input name repository.


Labels: PR modifies CI install actions and workflow files


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (2)

Review

Findings

Critical

  • [logic-error] action.yml:96 — The composite action reference uses: ./defaults/.github/actions/install-fullsend-cli uses path defaults without a dot prefix. Every reusable workflow in this repository checks out the fullsend repo to .defaults (with dot prefix), and no checkout creates a defaults/ directory. This path will not exist at runtime, causing an action-not-found error for every invocation of the root action.yml.
    Remediation: Change to uses: ./.defaults/.github/actions/install-fullsend-cli.

High

  • [logic-error] .github/actions/install-fullsend-cli/action.yml:100 — When VERSION is empty (its default for all existing callers in reusable-dispatch.yml), the regex check [[ ! "${VERSION}" =~ ^[0-9a-f]{40}$ ]] matches empty string, causing tag="" to be written to GITHUB_OUTPUT and an early exit. This bypasses the entire SHA-to-tag resolution logic, so all upstream-mode installs will skip the release download and fall through to unnecessary source builds.
    Remediation: Guard with a non-empty test: if [[ -n "${VERSION}" && ! "${VERSION}" =~ ^[0-9a-f]{40}$ ]]; then.

  • [scope-mismatch] action.yml:67 — Issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 proposes extracting shared install helpers into a library file (.github/scripts/fullsend-install-lib.sh) that both action files would source. This PR instead moves all logic from action.yml into the composite action, creating a one-way delegation rather than the authorized shared-library approach.
    Remediation: Either implement the shared-library approach described in Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511, or update the issue to document and seek authorization for the delegation approach.

Medium

  • [missing-retry] .github/actions/install-fullsend-cli/action.yml:88 — The gh api call to resolve the 'latest' release tag lost its retry wrapper. The old code used TAG=$(retry gh api ...). The retry function is defined in the same script block and used for other API calls.
    Remediation: Wrap in the existing retry function: TAG=$(retry gh api "repos/${WORKFLOW_REPOSITORY}/releases/latest" --jq '.tag_name').

  • [architectural-coherence] action.yml:70 — The composite action .github/actions/install-fullsend-cli was designed for consumption by reusable workflows (per ADR 0031). This PR inverts the dependency by making the root action.yml delegate to it. See also: [scope-mismatch] finding above.

  • [scope-creep] .github/actions/install-fullsend-cli/action.yml:19 — A new version input and restructured version resolution logic were added. Issue Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 does not authorize adding new inputs or restructuring version resolution — it proposes extracting shared helpers.

  • [protected-path] .github/actions/install-fullsend-cli/action.yml — This PR modifies files under .github/, which is a protected path. While the PR links to Extract shared fullsend install helpers from action.yml and install-fullsend-cli #5511 and explains the rationale, human approval is always required for protected-path changes.

Low

  • [gha-workflow-command-injection] .github/actions/install-fullsend-cli/action.yml — Raw VERSION input is written to GITHUB_OUTPUT without newline sanitization (echo "tag=${VERSION}" >> "${GITHUB_OUTPUT}"). While VERSION originates from trusted workflow callers, this violates defense-in-depth.

  • [breaking-change] .github/actions/install-fullsend-cli/action.yml:23 — The composite action's fullsend-path output was removed. No internal consumers reference this output (the binary is available via GITHUB_PATH), so impact is limited.

  • [message-formatting] .github/actions/install-fullsend-cli/action.yml:103 — Debug message has typo ("s tag" should be "a tag") and mismatched single quotes.

  • [message-formatting] .github/actions/install-fullsend-cli/action.yml:81 — Warning message ends with a period, inconsistent with existing messages in the same file.


Labels: PR modifies CLI install logic in action.yml and .github/actions/install-fullsend-cli/


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added component/install CLI install and app setup component/ci CI pipelines and checks labels Jul 31, 2026
Comment thread action.yml
@rh-hemartin
rh-hemartin force-pushed the refactor/5511-install-lib branch from 1386169 to 1112ae1 Compare August 3, 2026 10:30
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:31 AM UTC · Completed 10:51 AM UTC
Commit: 1112ae1 · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

Moved logic from the base action.yml that installed the Fullsend
CLI to the composite action 'install-fullsend-cli'.

The issue for this recommended to create script, which I agree
but I'm tending to do smaller changes for better reviews
cycles.

Signed-off-by: Hector Martinez <hemartin@redhat.com>
@rh-hemartin
rh-hemartin force-pushed the refactor/5511-install-lib branch from 1112ae1 to b09324b Compare August 3, 2026 11:55
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:56 AM UTC · Completed 12:36 PM UTC
Commit: b09324b · View workflow run →

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

Additional finding (not anchored to a diff line):

[MEDIUM] Substantial install control-flow refactor shipped with testing explicitly deferred

The PR body states: "Testing: [ ] Manual test required, not done for now. Review as usual. I will include results another day." This PR rewrites the install-mode decision tree across action.yml, install-fullsend-cli/action.yml, and reusable-dispatch.yml (repository/sha input renames, a new mode-detection step, a new cross-composite-action .defaults checkout, and restructured version→tag/sha resolution) — exactly the class of GitHub Actions context/expression logic that is hard to validate without a live run.

This isn't a theoretical risk: this review already surfaced one CRITICAL bug (direct/GHES install path is broken) and one HIGH bug (silent wrong-commit fallback on release-download failure) that a single live run of the direct-usage and "latest"-with-transient-failure paths would likely have caught.

Suggestion: before merging, run/add a test of the direct (non-workflow_call) invocation path (uses: fullsend-ai/fullsend@<branch-sha> from a plain workflow) and the reusable-dispatch.yml upstream path, and update the PR's Testing checklist with actual results rather than deferring them.

Comment thread action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
Comment thread .github/actions/install-fullsend-cli/action.yml
# Resolve 'latest' to the actual tag before checking the release API
if [[ "${VERSION}" == "latest" ]]; then
echo "::debug::Version received is latest, resolving it to a real tag"
TAG=$(retry gh api "repos/${REPOSITORY}/releases/latest" --jq '.tag_name') || {

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.

[MEDIUM] New hard dependency on the gh CLI for the primary install path, with no explicit check or documentation

Pre-PR action.yml's install-detection logic used raw curl against the GitHub REST API with a Bearer token, with no dependency on the gh CLI being present. Post-PR, the entire "upstream" install path (resolve-tag, release download, and tag lookup) uses gh api / gh release download throughout, first here and consistently through the rest of this step.

GitHub-hosted runners ship gh preinstalled, but this action explicitly targets Linux runners with Podman/rootless/cgroups v2/systemd configured (see the "Require Linux runner" and "Configure rootless Podman" steps in the root action.yml), which is consistent with custom/self-hosted runner images that are not guaranteed to have gh installed and previously did not need it.

Suggestion: Document the new gh CLI requirement prominently in the action's top-level description, or add an explicit command -v gh check that fails with a clear error message rather than an opaque "command not found" partway through the composite action.

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

2. Release download — the caller requests a specific version (`latest`,
a semver tag, or a 40-char SHA that resolves to a tagged release).
The action downloads the matching pre-built tarball from GitHub
Releases.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] breaking-change

The composite action inputs were renamed from workflow_repository/workflow_sha to repository/sha. This composite action is vendored into customer repos via the scaffold manifest. When customers upgrade, workflows passing old input names will silently receive default values instead of intended values, potentially building from the wrong repository or commit SHA.

Suggested fix: Add backward-compatible input aliases or coordinate the rename with a vendor-content update cycle.

2. Release download — the caller requests a specific version (`latest`,
a semver tag, or a 40-char SHA that resolves to a tagged release).
The action downloads the matching pre-built tarball from GitHub
Releases.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] input-naming-convention

Renamed inputs use bare generic names (repository, sha) which differ from the qualified naming pattern used in sibling composite actions (source_repo, gcp_wif_provider, mint_url, install_mode).

Comment thread action.yml
version:
description: >-
Release tag, version or long-form SHA: use latest, v0.0.1, 0.0.1 or a 40-char commit SHA.
Release tag, version or long-form SHA: use latest, v0.0.1 or a 40-char commit SHA.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] api-documentation

The root action's version input description removed bare semver 0.0.1 as an accepted format, but the composite action code still handles it via regex that prepends v. Docs-code discrepancy.

@rh-hemartin
rh-hemartin marked this pull request as draft August 3, 2026 14:48
@rh-hemartin

Copy link
Copy Markdown
Member Author

I'm taking a while to process the feedback, as it has given me a new perspective on this problem. Will update at some point this week hopefully.

@rh-hemartin rh-hemartin self-assigned this Aug 4, 2026
@rh-hemartin rh-hemartin closed this Sep 1, 2026
@fullsend-ai-retro

fullsend-ai-retro Bot commented Sep 1, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 10:17 AM UTC · Completed 10:30 AM UTC

Commit: b09324b · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.05

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #5792

Outcome: Closed without merging after 30 days. The PR refactored install logic from action.yml into a composite action, diverging from issue #5511's prescribed shared-library approach.

Review Agent Performance

The review agent ran 3 cycles and performed strongly on bug detection: all 6 critical/high findings were true positives confirmed and fixed by the author (missing dot prefix, empty VERSION bypass, SHA override wipe, missing retry wrapper, wrong SHA reference, missing direct-caller fallbacks). The challenger sub-agent improved precision in cycle 3 by downgrading weaker design-direction findings. Cost: ~$18.50 total across 3 cycles.

Human Review Delta

Human reviewer waynesun09 found several findings the agent missed:

  • CRITICAL: Checkout step falls back to github.repository (caller repo) instead of github.action_repository for direct/GHES usage
  • HIGH: Failed release download silently builds from the wrong commit when resolve-tag emits only a tag
  • MEDIUM: Linux-only OS guard removed without replacement, lost whitespace trimming on inputs, new hard dependency on gh CLI (replacing portable curl)
  • MEDIUM: Testing explicitly deferred in PR description — the review had already surfaced bugs that live testing would have caught

The agent partially overlapped on the direct-usage issue (cycle 3 HIGH), but the human caught deployment-mode-specific scenarios requiring deep GitHub Actions context-variable knowledge.

Dispatch Storm

26 individual COMMENTED reviews from the author (submitted via GitHub's single-comment button rather than batch review) triggered 34 dispatch runs on 2026-08-03. This likely contributed to the GCP WIF quota exhaustion (HTTP 429) that caused E2E test failure on run 30805849182.

Existing Issues — New Evidence

Proposals filed

Proposals skipped (target repo not allowed)

File manually or update create_issues.allow_targets in config.yaml:

  • Review agent should detect and escalate explicitly-deferred testing in PR descriptions (fullsend-ai/agents)

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/install CLI install and app setup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants