Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/_static-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ jobs:

- name: Test workflow helper scripts
run: python3 -m unittest discover -s .github/scripts -p 'test_*.py'

- name: Test release PR body renderer
run: node --test scripts/upstream-release/render-pr-body.test.mjs
11 changes: 11 additions & 0 deletions .github/workflows/_visual-regression.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,18 @@ jobs:
exit 1
fi

# The Cosign action expands its install path with envsubst.
- name: Install Cosign installer dependency
run: |
apt-get update
apt-get install -y --no-install-recommends gettext-base

- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Install ToolHive CLI
env:
TOOLHIVE_VERIFY_SIGNATURE: 'true'
run: ./scripts/install-thv.sh

# SWC's native loader rejects the writable parents of /github/home.
Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/update-visual-baselines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ on:
types: [created]

concurrency:
group: ${{ github.workflow }}-${{ github.event.issue.number }}
# Non-command comments get their own group and cannot preempt a request.
group: ${{ github.workflow }}-${{ github.event.issue.number }}-${{ startsWith(github.event.comment.body, '/update-snapshots') && 'request' || github.run_id }}
cancel-in-progress: true

permissions:
Expand Down Expand Up @@ -99,7 +100,18 @@ jobs:
exit 1
fi

# The Cosign action expands its install path with envsubst.
- name: Install Cosign installer dependency
run: |
apt-get update
apt-get install -y --no-install-recommends gettext-base

- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Install ToolHive CLI
env:
TOOLHIVE_VERIFY_SIGNATURE: 'true'
run: ./scripts/install-thv.sh

# SWC's native loader rejects the writable parents of /github/home.
Expand Down
320 changes: 6 additions & 314 deletions .github/workflows/upstream-release-docs.yml

Large diffs are not rendered by default.

37 changes: 31 additions & 6 deletions scripts/install-thv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ else
for profile in ~/.bashrc ~/.zshrc ~/.profile; do
if [[ -f "$profile" ]]; then
# Check if the PATH export already exists to avoid duplicates
# Keep the variables literal for the profile to expand at login.
# shellcheck disable=SC2016
if ! grep -q 'export PATH="$HOME/.local/bin:$PATH"' "$profile" 2>/dev/null; then
# shellcheck disable=SC2016
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$profile"
echo "Added ~/.local/bin to PATH in $profile"
fi
Expand All @@ -63,13 +66,35 @@ else
export PATH="$HOME/.local/bin:$PATH"
fi

# Download the release tarball and extract the binary
# Keep downloads isolated, and verify before extracting or executing the CLI.
DOWNLOAD_DIR=$(mktemp -d)
trap 'rm -rf "$DOWNLOAD_DIR"' EXIT

echo "Downloading ToolHive CLI release $RELEASE_VERSION"
curl -s -L "$RELEASE_TARBALL" -o /tmp/toolhive.tar.gz
tar -xzf /tmp/toolhive.tar.gz -C /tmp thv
chmod +x /tmp/thv
cp /tmp/thv "$INSTALL_DIR/thv"
rm -f /tmp/toolhive.tar.gz /tmp/thv
curl -fsSL "$RELEASE_TARBALL" -o "$DOWNLOAD_DIR/toolhive.tar.gz"

if [[ "${TOOLHIVE_VERIFY_SIGNATURE:-false}" == "true" ]]; then
command -v cosign >/dev/null 2>&1 || {
echo "Error: cosign is required for signature verification"
exit 1
}
BUNDLE_URL=$(echo "$RELEASE_JSON" | jq -r \
--arg version "$RELEASE_VERSION" \
'.assets[] | select(.name == "toolhive_" + $version + "_linux_amd64.tar.gz.sigstore.json") | .browser_download_url // empty')
if [[ -z "$BUNDLE_URL" ]]; then
echo "Error: signature bundle missing for release $RELEASE_VERSION"
exit 1
fi
curl -fsSL "$BUNDLE_URL" -o "$DOWNLOAD_DIR/toolhive.sigstore.json"
cosign verify-blob "$DOWNLOAD_DIR/toolhive.tar.gz" \
--bundle "$DOWNLOAD_DIR/toolhive.sigstore.json" \
--certificate-identity "https://github.com/stacklok/toolhive/.github/workflows/releaser.yml@refs/tags/v$RELEASE_VERSION" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
fi

tar -xzf "$DOWNLOAD_DIR/toolhive.tar.gz" -C "$DOWNLOAD_DIR" thv
chmod +x "$DOWNLOAD_DIR/thv"
cp "$DOWNLOAD_DIR/thv" "$INSTALL_DIR/thv"

thv version || {
echo "Installation failed: 'thv' command is not working."
Expand Down
28 changes: 28 additions & 0 deletions scripts/upstream-release/fixtures/release-1181-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"PROJECT_ID": "toolhive",
"NEW_TAG": "v0.51.4",
"PREV_TAG": "v0.51.1",
"REPO": "stacklok/toolhive",
"NOTE_BLOCK": "",
"GAPS_BLOCK": "",
"SUMMARY_BLOCK": "- Added `thv secret upgrade-protection` guidance in `docs/toolhive/guides-cli/secrets-management.mdx`, explaining when to migrate legacy encrypted stores to Argon2id and the one-way compatibility break.\n- Updated `docs/toolhive/guides-vmcp/tool-aggregation.mdx` to note that the `priority` strategy now drops every candidate in a tool-name collision when any conflicting backend is absent from `priorityOrder` (verified against `pkg/vmcp/aggregator/priority_resolver.go`).\n- Updated `docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx` and `docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx` to require each upstream provider's `redirectUri` to share the browser-facing authorize hostname (`issuer` or `authorizationEndpointBaseUrl`), because `/oauth/callback` binds each login to the browser that started it with a host-only cookie.",
"AUTOGEN_TOUCHED": "",
"CRD_PAGES_DIRS": "docs/toolhive/reference/crds",
"COMPARE_OK": "true",
"STANDIN_BLOCK": "@JAORMX (merged stacklok/toolhive#6127)",
"UNRESOLVED_BLOCK": "",
"UNRESOLVED_COUNT": "0",
"ASSIGN_LIST": "JAORMX,jhrozek,rdimitrov",
"FYI_COUNT": "0",
"OWNER": "JAORMX",
"OWNER_ASSIGNED": "true",
"OWNER_SOURCE": "merged release PR stacklok/toolhive#6728",
"SKILL_COMMIT_COUNT": "2",
"GEN_CONCLUSION": "success",
"REVIEW_CONCLUSION": "success",
"GEN_TURNS": "93",
"GEN_COST": "11.5335",
"REVIEW_TURNS": "36",
"REVIEW_COST": "2.8230",
"REFRESHED": "true"
}
61 changes: 61 additions & 0 deletions scripts/upstream-release/fixtures/release-1181-section.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!-- upstream-release-docs:start -->

## Docs update for `toolhive` v0.51.4

### At a glance

| | |
| --- | --- |
| **Upstream** | `stacklok/toolhive` [`v0.51.1` → `v0.51.4`](https://github.com/stacklok/toolhive/compare/v0.51.1...v0.51.4) |
| **Hand-written changes** | 2 commit(s) |
| **Reference assets** | refreshed (separate commit) |
| **Gaps** | 0 |
| **Owner** | @JAORMX - identified from merged release PR stacklok/toolhive#6728 |
| **Release contributors** | 3 review requested (see sidebar) |
| **Action required** | Spot-check skill-authored prose for accuracy |

### Who does what

@JAORMX cut this release and owns this PR: review your own changes, chase the remaining approvals, and merge once they're in. You don't need to wait on a review from anyone listed as having no docs impact below.

Everyone with a review request: the target is a review and approval within **2 business days**.

### Summary of changes

- Added `thv secret upgrade-protection` guidance in `docs/toolhive/guides-cli/secrets-management.mdx`, explaining when to migrate legacy encrypted stores to Argon2id and the one-way compatibility break.
- Updated `docs/toolhive/guides-vmcp/tool-aggregation.mdx` to note that the `priority` strategy now drops every candidate in a tool-name collision when any conflicting backend is absent from `priorityOrder` (verified against `pkg/vmcp/aggregator/priority_resolver.go`).
- Updated `docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx` and `docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx` to require each upstream provider's `redirectUri` to share the browser-facing authorize hostname (`issuer` or `authorizationEndpointBaseUrl`), because `/oauth/callback` binds each login to the browser that started it with a host-only cookie.

### Review routing

GitHub could not request the upstream contributor directly, so review went to the human merger of each relevant upstream PR:

- @JAORMX (merged stacklok/toolhive#6127)

### Run cost

| Session | Turns | Cost (USD) |
| --- | ---: | ---: |
| Generation | 93 | $11.5335 |
| Editorial review | 36 | $2.8230 |
| **Total** | **129** | **$14.3565** |

<details><summary>How this PR was built</summary>

Two Claude Opus sessions run per release: a generation pass
(`upstream-release-docs` skill, 6 phases) followed by a fresh-
context editorial pass (`docs-review`). Prettier/ESLint
auto-fixes are applied after.

Auto-synced paths — do not hand-edit these in review:
- `static/api-specs/`
- `docs/toolhive/reference/cli/` (toolhive only)
- `docs/toolhive/reference/crds/`

If a "Gaps needing human context" section is present above,
each entry includes a paste-ready **Helper prompt for local
Claude** a reviewer can use to resolve the gap.

</details>

<!-- upstream-release-docs:end -->
Loading
Loading