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
1 change: 0 additions & 1 deletion .envrc

This file was deleted.

73 changes: 39 additions & 34 deletions .github/actions/rho/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ inputs:
default: ""
github-token:
description: >-
Token used to post a PR comment when post-to is pr-comment.
Defaults to ${{ github.token }}.
Token used to look up the latest Rho release and, when post-to is
pr-comment, to post the PR comment. Defaults to ${{ github.token }}.
required: false
default: ${{ github.token }}
working-directory:
Expand All @@ -103,12 +103,16 @@ inputs:
default: ${{ github.workspace }}
rho-version:
description: >-
Rho release version/tag to install (e.g. v1.2.3 or latest).
Defaults to the ref this action was resolved at.
Rho release to install (e.g. 0.3.0 or v0.3.0), or latest. Defaults to
the release tag this action is pinned to (uses: ...@v0.3.0); a branch or
commit-SHA pin installs the latest release. Requires Rho v0.3.0 or later:
earlier tags predate the rename and have no rho_* archives.
required: false
default: ""
rho-repo:
description: Repository to install Rho from (owner/repo).
description: >-
Repository to install Rho from (owner/repo). The release archive's
cosign signature must come from that repository's release workflow.
required: false
default: GrayCodeAI/rho

Expand All @@ -126,6 +130,11 @@ outputs:
runs:
using: composite
steps:
# cosign verifies the release signature; install.sh runs with
# RHO_REQUIRE_COSIGN=1 so an unsigned or tampered release fails the step.
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Install Rho
id: install
shell: bash
Expand All @@ -134,47 +143,43 @@ runs:
RHO_VERSION_INPUT: ${{ inputs.rho-version }}
ACTION_REF: ${{ github.action_ref }}
ACTION_PATH: ${{ github.action_path }}
GH_TOKEN: ${{ inputs.github-token }}
RUNNER_TEMP: ${{ runner.temp }}
run: |
set -euo pipefail
if [ "${RUNNER_OS}" = "Windows" ]; then
echo "::error::The Rho action currently supports Linux and macOS runners only." >&2
exit 1
fi
# Resolve the version to install: explicit input wins; otherwise the ref
# this action was checked out at (a tag); otherwise the latest release.
if ! [[ "${RHO_REPO}" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
echo "::error::rho-repo must look like owner/repo." >&2
exit 2
fi
release_re='^v?[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'
# Resolve the version: explicit input wins; otherwise the release tag
# this action is pinned to; otherwise (branch or SHA pin) the latest
# release of rho-repo.
version="${RHO_VERSION_INPUT}"
if [ -z "${version}" ]; then
if [ -z "${version}" ] && [[ "${ACTION_REF}" =~ ${release_re} ]]; then
version="${ACTION_REF}"
fi
# A commit-SHA pin (github.action_ref is the 40-hex SHA) is not a release
# tag, so fall back to latest rather than fetching releases/download/v<sha>.
case "${version}" in
""|refs/*|*/*) version="latest" ;;
esac
if printf '%s' "${version}" | grep -qiE '^[0-9a-f]{40}$'; then
version="latest"
if [ -z "${version}" ] || [ "${version}" = "latest" ]; then
version="$(gh release view --repo "${RHO_REPO}" --json tagName --jq .tagName)"
fi
install_dir="${RUNNER_TEMP}/rho-bin"
src_dir="${RUNNER_TEMP}/rho-src"
mkdir -p "${install_dir}" "${src_dir}"
# Download the Rho source archive and extract it
if [ "${version}" = "latest" ]; then
tarball_url=$(curl -sL "https://api.github.com/repos/${RHO_REPO}/releases/latest" \
| grep '"tarball_url":' | sed 's/.*"\([^"]*\)".*/\1/')
else
tarball_url="https://github.com/${RHO_REPO}/archive/refs/tags/v${version}.tar.gz"
fi
curl -sL "${tarball_url}" | tar -xz -C "${src_dir}" --strip-components=1
# Build the Rho binary from source (Go must be available on the runner)
if ! command -v go &>/dev/null; then
echo "::error::Go is required but not found on the runner PATH. Add actions/setup-go before this action, or install Go manually." >&2
exit 1
if ! [[ "${version}" =~ ${release_re} ]]; then
echo "::error::rho-version must be a release version such as 0.3.0, or 'latest'." >&2
exit 2
fi
go build -o "${install_dir}/rho" "${src_dir}/cmd/rho"
chmod +x "${install_dir}/rho"
echo "${install_dir}" >> "${GITHUB_PATH}"
echo "Installed Rho from ${RHO_REPO}@${version}"
version="${version#v}"
# install.sh ships with this action at the same ref. It downloads the
# release archive and checksums.txt, verifies the cosign signature
# (required here) and the SHA-256, and installs under the prefix.
installer="$(cd "${ACTION_PATH}/../../.." && pwd)/install.sh"
prefix="${RUNNER_TEMP}/rho"
RHO_INSTALL_REPO="${RHO_REPO}" RHO_REQUIRE_COSIGN=1 \
sh "${installer}" --version "${version}" --prefix "${prefix}"
echo "${prefix}/bin" >> "${GITHUB_PATH}"
echo "Installed Rho ${version} from ${RHO_REPO}"

- name: Run Rho
id: run
Expand Down
28 changes: 5 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
fetch-depth: 0
- uses: ./.github/actions/checkout-flux
with:
ref: ${{ github.head_ref == 'feat/ecosystem-wiring-pr' && 'feat/ecosystem-wiring' || github.head_ref || github.ref_name }}
ref: ${{ github.head_ref || github.ref_name }}
- name: Generate ecosystem workspace
run: bash ./scripts/generate-workspace.sh
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
Expand Down Expand Up @@ -487,9 +487,6 @@ jobs:
matrix:
goos: [linux, darwin, windows]
goarch: [amd64, arm64]
exclude:
- goos: windows
goarch: arm64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand All @@ -507,26 +504,11 @@ jobs:
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: go build -trimpath -v ./...
- name: Binary size check (linux/amd64 only)
- name: Binary size budget (linux/amd64 only)
if: matrix.goos == 'linux' && matrix.goarch == 'amd64'
run: |
# Use -ldflags="-s -w" to match release build size (Makefile LDFLAGS).
# This catches binary bloat regressions against the actual shipped artifact size.
size=$(go build -trimpath -ldflags="-s -w" -o /tmp/rho-bin ./cmd/rho && wc -c < /tmp/rho-bin)
size_mb=$((size / 1024 / 1024))
echo "Binary size: ${size_mb}MB"
# Threshold history: 110MB → 80MB (binary was ~76MB) → 98MB.
# The 80MB line became stale: the audit-sweep merges (swift
# rebrand, harrier at-rest encryption, engine features) grew the
# release binary to ~95MB (linux/amd64, -trimpath -ldflags="-s -w").
# Re-baselined to 98MB (3MB headroom) so this check detects new
# bloat regressions instead of warning on every run. A real size
# reduction (e.g. swapping modernc.org/sqlite for cgo sqlite,
# lazy-loading WASM/CEL) is tracked separately.
if [ "$size_mb" -gt 98 ]; then
echo "::warning::Binary size ${size_mb}MB exceeds 98MB threshold"
fi
rm -f /tmp/rho-bin
# Builds bin/rho with the release ldflags (-s -w) and fails when it
# exceeds SIZE_LIMIT_MB in the Makefile — the single source of the budget.
run: make size-check

# -------------------------------------------------------------------------
# Fuzz — short corpus runs to catch panics in fuzz targets.
Expand Down
79 changes: 45 additions & 34 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Canonical release workflow for GrayCodeAI Go binary repos.
# Triggered by release-please when it pushes a v* tag.
# Release workflow for rho. A maintainer pushes a v<VERSION> tag after the
# release PR (VERSION + CHANGELOG) has merged; creating v* tags is restricted by
# the repository ruleset "protect-release-tags". See docs/RELEASING.md.
# Source of truth: .shared-templates/workflows/go-release.yml.tmpl

name: release
Expand All @@ -9,66 +10,76 @@ on:
tags: ["v*"]

permissions:
contents: write
packages: write
id-token: write # for cosign keyless signing if enabled later
contents: write # create the GitHub release and upload its assets
id-token: write # cosign keyless signing (GitHub OIDC -> Sigstore Fulcio)

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
goreleaser:
runs-on: ubuntu-latest
env:
GOPROXY: "https://proxy.golang.org,direct"
# Release builds resolve every dependency (including flux) from
# go.mod/go.sum through the public proxy — never from sibling checkouts.
GOWORK: "off"
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # goreleaser needs full history for changelog
persist-credentials: false

# Releases build against the sibling repos resolved via the workspace go.work.
- uses: ./.github/actions/checkout-flux
with:
ref: ${{ github.ref_name }}
# Refuses a tag that disagrees with VERSION or has no CHANGELOG section,
# and extracts that section as the release notes.
- name: Check tag against VERSION and CHANGELOG
run: bash ./scripts/check-release-tag.sh --notes "${RUNNER_TEMP}/release-notes.md" "${GITHUB_REF_NAME}"

- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.6"
cache: true

- name: Refuse local replace directives
run: bash ./scripts/check-no-replace-directives.sh

# GoReleaser shells out to syft for the `sboms:` stanza; the runner image
# does not ship it.
- name: Install syft
uses: anchore/sbom-action/download-syft@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2

# GoReleaser shells out to cosign for the `signs:` stanza (keyless
# signature over checksums.txt, uploaded as checksums.txt.sigstore.json).
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1
with:
distribution: goreleaser
# Must match a real goreleaser release — verify at
# https://github.com/goreleaser/goreleaser/releases before bumping.
version: "v2.17.0"
args: release --clean
args: release --clean --release-notes=${{ runner.temp }}/release-notes.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Optional secrets used by some repos' goreleaser configs:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}

# Sign release artifacts with cosign keyless signing. The
# id-token: write permission above enables OIDC federation with
# Fulcio's root CA — no long-lived signing keys to manage.
- name: Install cosign
uses: sigstore/cosign-installer@d8a3f51ef971a853e51de6231a89f4483c5a7a0e # v3.4.0

- name: Sign release checksums with cosign
- name: Verify the published signature
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
# Download the checksums artifact produced by goreleaser.
gh release download "${GITHUB_REF_NAME}" --pattern "checksums.txt" -D dist/
# Sign with keyless OIDC — output is dist/checksums.txt.sig (bundle).
cosign sign-blob \
--yes \
--output-signature dist/checksums.txt.sig \
--output-certificate dist/checksums.txt.cert \
dist/checksums.txt
# Upload the signature and certificate back to the release.
gh release upload "${GITHUB_REF_NAME}" \
dist/checksums.txt.sig \
dist/checksums.txt.cert
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Re-download what users will download and verify it the way
# install.sh does, so a broken signature fails this run loudly.
verify_dir="$(mktemp -d)"
gh release download "${GITHUB_REF_NAME}" --repo "${GITHUB_REPOSITORY}" \
--pattern checksums.txt --pattern checksums.txt.sigstore.json \
--dir "${verify_dir}"
cosign verify-blob \
--bundle "${verify_dir}/checksums.txt.sigstore.json" \
--certificate-identity "https://github.com/${GITHUB_REPOSITORY}/.github/workflows/release.yml@${GITHUB_REF}" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"${verify_dir}/checksums.txt"
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Ignore build output in bin/, but track committed source scripts like bin/buf.
bin/*
!bin/buf
# GoReleaser output (goreleaser release --snapshot / make release).
/dist/
rho_bin
*.exe
*.dll
Expand Down Expand Up @@ -38,10 +40,12 @@ coverage.html
CODE_REVIEW_REPORT.md
review_report.md

# Workspace checksum file — regenerated by `make setup` / `go work sync`;
# deleted and regenerated by the Dockerfile and flake.nix builds.
# Workspace checksum file — regenerated by `make setup` / `go work sync`.
go.work.sum

# Local direnv file (may hold personal keys for `make test-live`).
/.envrc

# Lefthook-generated git hook wrappers
.githooks/
__pycache__/
Expand Down
Loading
Loading