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
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[alias]
xtask = "run --package xtask --"
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.git
.agentctl
.runtime
archive
artifacts
dist
docs
examples
fixture
fixtures
fuzz
node_modules
schemas
target
*.db
*.log
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/schemas/workflow.schema.json text eol=lf
/docs/generated/CLI.md text eol=lf
*.pack.yaml text eol=lf
145 changes: 145 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: credential-free-ci

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: credential-free-ci-${{ github.ref }}
cancel-in-progress: true

env:
RUST_TOOLCHAIN: "1.88.0"
CARGO_DENY_VERSION: "0.20.2"
CARGO_CYCLONEDX_VERSION: "0.5.9"
CARGO_CYCLONEDX_LINUX_X64_SHA256: "fb8dbee9f182173e062a64a387b21a0badc6fab8b2abf9294973f012972bf6d8"

jobs:
gates:
name: gates (${{ matrix.target }})
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
target: x86_64-unknown-linux-gnu
- runner: macos-14
target: aarch64-apple-darwin
- runner: windows-2022
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.runner }}
defaults:
run:
shell: bash
steps:
- name: Checkout exact revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install pinned Rust toolchain
run: |
set -euo pipefail
rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal --component clippy,rustfmt
rustup default "$RUST_TOOLCHAIN"
host="$(rustc -vV | sed -n 's/^host: //p' | tr -d '\r')"
test "$host" = "${{ matrix.target }}"

- name: Install pinned cargo-deny
run: cargo install cargo-deny --version "$CARGO_DENY_VERSION" --locked

- name: Run deterministic verification gate
run: cargo xtask verify

- name: Run credential-free acceptance gate
run: cargo xtask acceptance

- name: Build production package
run: cargo xtask package

- name: Upload production package
id: package
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: agentctl-${{ matrix.target }}
path: dist/
if-no-files-found: error
retention-days: 14

- name: Record package artifact digest
run: echo "agentctl-${{ matrix.target }} artifact digest ${{ steps.package.outputs.artifact-digest }}" >> "$GITHUB_STEP_SUMMARY"

production-sbom:
name: production SBOM
needs: gates
runs-on: ubuntu-24.04
defaults:
run:
shell: bash
steps:
- name: Checkout exact revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install pinned Rust toolchain
run: |
set -euo pipefail
rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal
rustup default "$RUST_TOOLCHAIN"

- name: Install pinned cargo-cyclonedx
run: |
set -euo pipefail
archive="$RUNNER_TEMP/cargo-cyclonedx.tar.xz"
tool_dir="$RUNNER_TEMP/cargo-cyclonedx"
curl --proto '=https' --tlsv1.2 --retry 3 --fail --location \
"https://github.com/CycloneDX/cyclonedx-rust-cargo/releases/download/cargo-cyclonedx-${CARGO_CYCLONEDX_VERSION}/cargo-cyclonedx-x86_64-unknown-linux-gnu.tar.xz" \
--output "$archive"
echo "$CARGO_CYCLONEDX_LINUX_X64_SHA256 $archive" | sha256sum --check -
mkdir -p "$tool_dir"
tar -xJf "$archive" -C "$tool_dir" --strip-components=1
"$tool_dir/cargo-cyclonedx" cyclonedx --version
echo "$tool_dir" >> "$GITHUB_PATH"

- name: Generate CycloneDX production SBOM
run: |
set -euo pipefail
cargo cyclonedx \
--manifest-path crates/agentctl-cli/Cargo.toml \
--format json \
--describe binaries \
--target x86_64-unknown-linux-gnu \
--spec-version 1.5 \
--no-build-deps
mv crates/agentctl-cli/agentctl_bin.cdx.json agentctl-production.cdx.json

- name: Validate and digest production SBOM
id: sbom_file
run: |
set -euo pipefail
jq -e '
.bomFormat == "CycloneDX"
and .specVersion == "1.5"
and .metadata.component.name == "agentctl"
and ((.components | type) == "array")
and ((.components | length) > 0)
and any(.components[]; ((.purl // "") | startswith("pkg:cargo/")))
' agentctl-production.cdx.json >/dev/null
digest="$(sha256sum agentctl-production.cdx.json | cut -d ' ' -f 1)"
echo "sha256=$digest" >> "$GITHUB_OUTPUT"
echo "agentctl-production.cdx.json SHA-256 $digest" >> "$GITHUB_STEP_SUMMARY"

- name: Upload production SBOM
id: sbom
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: agentctl-production-sbom-cyclonedx
path: agentctl-production.cdx.json
if-no-files-found: error
retention-days: 14

- name: Record SBOM artifact digest
run: echo "agentctl-production-sbom-cyclonedx artifact digest ${{ steps.sbom.outputs.artifact-digest }}" >> "$GITHUB_STEP_SUMMARY"
94 changes: 94 additions & 0 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: container-security

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: container-security-${{ github.ref }}
cancel-in-progress: true

env:
RUST_TOOLCHAIN: "1.88.0"

jobs:
container:
runs-on: ubuntu-24.04
defaults:
run:
shell: bash
steps:
- name: Checkout exact revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install pinned Rust toolchain
run: |
set -euo pipefail
rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal
rustup default "$RUST_TOOLCHAIN"

- name: Prepare optional build CA secret
env:
BUILD_CA_PEM: ${{ secrets.AGENTCTL_BUILD_CA_PEM }}
run: |
set -euo pipefail
if [[ -n "${BUILD_CA_PEM:-}" ]]; then
ca_file="$RUNNER_TEMP/agentctl-build-ca.pem"
umask 077
printf '%s' "$BUILD_CA_PEM" > "$ca_file"
echo "AGENTCTL_BUILD_CA_FILE=$ca_file" >> "$GITHUB_ENV"
fi

- name: Build and run hardened container acceptance
run: cargo xtask acceptance-container

- name: Remove optional build CA secret
if: always()
run: rm -f "${AGENTCTL_BUILD_CA_FILE:-$RUNNER_TEMP/agentctl-build-ca.pem}"

- name: Record local image digest
run: |
image_id="$(docker image inspect agentctl-acceptance:local --format '{{.Id}}')"
test -n "$image_id"
echo "agentctl-acceptance:local image digest $image_id" >> "$GITHUB_STEP_SUMMARY"

- name: Reject fixed critical or high image vulnerabilities
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: agentctl-acceptance:local
version: v0.72.0
scanners: vuln
format: table
severity: CRITICAL,HIGH
ignore-unfixed: true
exit-code: "1"

- name: Generate CycloneDX image SBOM
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: agentctl-acceptance:local
version: v0.72.0
format: cyclonedx
output: agentctl-image.cdx.json
exit-code: "1"

- name: Validate image SBOM
run: jq -e '.bomFormat == "CycloneDX" and (.components | type == "array")' agentctl-image.cdx.json >/dev/null

- name: Upload image SBOM
id: image_sbom
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: agentctl-image-sbom-cyclonedx
path: agentctl-image.cdx.json
if-no-files-found: error
retention-days: 14

- name: Record image SBOM artifact digest
run: echo "agentctl-image-sbom-cyclonedx artifact digest ${{ steps.image_sbom.outputs.artifact-digest }}" >> "$GITHUB_STEP_SUMMARY"
57 changes: 57 additions & 0 deletions .github/workflows/release-prep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: rc-release-preparation

on:
workflow_dispatch:

permissions:
contents: read

env:
RUST_TOOLCHAIN: "1.88.0"
CARGO_DENY_VERSION: "0.20.2"

jobs:
release-candidate:
name: RC (${{ matrix.target }})
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
target: x86_64-unknown-linux-gnu
- runner: macos-14
target: aarch64-apple-darwin
- runner: windows-2022
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.runner }}
defaults:
run:
shell: bash
steps:
- name: Checkout exact revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install pinned release toolchain
run: |
set -euo pipefail
rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal --component clippy,rustfmt
rustup default "$RUST_TOOLCHAIN"
cargo install cargo-deny --version "$CARGO_DENY_VERSION" --locked

- name: Run full credential-free RC gate
run: |
cargo xtask verify
cargo xtask acceptance
cargo xtask package

- name: Upload RC package
id: package
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: agentctl-rc-${{ matrix.target }}
path: dist/
if-no-files-found: error
retention-days: 14

- name: Record RC artifact digest
run: echo "agentctl-rc-${{ matrix.target }} artifact digest ${{ steps.package.outputs.artifact-digest }}" >> "$GITHUB_STEP_SUMMARY"
Loading
Loading