name: publish
# A tag publishes; master only checks that a publish *would* work.
#
# Cargo refuses to overwrite a published version, and rightly — so a workflow
# that published on every push would fail on its second run and stay failed
# until someone bumped the version. The dry run on master is the useful half of
# that anyway: it catches a manifest that cannot be packaged at the commit that
# broke it, rather than at the tag three weeks later.
on:
push:
branches: [master]
tags: ['v*']
jobs:
publish:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
# Through $GITHUB_ENV rather than a job-level `env:` block: every value
# in this file travels that way, so there is one mechanism to trust
# instead of two.
#
# `cargo publish` needs a host toolchain and nothing else — no ESP
# anything, since esp-idf-svc is target-scoped in Cargo.toml and a host
# build compiles only the pure modules. It is installed with rustup
# rather than taken from a `container:` image, because the runner
# executes JavaScript actions with node inside the job container and
# `rust:1.90-bookworm` has no node: `actions/checkout@v4` would die
# before this workflow started. (lambent-flex-c6 hits the same wall from
# the other side; see its firmware.yml.)
- name: Settings
run: |
set -euo pipefail
echo "RUST_VERSION=1.90.0" >> "$GITHUB_ENV"
echo "REGISTRY_NAME=neiam-portal" >> "$GITHUB_ENV"
- name: Resolve the forge URL
env:
CI_FORGE_URL: ${{ vars.CI_FORGE_URL }}
run: |
set -euo pipefail
forge_url=${CI_FORGE_URL:-${GITHUB_SERVER_URL:-}}
if [ -z "$forge_url" ]; then
echo "No forge URL available." >&2
echo "Set a CI_FORGE_URL variable on this repository or its org." >&2
exit 1
fi
echo "FORGE_URL=$forge_url" >> "$GITHUB_ENV"
- name: Cache the toolchain and the registry
uses: actions/cache@v4
with:
path: |
.home
target
key: rust-${{ env.RUST_VERSION }}-${{ hashFiles('Cargo.toml') }}
restore-keys: rust-${{ env.RUST_VERSION }}-
- name: Rust
run: |
set -euo pipefail
export RUSTUP_HOME="$PWD/.home/.rustup" CARGO_HOME="$PWD/.home/.cargo"
echo "RUSTUP_HOME=$RUSTUP_HOME" >> "$GITHUB_ENV"
echo "CARGO_HOME=$CARGO_HOME" >> "$GITHUB_ENV"
echo "$CARGO_HOME/bin" >> "$GITHUB_PATH"
if [ ! -x "$CARGO_HOME/bin/cargo" ]; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --profile minimal --default-toolchain "$RUST_VERSION"
fi
"$CARGO_HOME/bin/cargo" --version
# The registry is per repository: its index lives under this repository's
# own path, and the name a consumer registers it under is the repository
# name. Cargo takes an index from configuration only, never a flag — and
# this goes in CARGO_HOME rather than ./.cargo/config.toml on purpose,
# because `cargo publish` refuses a dirty working tree and writing into
# the checkout would make it one.
#
# Written whole (`>`), not appended (`>>`). CARGO_HOME is restored from
# the cache, so appending accumulated a second copy of the stanza on
# every run after the first, and cargo rejects a duplicate key outright:
#
# could not parse TOML configuration in …/.home/.cargo/config.toml
# TOML parse error at line 5, column 13: duplicate key
#
# That failed in one second, before the registry was ever contacted,
# which is why it looked like an auth problem. The file is entirely
# ours — rustup writes `env` and `bin/`, never this — so owning it
# outright is both safe and idempotent.
- name: Point cargo at the forge
run: |
set -euo pipefail
mkdir -p "$CARGO_HOME"
cat > "$CARGO_HOME/config.toml" <<TOML
[registries.$REGISTRY_NAME]
index = "sparse+$FORGE_URL/pkg/cargo/${{ github.repository }}/"
TOML
cat "$CARGO_HOME/config.toml"
# `${{ github.token }}` is minted for this job and may write this
# repository's packages and nothing else, so there is no secret to create
# first. Cargo reads it from CARGO_REGISTRIES_<NAME>_TOKEN, uppercased
# with every non-alphanumeric run folded to `_`.
- name: Publish
env:
CARGO_REGISTRIES_NEIAM_PORTAL_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
# Run #2 failed here in one second and said nothing about why. The
# two candidates — an empty registry name and a missing token —
# both fail that fast, so name them rather than guess again. The
# token is reported by length, never by value.
: "${REGISTRY_NAME:?registry name is empty}"
: "${CARGO_HOME:?cargo home is unset}"
echo "registry=$REGISTRY_NAME ref_type=${GITHUB_REF_TYPE:-<unset>} ref=${GITHUB_REF_NAME:-<unset>}"
token=${CARGO_REGISTRIES_NEIAM_PORTAL_TOKEN:-}
echo "token: ${#token} chars"
echo "config: $CARGO_HOME/config.toml"
grep -A 1 "registries" "$CARGO_HOME/config.toml" || echo " (no registry stanza!)"
if [ "${GITHUB_REF_TYPE:-branch}" = "tag" ]; then
cargo publish --registry "$REGISTRY_NAME"
echo
echo "Published. Consumers add:"
echo " [registries.$REGISTRY_NAME]"
echo " index = \"sparse+$FORGE_URL/pkg/cargo/${{ github.repository }}/\""
else
# --dry-run still packages and verify-builds; it just does not
# upload. That is the whole value of running this on master.
cargo publish --registry "$REGISTRY_NAME" --dry-run
fi
neiam
/neiam-portal
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
5.9 KiB · text
History
b46a4bd