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
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
push:
branches: [master]
pull_request:

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

env:
CARGO_TERM_COLOR: always

jobs:
test:
name: Build and test
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- uses: Swatinem/rust-cache@v2

- name: Format
run: cargo fmt --check

- name: Clippy
run: |
rustc --version
cargo clippy --version
cargo clippy --all-targets -- -D warnings

- name: Test
run: cargo test --locked
120 changes: 120 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: Publish

# Publish on a version bump, not on every push to master. Source paths are
# included so a re-run after a transient registry failure does not need a
# dummy version change. Existing versions exit cleanly.
on:
push:
branches: [master]
paths:
- Cargo.toml
- Cargo.lock
- crates/**
workflow_dispatch:
inputs:
dry_run:
description: 'Package and verify, but do not upload'
required: false
type: boolean
default: false

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

jobs:
publish:
name: crates.io
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Are these versions already on crates.io?
id: check
shell: bash
run: |
set -euo pipefail
version=""
missing=""
for crate_name in agency-proxy-protocol agency-proxy-client agency-proxy; do
package_version=$(cargo metadata --no-deps --format-version 1 \
| jq -r --arg name "$crate_name" '.packages[] | select(.name == $name) | .version')
if [ -n "$version" ] && [ "$package_version" != "$version" ]; then
echo "workspace package versions disagree: $version and $package_version" >&2
exit 1
fi
version=$package_version
published=$(curl -sS -H 'User-Agent: pathscale-ci' \
"https://crates.io/api/v1/crates/$crate_name/versions" \
| jq -r --arg v "$version" '.versions[]? | select(.num == $v) | .num' || true)
if [ -n "$published" ]; then
echo "$crate_name $version is already published"
else
missing="$missing $crate_name"
echo "$crate_name $version is new"
fi
done
echo "version=$version" >> "$GITHUB_OUTPUT"
if [ -n "$missing" ]; then
echo "already=false" >> "$GITHUB_OUTPUT"
else
echo "already=true" >> "$GITHUB_OUTPUT"
fi

- name: Build
if: steps.check.outputs.already == 'false'
run: cargo build --release

- name: Test
if: steps.check.outputs.already == 'false'
run: cargo test --release

- name: Package dry run
if: steps.check.outputs.already == 'false' && inputs.dry_run
run: |
cargo package -p agency-proxy-protocol --locked
cargo package -p agency-proxy-client --locked --no-verify
cargo package -p agency-proxy --locked --no-verify

- name: Publish
if: steps.check.outputs.already == 'false' && !inputs.dry_run
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
VERSION: ${{ steps.check.outputs.version }}
run: |
set -euo pipefail
if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
echo "CARGO_REGISTRY_TOKEN is not set on this repository" >&2
echo "Add it under Settings -> Secrets -> Actions." >&2
exit 1
fi
for crate_name in agency-proxy-protocol agency-proxy-client agency-proxy; do
published=$(curl -sS -H 'User-Agent: pathscale-ci' \
"https://crates.io/api/v1/crates/$crate_name/versions" \
| jq -r --arg v "$VERSION" '.versions[]? | select(.num == $v) | .num' || true)
if [ -n "$published" ]; then
echo "$crate_name $VERSION is already published; skipping"
else
cargo publish -p "$crate_name" --locked --registry crates-io
fi
done

- name: Summary
if: always()
run: |
{
if [ '${{ steps.check.outputs.already }}' = 'true' ]; then
echo "Nothing to publish: all AgencyProxy crates at \`${{ steps.check.outputs.version }}\` are already on crates.io."
echo
echo 'Bump `version` in Cargo.toml to cut a new release.'
elif [ '${{ inputs.dry_run }}' = 'true' ]; then
echo "Dry run: packaged AgencyProxy \`${{ steps.check.outputs.version }}\` without uploading."
else
echo "Published AgencyProxy \`${{ steps.check.outputs.version }}\`."
fi
} >> "$GITHUB_STEP_SUMMARY"
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ Run it with `agency-proxy --config /path/to/agency-proxy.json`. TLS is optional
for local development, but an HTTPS-hosted frontend should use the configured
certificate and connect with `wss://`. Browser clients authenticate with the
WebSocket subprotocol `agency-proxy.<authenticationKey>`.

## Publishing

The three crates share the workspace version. A merge to `master` that changes
the root `Cargo.toml` runs the full CI checks, then publishes any missing crates
in dependency order: protocol, client, and daemon. The repository must provide
an Actions secret named `CARGO_REGISTRY_TOKEN` with permission to publish all
three crates.
Loading