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

# No push trigger for `dev`: everything on dev travels through a pull
# request anyway, and a push run would twin the PR run on the same commit —
# under *required* checks, a deduplicating cancellation poisons the gate
# (a cancelled twin's "CI is green" reads as failure and blocks the merge).
# `main` keeps its push trigger because a rebase-merge mints a new SHA that
# no PR run ever checked.
# No push trigger at all: everything travels through a pull request, and
# main only ever receives a SQUASH of a green PR — the squashed tree is
# byte-identical to the PR head the checks already ran on, so a main
# re-run would test the same content twice. Merging runs release.yml
# alone; workflow_dispatch stays as the manual escape hatch.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:

Expand All @@ -29,6 +26,50 @@ env:
RUST_BACKTRACE: 1

jobs:
conformance:
name: the three languages agree
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
# The engine's conformance cases, at a PINNED ref: bumping the pin is
# a visible PR diff, which is the point — semantics move only when
# somebody says so.
- run: |
ref="v0.8.0" # the engine release these wheels build against
curl -sSL "https://github.com/dynamic-config-rs/dynamic-config/archive/refs/tags/${ref}.tar.gz" \
| tar -xz --strip-components=1 --wildcards '*/conformance/'
- uses: actions/setup-python@2e3e4b15a884dc73a63f962bff250a855150a234 # v6
with:
python-version: "3.12"
- run: pip install dynamic-config-py
- run: CONFORMANCE_DIR=conformance/cases python scripts/conformance.py

msrv:
name: the declared floor compiles
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
toolchain: stable
# The stores reach `etcd-client`, whose build script compiles protos.
- run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
# A lockfile resolved by stable, then checked by the floor — the
# combination `pip install` + our build actually produces. This job
# did not exist before the 1.88 raise; a floor nobody compiles
# against is a number in a manifest.
- run: cargo generate-lockfile
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
toolchain: "1.88"
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
with:
shared-key: msrv
- run: cargo +1.88 check -p dynamic-config-python --locked --lib
- run: cargo +1.88 check -p dynamic-config-python-remote --locked --lib

# What changed, so the expensive jobs below can sit out a run that cannot
# affect them. Deliberately a *job* rather than `on.pull_request.paths`:
# a workflow filtered out at the trigger never reports at all, and a
Expand Down Expand Up @@ -419,6 +460,8 @@ jobs:
- python-free-threaded
- docs-links
- actionlint
- msrv
- conformance
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Nightly

# The binding-side leak budget: callback and notifier lifecycles are
# where leaks hide even when the Rust core is clean. The engine's
# nightly carries the 5-hour soak; these legs churn the binding's own
# machinery a million times and hold the deltas to a budget.
on:
schedule:
- cron: "23 1 * * *"
workflow_dispatch:

permissions:
contents: read

jobs:
leak:
name: a million reloads leak nothing
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-python@2e3e4b15a884dc73a63f962bff250a855150a234 # v6
with:
python-version: "3.12"
- run: pip install dynamic-config-py
- run: LEAK_RELOADS=1000000 python scripts/leak.py
2 changes: 1 addition & 1 deletion .github/workflows/publish-dry-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: Publish dry run
# manifests change, not when the code does.
on:
push:
branches: [main, dev]
branches: [dev]
paths:
- "**/Cargo.toml"
- "**/README.md"
Expand Down
23 changes: 14 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -293,22 +293,27 @@ jobs:
&& (needs.decide.outputs.release == 'true' || github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
# Trusted publishing: PyPI verifies THIS workflow's OIDC identity
# and mints a short-lived token — no PYPI_TOKEN to store, leak or
# rotate. Both projects (`dynamic-config-py`,
# `dynamic-config-py-remote`) carry a Trusted Publisher entry on
# PyPI naming this repository and this file; that console entry is
# a release-train prerequisite and OUTSTANDING.md spells it out.
id-token: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: wheels-*
merge-multiple: true
path: dist
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
# `skip-existing`: a version on PyPI is permanent, so the only way
# forward after a partial failure is a rerun that publishes the
# remainder.
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
python-version: "3.13"
# what is already uploaded: a version on PyPI is permanent, so the
# only way forward after a partial failure is a rerun that publishes
# the remainder.
- run: pip install maturin
- run: maturin upload --skip-existing dist/*
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
packages-dir: dist
skip-existing: true

tag-and-release:
name: tag and GitHub release
Expand Down
22 changes: 19 additions & 3 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ name: Security
# No push trigger for `dev` — same reasoning as ci.yml: dev travels through
# pull requests, and a push twin under required checks poisons the gate.
on:
push:
branches: [main]
pull_request:
schedule:
- cron: "17 6 * * 1"
Expand All @@ -23,6 +21,24 @@ permissions:
contents: read

jobs:
policy:
name: the security policy names the current line
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
# The stale-table drift this org has already lived through once:
# SECURITY.md said 0.0.x while the workspace shipped 0.7. The table's
# top row must name the line that is actually published.
- run: |
version=$(grep -m1 '^version = ' dynamic-config-python/Cargo.toml | cut -d'"' -f2)
line="${version%.*}.x"
if ! grep -qF "| ${line}" SECURITY.md; then
echo "::error file=SECURITY.md::the supported-versions table does not name ${line} (workspace is ${version})"
exit 1
fi
echo "SECURITY.md names ${line} — current"

deny:
name: advisories, licences, sources
runs-on: ubuntu-latest
Expand Down Expand Up @@ -149,7 +165,7 @@ jobs:
# — which is the whole point of running it.
security-ok:
name: Security is green
needs: [deny, unsafe, osv, supply-chain]
needs: [policy, deny, unsafe, osv, supply-chain]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
Expand Down
Loading
Loading