diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ef63e63..093a1fb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -25,6 +25,14 @@ regenerate `docs/cli.md` (it is generated — never edit it by hand). CI's `make verify-generated` fails on drift. +## Documented command output is generated + +- The `console` code blocks in `README.md`, `docs/*.md`, and `examples/*/README.md` + are trycmd cases: their expected output is verified by the `documentation` test. + The dependency report the CLI prints carries the versions declared in + `crates/oapi-codegen/Cargo.toml`, so a dependency bump changes that output. + After any dependency upgrade, run `make update-docs` and commit the result. + # Rust Coding Conventions and Best Practices Follow idiomatic Rust practices and community standards when writing Rust code. diff --git a/.github/workflows/automatic-prod-pr.yml b/.github/workflows/automatic-prod-pr.yml new file mode 100644 index 0000000..41c59a8 --- /dev/null +++ b/.github/workflows/automatic-prod-pr.yml @@ -0,0 +1,75 @@ +name: Automatic Production PR + +on: + schedule: + - cron: "0 0 * * 0" # Runs every Sunday at midnight UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + create-prod-pr: + runs-on: ubuntu-latest + steps: + - name: Create temporary GitHub App Token + id: app + uses: actions/create-github-app-token@v3 + with: + owner: ${{ github.repository_owner }} + client-id: ${{ vars.HOUSEKEEPING_BOT_APP_ID }} + repositories: ${{ github.event.repository.name }} + private-key: ${{ secrets.HOUSEKEEPING_BOT_PRIVATE_KEY }} + + - name: Checkout repository + uses: actions/checkout@v7 + with: + ref: develop + fetch-depth: 0 + token: ${{ steps.app.outputs.token }} + + - name: Check for changes between develop and main + id: check_changes + run: | + git fetch origin main develop + + if git diff --quiet origin/main...origin/develop; then + echo "No changes detected between develop and main" + echo "has_changes=false" >> "$GITHUB_OUTPUT" + else + echo "Changes detected between develop and main" + echo "has_changes=true" >> "$GITHUB_OUTPUT" + fi + + - name: Create Pull Request + if: steps.check_changes.outputs.has_changes == 'true' + id: create_pr + env: + GH_TOKEN: ${{ steps.app.outputs.token }} + run: | + # Check if PR already exists + EXISTING_PR=$(gh pr list --base main --head develop --json number --jq '.[0].number // empty') + + if [ -n "$EXISTING_PR" ]; then + echo "Pull request already exists: #$EXISTING_PR" + echo "pr_number=$EXISTING_PR" >> "$GITHUB_OUTPUT" + else + echo "Creating pull request from develop to main" + PR_URL=$(gh pr create \ + --title "chore: to production" \ + --body "" \ + --head develop \ + --base main) + + echo "Pull request created at: $PR_URL" + PR_NUMBER=$(gh pr view "$PR_URL" --json number --jq .number) + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + fi + + - name: Enable auto-merge + if: steps.check_changes.outputs.has_changes == 'true' + uses: alchemaxinc/composite-toolbox/merge-pr@v1 + with: + token: ${{ steps.app.outputs.token }} + pull-request-number: ${{ steps.create_pr.outputs.pr_number }} diff --git a/.github/workflows/check-openapi-versions.yml b/.github/workflows/check-openapi-versions.yml index 3254e65..6bb3e5d 100644 --- a/.github/workflows/check-openapi-versions.yml +++ b/.github/workflows/check-openapi-versions.yml @@ -29,6 +29,7 @@ jobs: with: owner: ${{ github.repository_owner }} client-id: ${{ vars.HOUSEKEEPING_BOT_APP_ID }} + repositories: ${{ github.event.repository.name }} private-key: ${{ secrets.HOUSEKEEPING_BOT_PRIVATE_KEY }} - name: Checkout and setup diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b914f89..813f98f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,26 @@ name: CI on: pull_request: + # Do not remove this trigger as redundant with `pull_request`: it exists to + # seed the shared cache on the default branch after merges; the checks already + # ran for the change in the pull request workflow. + # GitHub scopes every cache entry to the ref that wrote it, and a run may + # only read entries from its own ref, its base ref, or the default branch. + # A `pull_request`-only workflow therefore writes every entry into a + # `refs/pull/N/merge` scope that no other pull request can ever read, so + # each one starts cold, rebuilds everything, and saves yet another private + # copy. That churn previously consumed the whole 10 GB repository cache + # quota and evicted entries faster than they could be reused. + # + # Running on pushes to the default branch writes the entries into a scope + # every pull request can read, so one post-merge run seeds them all. + push: + branches: [develop] + concurrency: - cancel-in-progress: true + # Superseded pull request runs are worth cancelling, but a push to the + # default branch is what seeds the shared cache, so let it always finish. + cancel-in-progress: ${{ github.event_name == 'pull_request' }} group: ${{ github.workflow }}-${{ github.ref }} permissions: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7c52458..150a097 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,6 +41,7 @@ jobs: with: owner: ${{ github.repository_owner }} client-id: ${{ vars.HOUSEKEEPING_BOT_APP_ID }} + repositories: ${{ github.event.repository.name }} private-key: ${{ secrets.HOUSEKEEPING_BOT_PRIVATE_KEY }} - name: Checkout and setup diff --git a/.github/workflows/pr-title-lint.yml b/.github/workflows/pr-title-lint.yml index 36c86d3..2c00d8b 100644 --- a/.github/workflows/pr-title-lint.yml +++ b/.github/workflows/pr-title-lint.yml @@ -27,15 +27,12 @@ jobs: - name: Checkout code (shallow) uses: actions/checkout@v7 - - name: Cache Commitlint - id: cache-commitlint - uses: actions/cache@v6 - with: - path: node_modules - key: v1-commitlint-${{ env.COMMITLINT_CLI_VERSION }} - + # Deliberately not cached. This workflow only runs on `pull_request`, so + # every cache entry lands in a `refs/pull/N/merge` scope that no other + # pull request can read: each one paid the full install anyway and then + # wrote another ~12 MB private copy against the repository's 10 GB quota. + # Restoring the entry also costs about as long as the install it skips. - name: Install Commitlint - if: steps.cache-commitlint.outputs.cache-hit != 'true' run: npm i -D @commitlint/cli@${{ env.COMMITLINT_CLI_VERSION }} @commitlint/config-conventional @commitlint/types - name: Lint PR title (conventional commit) diff --git a/.github/workflows/update-deps-cargo.yml b/.github/workflows/update-deps-cargo.yml index 2a2438c..3ace570 100644 --- a/.github/workflows/update-deps-cargo.yml +++ b/.github/workflows/update-deps-cargo.yml @@ -4,6 +4,9 @@ on: schedule: - cron: "0 0 * * 0" # Run every Sunday at midnight +env: + BRANCH_PREFIX: update-cargo + jobs: update-cargo: runs-on: ubuntu-latest @@ -14,6 +17,7 @@ jobs: with: owner: ${{ github.repository_owner }} client-id: ${{ vars.HOUSEKEEPING_BOT_APP_ID }} + repositories: ${{ github.event.repository.name }} private-key: ${{ secrets.HOUSEKEEPING_BOT_PRIVATE_KEY }} - name: Update Cargo Dependencies @@ -23,6 +27,31 @@ jobs: auto-merge: "true" base-branch: "develop" merge-method: "squash" - branch-prefix: "update-cargo" + branch-prefix: ${{ env.BRANCH_PREFIX }} pr-title: "fix(deps): update cargo dependencies" commit-message: "fix(deps): update cargo dependencies" + + # The action leaves the working tree on the branch it created, so the + # regenerated output lands on the same pull request. + - name: Refresh the documented command output + run: | + set -euo pipefail + branch="$(git rev-parse --abbrev-ref HEAD)" + case "$branch" in + "$BRANCH_PREFIX"-*) ;; + *) + echo "::notice::No dependency-update branch exists; nothing to refresh." + exit 0 + ;; + esac + + make update-docs + + paths="$(make --no-print-directory print-generated-paths)" + if [ -z "$(git status --porcelain -- $paths)" ]; then + echo "::notice::The documented command output is already up to date." + exit 0 + fi + git add -- $paths + git commit -m "docs: refresh documented command output for updated dependencies" + git push origin "HEAD:$branch" diff --git a/.github/workflows/update-deps-github-actions.yml b/.github/workflows/update-deps-github-actions.yml index 85f29b3..2c04e0e 100644 --- a/.github/workflows/update-deps-github-actions.yml +++ b/.github/workflows/update-deps-github-actions.yml @@ -14,6 +14,7 @@ jobs: with: owner: ${{ github.repository_owner }} client-id: ${{ vars.HOUSEKEEPING_BOT_APP_ID }} + repositories: ${{ github.event.repository.name }} private-key: ${{ secrets.HOUSEKEEPING_BOT_PRIVATE_KEY }} - name: Update GitHub Actions diff --git a/Cargo.lock b/Cargo.lock index e22f2b9..3c09a50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" dependencies = [ "memchr", "serde_core", @@ -212,9 +212,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.3.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" dependencies = [ "find-msvc-tools", "shlex 2.0.1", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.4" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -261,9 +261,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.2" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -306,9 +306,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" dependencies = [ "percent-encoding", "time", @@ -354,13 +354,13 @@ checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -371,9 +371,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "encoding_rs" @@ -418,9 +418,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" [[package]] name = "form_urlencoded" @@ -433,9 +433,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -443,33 +443,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-sink" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-core", "futures-io", @@ -500,9 +500,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -520,9 +520,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", @@ -744,9 +744,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" [[package]] name = "is_terminal_polyfill" @@ -762,9 +762,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if", "futures-util", @@ -1228,9 +1228,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "similar" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6505efef05804732ed8a3f2d4f279429eb485bd69d5b0cc6b19cc02005cda16" +checksum = "85ee016af5d736b69fc89e19254540fa4b5f5492853fb5503920f084011c78b6" dependencies = [ "bstr", ] @@ -1362,9 +1362,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", "num-conv", @@ -1416,13 +1416,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -1451,9 +1451,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow", ] @@ -1648,9 +1648,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -1661,9 +1661,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.76" +version = "0.4.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" dependencies = [ "js-sys", "wasm-bindgen", @@ -1671,9 +1671,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1681,9 +1681,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", @@ -1694,18 +1694,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Makefile b/Makefile index 071a2b7..36993d3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,17 @@ SHELL := /bin/bash +RUST_VERSION := $(shell sed -n 's/^[[:space:]]*channel[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' rust-toolchain.toml) +ifeq ($(strip $(RUST_VERSION)),) +$(error could not read the toolchain channel from rust-toolchain.toml) +endif +export RUST_VERSION + +GENERATED_PATHS := \ + README.md \ + docs \ + examples \ + crates/oapi-codegen/tests/generated + .PHONY: help help: ## Show this help text @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ @@ -58,8 +70,9 @@ update-generated: ## Refresh generated files from the coverage fixtures UPDATE_GENERATED=1 cargo test -p oapi-codegen --test coverage .PHONY: update-docs -update-docs: ## Refresh docs/cli.md from the clap CLI definition +update-docs: ## Refresh docs/cli.md and the documented command output in Markdown files UPDATE_DOCS=1 cargo test -p oapi-codegen --test cli_docs + TRYCMD=overwrite cargo test -p oapi-codegen --test documentation .PHONY: generate-example generate-example: ## Regenerate the bookstore example from its OpenAPI specification @@ -77,16 +90,20 @@ verify-example: ## Fail when the bookstore example is out of date, without writi cargo run -q -p oapi-codegen -- --check --config-file oapi-codegen-server.yaml openapi.yaml && \ cargo run -q -p oapi-codegen -- --check --config-file oapi-codegen-client.yaml openapi.yaml +.PHONY: print-generated-paths +print-generated-paths: ## Print the paths that regeneration writes, one per line + @printf '%s\n' $(GENERATED_PATHS) + .PHONY: verify-generated verify-generated: ## Regenerate all generated files and fail when they differ from committed files $(MAKE) verify-example $(MAKE) update-generated $(MAKE) update-docs - @if [ -n "$$(git status --porcelain -- examples/bookstore/generated crates/oapi-codegen/tests/generated docs/cli.md)" ]; then \ + @if [ -n "$$(git status --porcelain -- $(GENERATED_PATHS))" ]; then \ echo "ERROR: generated files are out of date."; \ echo "Run 'make generate-example', 'make update-generated' and 'make update-docs'. Commit the result."; \ - git status --porcelain -- examples/bookstore/generated crates/oapi-codegen/tests/generated docs/cli.md; \ - git --no-pager diff -- examples/bookstore/generated crates/oapi-codegen/tests/generated docs/cli.md; \ + git status --porcelain -- $(GENERATED_PATHS); \ + git --no-pager diff -- $(GENERATED_PATHS); \ exit 1; \ fi @echo "Generated files are up to date." diff --git a/README.md b/README.md index 478dfe8..3e59a02 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,13 @@ $ oapi-codegen --config-file examples/bookstore/oapi-codegen-server.yaml example note: add the crates the generated code references to Cargo.toml: serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" - http = "1.4.2" + http = "1.5.0" axum = { version = "0.8.9", features = ["multipart"] } axum-extra = { version = "0.12.6", features = ["query"] } # or: cargo add serde@1.0.229 --features derive cargo add serde_json@1.0.151 - cargo add http@1.4.2 + cargo add http@1.5.0 cargo add axum@0.8.9 --features multipart cargo add axum-extra@0.12.6 --features query diff --git a/crates/oapi-codegen/Cargo.toml b/crates/oapi-codegen/Cargo.toml index 80c7c31..9ee0cac 100644 --- a/crates/oapi-codegen/Cargo.toml +++ b/crates/oapi-codegen/Cargo.toml @@ -28,8 +28,8 @@ workspace = true [dependencies] anstream = "1.0.0" -clap = { version = "4.6.4", features = ["derive"] } -http = "1.4.2" +clap = { version = "4.6.6", features = ["derive"] } +http = "1.5.0" indexmap = "2.14.0" openapiv3 = "2.2.0" owo-colors = "4.3.0" diff --git a/crates/oapi-codegen/tests/integration/client/Dockerfile b/crates/oapi-codegen/tests/integration/client/Dockerfile index 5d1a6c6..f3c33b6 100644 --- a/crates/oapi-codegen/tests/integration/client/Dockerfile +++ b/crates/oapi-codegen/tests/integration/client/Dockerfile @@ -4,7 +4,10 @@ # start; pre-building with `--no-run` means startup goes straight to the tests. # The build context is the repository root (see docker-compose.yml). -FROM rust:1.96-bookworm AS builder +# Kept in sync with rust-toolchain.toml by the Makefile: a mismatch makes +# rustup download a second toolchain inside the image on every build. +ARG RUST_VERSION=1.97.1 +FROM rust:${RUST_VERSION}-bookworm AS builder WORKDIR /src COPY . . RUN cargo test --no-run --locked -p bookstore-example --features client --test e2e diff --git a/crates/oapi-codegen/tests/integration/docker-compose.yml b/crates/oapi-codegen/tests/integration/docker-compose.yml index 2361f26..9bd5104 100644 --- a/crates/oapi-codegen/tests/integration/docker-compose.yml +++ b/crates/oapi-codegen/tests/integration/docker-compose.yml @@ -14,6 +14,8 @@ services: build: context: ../../../.. dockerfile: crates/oapi-codegen/tests/integration/server/Dockerfile + args: + RUST_VERSION: ${RUST_VERSION:-1.97.1} environment: BOOKSTORE_ADDR: 0.0.0.0:8080 expose: @@ -23,6 +25,8 @@ services: build: context: ../../../.. dockerfile: crates/oapi-codegen/tests/integration/client/Dockerfile + args: + RUST_VERSION: ${RUST_VERSION:-1.97.1} depends_on: - server environment: diff --git a/crates/oapi-codegen/tests/integration/server/Dockerfile b/crates/oapi-codegen/tests/integration/server/Dockerfile index 1e1a5c9..69fa306 100644 --- a/crates/oapi-codegen/tests/integration/server/Dockerfile +++ b/crates/oapi-codegen/tests/integration/server/Dockerfile @@ -1,14 +1,17 @@ # Build the bookstore server binary from the workspace, then run it from a slim # runtime image. The build context is the repository root (see docker-compose.yml). -FROM rust:1.96-bookworm AS builder +# Kept in sync with rust-toolchain.toml by the Makefile: a mismatch makes +# rustup download a second toolchain inside the image on every build. +ARG RUST_VERSION=1.97.1 +FROM rust:${RUST_VERSION}-bookworm AS builder WORKDIR /src COPY . . -RUN cargo build --release --locked -p bookstore-example --bin bookstore-server +RUN cargo build --locked -p bookstore-example --bin bookstore-server FROM debian:bookworm-slim AS runtime WORKDIR /app -COPY --from=builder /src/target/release/bookstore-server /usr/local/bin/bookstore-server +COPY --from=builder /src/target/debug/bookstore-server /usr/local/bin/bookstore-server ENV BOOKSTORE_ADDR=0.0.0.0:8080 EXPOSE 8080 CMD ["bookstore-server"] diff --git a/examples/bookstore/Cargo.toml b/examples/bookstore/Cargo.toml index 6f9d530..6658ea7 100644 --- a/examples/bookstore/Cargo.toml +++ b/examples/bookstore/Cargo.toml @@ -19,7 +19,7 @@ client = ["dep:reqwest", "dep:percent-encoding"] [dependencies] axum = { version = "0.8.9", features = ["multipart"] } axum-extra = { version = "0.12.6", features = ["query"] } -http = "1.3.1" +http = "1.5.0" serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" tokio = { version = "1.53.1", features = ["rt-multi-thread", "macros", "net"] } diff --git a/examples/bookstore/README.md b/examples/bookstore/README.md index b77b703..0332412 100644 --- a/examples/bookstore/README.md +++ b/examples/bookstore/README.md @@ -23,13 +23,13 @@ $ oapi-codegen --config-file oapi-codegen-server.yaml openapi.yaml note: add the crates the generated code references to Cargo.toml: serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" - http = "1.4.2" + http = "1.5.0" axum = { version = "0.8.9", features = ["multipart"] } axum-extra = { version = "0.12.6", features = ["query"] } # or: cargo add serde@1.0.229 --features derive cargo add serde_json@1.0.151 - cargo add http@1.4.2 + cargo add http@1.5.0 cargo add axum@0.8.9 --features multipart cargo add axum-extra@0.12.6 --features query @@ -37,12 +37,12 @@ $ oapi-codegen --config-file oapi-codegen-client.yaml openapi.yaml ✓ wrote generated/restclient.rs note: add the crates the generated code references to Cargo.toml: serde_json = "1.0.151" - http = "1.4.2" + http = "1.5.0" reqwest = { version = "0.13.4", default-features = false, features = ["blocking", "json", "form", "query", "multipart"] } percent-encoding = "2.3.2" # or: cargo add serde_json@1.0.151 - cargo add http@1.4.2 + cargo add http@1.5.0 cargo add reqwest@0.13.4 --no-default-features --features blocking,json,form,query,multipart cargo add percent-encoding@2.3.2