Skip to content

feat: add Azure Responses API and observable streaming #21

feat: add Azure Responses API and observable streaming

feat: add Azure Responses API and observable streaming #21

Workflow file for this run

name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
packages: write
env:
GO_VERSION: "1.25.12"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# ────────────────────────────────────────────────────────────
# Test gate
# ────────────────────────────────────────────────────────────
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v7
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Vet
run: go vet ./...
- name: Test
# -short runs the fast variants of the engine/queue load/soak tests
# (the only tests gated on testing.Short()); the full 2000-run soak is a
# timing-sensitive load test, not a gate — run it manually/nightly.
run: go test -race -count=1 -timeout 120s -short ./...
# ────────────────────────────────────────────────────────────
# Publish Go module
# ────────────────────────────────────────────────────────────
publish-module:
name: Publish Go Module
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v7
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Request proxy to fetch new version
run: |
VERSION=${GITHUB_REF#refs/tags/}
echo "Publishing module version: $VERSION"
GOPROXY=https://proxy.golang.org GO111MODULE=on \
go list -m github.com/spawn08/chronos@${VERSION} || true
# ────────────────────────────────────────────────────────────
# Build cross-platform binaries
# Targets: Linux (amd64/arm64), macOS Intel (amd64),
# macOS Apple Silicon (arm64), Windows (amd64/arm64)
# ────────────────────────────────────────────────────────────
build-binaries:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
needs: test
strategy:
fail-fast: false
matrix:
include:
# Linux amd64 (Ubuntu, Debian, RHEL, CentOS, Fedora, Alpine)
- target: linux-amd64
runner: ubuntu-latest
goos: linux
goarch: amd64
# Linux arm64 (Ubuntu arm64, AWS Graviton, Raspberry Pi 64-bit)
- target: linux-arm64
runner: ubuntu-latest
goos: linux
goarch: arm64
# macOS Intel (x86_64)
- target: darwin-amd64
runner: macos-latest
goos: darwin
goarch: amd64
# macOS Apple Silicon (M1/M2/M3/M4)
- target: darwin-arm64
runner: macos-latest
goos: darwin
goarch: arm64
# Windows amd64
- target: windows-amd64
runner: windows-latest
goos: windows
goarch: amd64
# Windows arm64
- target: windows-arm64
runner: windows-latest
goos: windows
goarch: arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v7
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Determine version metadata
id: meta
shell: bash
run: |
VERSION=${GITHUB_REF#refs/tags/}
COMMIT=$(git rev-parse --short HEAD)
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "commit=$COMMIT" >> "$GITHUB_OUTPUT"
echo "build_date=$BUILD_DATE" >> "$GITHUB_OUTPUT"
- name: Build binary
shell: bash
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: |
BINARY_NAME="chronos-${{ matrix.goos }}-${{ matrix.goarch }}"
if [ "${{ matrix.goos }}" = "windows" ]; then
BINARY_NAME="${BINARY_NAME}.exe"
fi
go build -trimpath -ldflags "-s -w \
-X github.com/spawn08/chronos/cli/cmd.Version=${{ steps.meta.outputs.version }} \
-X github.com/spawn08/chronos/cli/cmd.Commit=${{ steps.meta.outputs.commit }} \
-X github.com/spawn08/chronos/cli/cmd.BuildDate=${{ steps.meta.outputs.build_date }}" \
-o "${BINARY_NAME}" ./cli/main.go
echo "Built: ${BINARY_NAME}"
ls -lh "${BINARY_NAME}"
- name: Create tarball (Linux/macOS)
if: matrix.goos != 'windows'
shell: bash
run: |
BINARY_NAME="chronos-${{ matrix.goos }}-${{ matrix.goarch }}"
ARCHIVE_NAME="chronos-${{ steps.meta.outputs.version }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz"
FILES="${BINARY_NAME}"
[ -f LICENSE ] && FILES="${FILES} LICENSE"
[ -f README.md ] && FILES="${FILES} README.md"
tar czf "${ARCHIVE_NAME}" ${FILES}
echo "Archive: ${ARCHIVE_NAME}"
ls -lh "${ARCHIVE_NAME}"
- name: Create zip (Windows)
if: matrix.goos == 'windows'
shell: pwsh
run: |
$version = "${{ steps.meta.outputs.version }}"
$archiveName = "chronos-${version}-${{ matrix.goos }}-${{ matrix.goarch }}.zip"
$files = @("chronos-${{ matrix.goos }}-${{ matrix.goarch }}.exe")
if (Test-Path "LICENSE") { $files += "LICENSE" }
if (Test-Path "README.md") { $files += "README.md" }
Compress-Archive -Path $files -DestinationPath $archiveName
Write-Host "Archive: $archiveName"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: chronos-${{ matrix.target }}
path: |
chronos-*.tar.gz
chronos-*.zip
chronos-${{ matrix.goos }}-${{ matrix.goarch }}*
retention-days: 1
# ────────────────────────────────────────────────────────────
# GitHub Release with all artifacts
# ────────────────────────────────────────────────────────────
github-release:
name: GitHub Release
runs-on: ubuntu-latest
needs: build-binaries
if: always() && !contains(needs.build-binaries.result, 'failure')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: List artifacts
run: |
echo "=== Downloaded artifacts ==="
ls -lhR artifacts/ 2>/dev/null || echo "No artifacts directory"
- name: Generate source SBOM (SPDX)
uses: anchore/sbom-action@v0
with:
path: .
format: spdx-json
output-file: artifacts/chronos-${{ github.ref_name }}-sbom.spdx.json
- name: Generate checksums
run: |
cd artifacts
sha256sum chronos-*.tar.gz chronos-*.zip chronos-linux-* chronos-darwin-* chronos-windows-* chronos-*-sbom.spdx.json 2>/dev/null | sort > checksums-sha256.txt || true
if [ ! -s checksums-sha256.txt ]; then
echo "WARNING: No files matched for checksums"
exit 1
fi
echo "=== SHA-256 Checksums ==="
cat checksums-sha256.txt
- name: Determine version
id: version
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
name: Chronos ${{ steps.version.outputs.tag }}
generate_release_notes: true
body: |
## Installation
### Quick Install (Linux / macOS)
```bash
curl -fsSL https://raw.githubusercontent.com/${{ github.repository }}/main/install.sh | bash
```
Or install a specific version:
```bash
curl -fsSL https://raw.githubusercontent.com/${{ github.repository }}/main/install.sh | bash -s -- ${{ steps.version.outputs.tag }}
```
### Manual Download
| Platform | Architecture | Download |
|----------|-------------|----------|
| **Linux** | x86_64 (amd64) | [chronos-${{ steps.version.outputs.tag }}-linux-amd64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-linux-amd64.tar.gz) |
| **Linux** | ARM64 | [chronos-${{ steps.version.outputs.tag }}-linux-arm64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-linux-arm64.tar.gz) |
| **macOS** | Intel (x86_64) | [chronos-${{ steps.version.outputs.tag }}-darwin-amd64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-darwin-amd64.tar.gz) |
| **macOS** | Apple Silicon (M1+) | [chronos-${{ steps.version.outputs.tag }}-darwin-arm64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-darwin-arm64.tar.gz) |
| **Windows** | x86_64 (amd64) | [chronos-${{ steps.version.outputs.tag }}-windows-amd64.zip](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-windows-amd64.zip) |
| **Windows** | ARM64 | [chronos-${{ steps.version.outputs.tag }}-windows-arm64.zip](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/chronos-${{ steps.version.outputs.tag }}-windows-arm64.zip) |
### Verify Checksum
```bash
sha256sum -c checksums-sha256.txt
```
files: |
artifacts/chronos-*.tar.gz
artifacts/chronos-*.zip
artifacts/chronos-linux-*
artifacts/chronos-darwin-*
artifacts/chronos-windows-*
artifacts/chronos-*-sbom.spdx.json
artifacts/checksums-sha256.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ────────────────────────────────────────────────────────────
# Docker image → GitHub Container Registry
# ────────────────────────────────────────────────────────────
docker:
name: Docker Image
runs-on: ubuntu-latest
needs: test
permissions:
contents: read
packages: write
# id-token for keyless (OIDC) cosign signing; security-events for
# uploading the Trivy image-scan SARIF to the Security tab.
id-token: write
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v7
with:
context: .
file: deploy/docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
# ── Supply-chain hardening for the published image ─────────
- name: Scan image with Trivy
# Pinned release tags for this action have been unreliable to resolve;
# track master (maintained by aquasecurity).
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: sarif
output: trivy-image.sarif
severity: CRITICAL,HIGH
ignore-unfixed: true
- name: Upload Trivy image SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-image.sarif
category: trivy-image
- name: Generate image SBOM (SPDX)
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: spdx-json
output-file: image-sbom.spdx.json
# The image SBOM is attested to the image via cosign below; don't also
# upload it as a release asset (this job is least-privilege
# contents: read, and the source SBOM is already on the release).
upload-release-assets: false
- name: Sign the published image (keyless OIDC)
env:
IMAGE_REF: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
run: cosign sign --yes "${IMAGE_REF}"
- name: Attest image SBOM (keyless OIDC)
env:
IMAGE_REF: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
run: |
cosign attest --yes \
--predicate image-sbom.spdx.json \
--type spdxjson \
"${IMAGE_REF}"