diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bba444c..98a5c49d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,8 @@ See [runtime coverage](maintainers/coverage.md) for coverage reports and focused After updating `openapi/openapi.yaml` from Hosting's public bundle, regenerate the internal client with `bin/generate-openapi` and check it with -`bin/check-openapi`. Keep generated code inside `lib/volcano/generated` and the realtime protocol +`bin/check-openapi`. The generator also refreshes `openapi/openapi.yaml.sha256`, +the digest the bundled-contract spec pins; commit it with the contract. Keep generated code inside `lib/volcano/generated` and the realtime protocol adapter behind the public facade. ## Coordinate SDK changes diff --git a/bin/check-openapi b/bin/check-openapi index 7d2ad7e4..fb5d41ba 100755 --- a/bin/check-openapi +++ b/bin/check-openapi @@ -14,4 +14,10 @@ if ! diff -qr "$expected" "$temporary/generated"; then exit 1 fi +actual_digest=$(ruby -rdigest -e 'puts Digest::SHA256.file(ARGV.fetch(0)).hexdigest' "$repo_root/openapi/openapi.yaml") +if [[ "$(tr -d '[:space:]' < "$repo_root/openapi/openapi.yaml.sha256")" != "$actual_digest" ]]; then + echo "openapi/openapi.yaml.sha256 is out of date; run bin/generate-openapi" >&2 + exit 1 +fi + echo "generated OpenAPI boundary is up to date" diff --git a/bin/generate-openapi b/bin/generate-openapi index 7fb41f68..59cec7b2 100755 --- a/bin/generate-openapi +++ b/bin/generate-openapi @@ -55,3 +55,12 @@ npx --no-install openapi-generator-cli generate \ -t openapi/templates \ -o "$output" \ --global-property apiTests=false,modelTests=false,apiDocs=false,modelDocs=false + +# Record the digest of the vendored contract next to it. The bundled-contract +# spec compares against this file, so a contract sync updates it here instead +# of by hand. Only the committed output refreshes it; freshness checks write to +# a temporary directory and leave it alone. +if [[ "$output" == "$committed_output" ]]; then + ruby -rdigest -e 'puts Digest::SHA256.file(ARGV.fetch(0)).hexdigest' \ + openapi/openapi.yaml > openapi/openapi.yaml.sha256 +fi diff --git a/openapi/openapi.yaml.sha256 b/openapi/openapi.yaml.sha256 new file mode 100644 index 00000000..bb7b29ca --- /dev/null +++ b/openapi/openapi.yaml.sha256 @@ -0,0 +1 @@ +7fec2090c1f4f4455b490a50ce2c92ef7ba82a1a71cfdb021ccc14adf5e1def8 diff --git a/spec/volcano_generation_spec.rb b/spec/volcano_generation_spec.rb index 98ececaa..e27d560a 100644 --- a/spec/volcano_generation_spec.rb +++ b/spec/volcano_generation_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Volcano do let(:root) { File.expand_path('..', __dir__) } - let(:openapi_sha256) { '7fec2090c1f4f4455b490a50ce2c92ef7ba82a1a71cfdb021ccc14adf5e1def8' } + let(:openapi_sha256) { File.read(File.join(root, 'openapi/openapi.yaml.sha256')).strip } it 'accepts current and legacy plan names in project responses' do project = described_class.const_get(:Generated).const_get(:Project)