feat(daycount): add ACT and 30/360 day-count conventions (Phase 0) (#2) #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release to crates.io + SLSA | |
| # Auto-publish flow: | |
| # 1. Push to main → detect job compares Cargo.toml `version` between HEAD and HEAD~1. | |
| # 2. If version bumped → build+package job runs full tests, packages the .crate, hashes it. | |
| # 3. SLSA generic generator (Level 3) creates an in-toto attestation from the hash. | |
| # 4. Publish job uploads to crates.io, tags v<version>, and attaches the .crate | |
| # file plus the SLSA provenance to a GitHub Release. | |
| # | |
| # Required repo secret: CARGO_REGISTRY_TOKEN (scope: publish-update on crate `yield-curves`). | |
| on: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| detect: | |
| name: detect version bump | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_release: ${{ steps.diff.outputs.should_release }} | |
| version: ${{ steps.diff.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Compare Cargo.toml version vs latest on crates.io | |
| id: diff | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| NEW=$(grep -m1 '^version =' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/') | |
| if [ -z "$NEW" ]; then | |
| echo "::error::cannot read version from Cargo.toml" | |
| exit 1 | |
| fi | |
| # Query crates.io for the latest published version. Fallback to "" | |
| # if crate is brand new (404) or if jq misses the field. | |
| PUBLISHED=$(curl -fsSL "https://crates.io/api/v1/crates/yield-curves" \ | |
| -H "User-Agent: yield-curves-release-workflow" \ | |
| | jq -r '.crate.max_stable_version // ""' || echo "") | |
| echo "cargo_toml=$NEW" | |
| echo "crates_io=$PUBLISHED" | |
| # Publish whenever Cargo.toml differs from what's on crates.io. | |
| # cargo publish enforces monotonic version on the registry side, so | |
| # downgrades fail loudly if a non-bump slips through. | |
| if [ "$PUBLISHED" != "$NEW" ]; then | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| echo "version=$NEW" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| build: | |
| name: build + package | |
| needs: detect | |
| if: needs.detect.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| hashes: ${{ steps.hash.outputs.hashes }} | |
| filename: ${{ steps.hash.outputs.filename }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Verify tests pass before publishing | |
| run: cargo test --all | |
| - name: Dry-run publish | |
| run: cargo publish --dry-run | |
| - name: Package | |
| run: cargo package --no-verify | |
| - name: Hash artifact for SLSA | |
| id: hash | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd target/package | |
| FILE=$(ls *.crate) | |
| HASH_LINE=$(sha256sum "$FILE") | |
| echo "filename=$FILE" >> "$GITHUB_OUTPUT" | |
| echo "hashes=$(echo -n "$HASH_LINE" | base64 -w0)" >> "$GITHUB_OUTPUT" | |
| - name: Upload package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: crate-package | |
| path: target/package/*.crate | |
| retention-days: 7 | |
| if-no-files-found: error | |
| provenance: | |
| name: SLSA Level 3 provenance | |
| needs: [detect, build] | |
| if: needs.detect.outputs.should_release == 'true' | |
| permissions: | |
| actions: read | |
| id-token: write | |
| contents: write | |
| uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 | |
| with: | |
| base64-subjects: ${{ needs.build.outputs.hashes }} | |
| provenance-name: yield-curves-provenance.intoto.jsonl | |
| upload-assets: false | |
| publish: | |
| name: publish to crates.io + GitHub Release | |
| needs: [detect, build, provenance] | |
| if: needs.detect.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| fetch-depth: 0 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Publish to crates.io | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| run: cargo publish | |
| # Download artefatos depois do publish — cargo publish recusa se houver | |
| # arquivos não commitados na working tree, então só baixamos pra | |
| # anexar no GitHub Release. | |
| - name: Download package | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: crate-package | |
| path: target/package | |
| - name: Download SLSA provenance | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ needs.provenance.outputs.provenance-name }} | |
| path: provenance | |
| - name: Create git tag | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag "v${{ needs.detect.outputs.version }}" | |
| git push origin "v${{ needs.detect.outputs.version }}" | |
| - name: Build changelog from commits since previous tag | |
| id: changelog | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # 2nd entry by creation date is the previous tag (1st is the one we just pushed). | |
| PREV_TAG=$(git tag --sort=-creatordate | sed -n '2p' || true) | |
| if [ -n "$PREV_TAG" ]; then | |
| RANGE="$PREV_TAG..HEAD" | |
| HEADER="### Changes since $PREV_TAG" | |
| else | |
| # First-ever release tag — list everything up to HEAD (capped). | |
| RANGE="HEAD" | |
| HEADER="### Changes" | |
| fi | |
| { | |
| echo "header=$HEADER" | |
| echo 'log<<EOF' | |
| git log --pretty=format:"- %s (%h)" "$RANGE" | head -n 50 | |
| echo | |
| echo EOF | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ needs.detect.outputs.version }} | |
| name: v${{ needs.detect.outputs.version }} | |
| files: | | |
| target/package/*.crate | |
| provenance/*.intoto.jsonl | |
| body: | | |
| ## yield-curves v${{ needs.detect.outputs.version }} | |
| Published to crates.io: https://crates.io/crates/yield-curves/${{ needs.detect.outputs.version }} | |
| ${{ steps.changelog.outputs.header }} | |
| ${{ steps.changelog.outputs.log }} | |
| ### Verifying SLSA provenance | |
| This release ships a SLSA Level 3 provenance attestation generated by | |
| [`slsa-github-generator`](https://github.com/slsa-framework/slsa-github-generator). | |
| Verify with: | |
| ```bash | |
| slsa-verifier verify-artifact \ | |
| --provenance-path yield-curves-provenance.intoto.jsonl \ | |
| --source-uri github.com/${{ github.repository }} \ | |
| yield-curves-${{ needs.detect.outputs.version }}.crate | |
| ``` |