Files
onyx/.github/workflows/release-cli.yml
T
dependabot[bot] 5f18eb94c5 chore(deps): bump docker/setup-buildx-action from 4.1.0 to 4.2.0 (#13040)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 22:49:59 +00:00

342 lines
12 KiB
YAML

name: Release CLI
on:
push:
tags:
- "cli/v*.*.*"
jobs:
pypi:
runs-on: ubuntu-latest
environment:
name: release-cli
permissions:
contents: read # needed to checkout the repo on private repos (no-op on public)
id-token: write
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
with:
enable-cache: false
version: "0.11.25"
- run: |
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 uv build --wheel
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ONYX_CLI_REUSE_BINARY=1 \
ONYX_CLI_WHEEL_PLATFORM_TAG=musllinux_1_2_x86_64 \
uv build --wheel
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 uv build --wheel
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 ONYX_CLI_REUSE_BINARY=1 \
ONYX_CLI_WHEEL_PLATFORM_TAG=musllinux_1_2_aarch64 \
uv build --wheel
for goos in windows darwin; do
for goarch in amd64 arm64; do
GOOS="$goos" GOARCH="$goarch" uv build --wheel
done
done
working-directory: cli
- name: Upload built wheels
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: onyx-cli-wheels
path: cli/dist/*.whl
if-no-files-found: error
retention-days: 7
- run: uv publish
working-directory: cli
docker-amd64:
runs-on:
- runs-on
- runner=2cpu-linux-x64
- run-id=${{ github.run_id }}-cli-amd64
environment: deploy
permissions:
contents: read # needed to checkout the repo on private repos (no-op on public)
id-token: write
timeout-minutes: 30
outputs:
digest: ${{ steps.build.outputs.digest }}
env:
REGISTRY_IMAGE: onyxdotapp/onyx-cli
steps:
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
with:
persist-credentials: false
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # ratchet:aws-actions/configure-aws-credentials@v6.2.0
with:
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
aws-region: us-east-2
- name: Get AWS Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53 # ratchet:aws-actions/aws-secretsmanager-get-secrets@v3.0.1
with:
secret-ids: |
DOCKER_USERNAME, deploy/docker-username
DOCKER_TOKEN, deploy/docker-token
parse-json-secrets: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_TOKEN }}
- name: Build and push AMD64
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: ./cli
file: ./cli/Dockerfile
platforms: linux/amd64
cache-from: type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
cache-to: type=inline
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
docker-arm64:
runs-on:
- runs-on
- runner=2cpu-linux-arm64
- run-id=${{ github.run_id }}-cli-arm64
environment: deploy
permissions:
contents: read # needed to checkout the repo on private repos (no-op on public)
id-token: write
timeout-minutes: 30
outputs:
digest: ${{ steps.build.outputs.digest }}
env:
REGISTRY_IMAGE: onyxdotapp/onyx-cli
steps:
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
with:
persist-credentials: false
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # ratchet:aws-actions/configure-aws-credentials@v6.2.0
with:
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
aws-region: us-east-2
- name: Get AWS Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53 # ratchet:aws-actions/aws-secretsmanager-get-secrets@v3.0.1
with:
secret-ids: |
DOCKER_USERNAME, deploy/docker-username
DOCKER_TOKEN, deploy/docker-token
parse-json-secrets: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_TOKEN }}
- name: Build and push ARM64
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: ./cli
file: ./cli/Dockerfile
platforms: linux/arm64
cache-from: type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
cache-to: type=inline
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
merge-docker:
needs:
- docker-amd64
- docker-arm64
runs-on:
- runs-on
- runner=2cpu-linux-x64
- run-id=${{ github.run_id }}-cli-merge
environment: deploy
permissions:
id-token: write
timeout-minutes: 10
env:
REGISTRY_IMAGE: onyxdotapp/onyx-cli
steps:
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # ratchet:aws-actions/configure-aws-credentials@v6.2.0
with:
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
aws-region: us-east-2
- name: Get AWS Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53 # ratchet:aws-actions/aws-secretsmanager-get-secrets@v3.0.1
with:
secret-ids: |
DOCKER_USERNAME, deploy/docker-username
DOCKER_TOKEN, deploy/docker-token
parse-json-secrets: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_TOKEN }}
- name: Create and push manifest
env:
AMD64_DIGEST: ${{ needs.docker-amd64.outputs.digest }}
ARM64_DIGEST: ${{ needs.docker-arm64.outputs.digest }}
TAG: ${{ github.ref_name }}
run: |
SANITIZED_TAG="${TAG#cli/}"
IMAGES=(
"${REGISTRY_IMAGE}@${AMD64_DIGEST}"
"${REGISTRY_IMAGE}@${ARM64_DIGEST}"
)
if [[ "$TAG" =~ ^cli/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
docker buildx imagetools create \
-t "${REGISTRY_IMAGE}:${SANITIZED_TAG}" \
-t "${REGISTRY_IMAGE}:latest" \
"${IMAGES[@]}"
else
docker buildx imagetools create \
-t "${REGISTRY_IMAGE}:${SANITIZED_TAG}" \
"${IMAGES[@]}"
fi
govulncheck:
needs:
- pypi
runs-on: ubuntu-latest
permissions:
contents: read # needed to checkout the repo for SARIF source locations
actions: read # needed to download the wheel artifact from the release job
security-events: write # needed for SARIF uploads
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # ratchet:actions/download-artifact@v4
with:
name: onyx-cli-wheels
path: cli/dist
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # zizmor: ignore[cache-poisoning]
with:
go-version: "1.26.4"
cache: false
- name: Install govulncheck
run: |
GOBIN="${RUNNER_TEMP}/bin" go install golang.org/x/vuln/cmd/govulncheck@v1.3.0
echo "${RUNNER_TEMP}/bin" >> "$GITHUB_PATH"
- name: Run govulncheck on released wheel binaries
run: |
set -euo pipefail
scan_exit=0
mkdir -p wheel-binaries govulncheck-results/raw
for wheel in cli/dist/*.whl; do
wheel_name="$(basename "$wheel" .whl)"
if [[ "$wheel_name" == *-musllinux_* ]]; then
echo "Skipping duplicate static Linux binary scan for $wheel_name"
continue
fi
extract_dir="wheel-binaries/${wheel_name}"
sarif_file="govulncheck-results/raw/${wheel_name}.sarif"
unzip -q "$wheel" -d "$extract_dir"
binary="$(
find "$extract_dir" \
\( -path '*.data/scripts/onyx-cli' -o -path '*.data/scripts/onyx-cli.exe' \) \
-type f \
-print -quit
)"
if [ -z "$binary" ]; then
echo "No onyx-cli binary found in $wheel" >&2
exit 1
fi
if ! govulncheck -mode=binary "$binary"; then
scan_exit=1
fi
govulncheck -mode=binary -format=sarif "$binary" > "$sarif_file"
done
python3 <<'PY'
import json
from pathlib import Path
raw_results_dir = Path("govulncheck-results/raw")
merged = {
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [],
}
sarif_paths = sorted(raw_results_dir.glob("*.sarif"))
if not sarif_paths:
raise SystemExit("No govulncheck SARIF files were generated")
for sarif_path in sarif_paths:
data = json.loads(sarif_path.read_text())
for run in data.get("runs", []):
run["automationDetails"] = {
"id": f"onyx-cli-govulncheck/{sarif_path.stem}",
}
results = []
upload_levels = {"error", "warning"}
for result in run.get("results", []):
if result.get("level") not in upload_levels:
continue
if not result.get("locations"):
result["locations"] = [
{
"physicalLocation": {
"artifactLocation": {"uri": "cli/go.mod"},
"region": {"startLine": 1},
}
}
]
results.append(result)
run["results"] = results
merged["runs"].append(run)
if not merged["runs"]:
raise SystemExit("No govulncheck SARIF runs were generated")
Path("govulncheck-results.sarif").write_text(json.dumps(merged))
PY
exit "$scan_exit"
- name: Upload govulncheck scan results to GitHub Security tab
if: always()
uses: github/codeql-action/upload-sarif@ba454b8ab46733eb6145342877cd148270bb77ab
with:
sarif_file: govulncheck-results.sarif