API Spec Watch #97
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: API Spec Watch | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "15 5 * * *" | |
| permissions: | |
| contents: read | |
| issues: write | |
| jobs: | |
| openapi-drift: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Check OpenAPI drift | |
| id: openapi_check | |
| env: | |
| ISBNDB_OPENAPI_SOURCE_URL: ${{ vars.ISBNDB_OPENAPI_SOURCE_URL }} | |
| ISBNDB_OPENAPI_SOURCE_URL_SECRET: ${{ secrets.ISBNDB_OPENAPI_SOURCE_URL }} | |
| run: | | |
| source_url="${ISBNDB_OPENAPI_SOURCE_URL:-${ISBNDB_OPENAPI_SOURCE_URL_SECRET:-}}" | |
| if [ -z "${source_url}" ]; then | |
| echo "No OpenAPI source URL configured (vars/secrets ISBNDB_OPENAPI_SOURCE_URL)." | |
| echo "Skipping drift check." | |
| echo "configured=false" >> "${GITHUB_OUTPUT}" | |
| echo "drift=false" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| echo "configured=true" >> "${GITHUB_OUTPUT}" | |
| echo "source_url=${source_url}" >> "${GITHUB_OUTPUT}" | |
| set +e | |
| ./scripts/check_api_spec_changes.sh \ | |
| --source-url "${source_url}" \ | |
| --write-fetched /tmp/isbndb-openapi-candidate.json \ | |
| > /tmp/isbndb-openapi-check.log 2>&1 | |
| status=$? | |
| set -e | |
| cat /tmp/isbndb-openapi-check.log | |
| if [ "${status}" -eq 0 ]; then | |
| echo "drift=false" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| if [ "${status}" -eq 2 ]; then | |
| echo "drift=true" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| exit "${status}" | |
| - name: Create or update drift issue | |
| if: steps.openapi_check.outputs.configured == 'true' && steps.openapi_check.outputs.drift == 'true' | |
| uses: actions/github-script@v7 | |
| env: | |
| SOURCE_URL: ${{ steps.openapi_check.outputs.source_url }} | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const title = 'API drift detected in ISBNdb OpenAPI'; | |
| const label = 'api-drift'; | |
| const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`; | |
| const body = [ | |
| 'The scheduled OpenAPI drift check detected changes against the repository snapshot.', | |
| '', | |
| `- Source URL: ${process.env.SOURCE_URL}`, | |
| `- Workflow run: ${runUrl}`, | |
| '', | |
| 'Next steps:', | |
| '1. Download the `isbndb-openapi-candidate` artifact from this run.', | |
| '2. Compare with `api/upstream/isbndb-openapi.json`.', | |
| '3. Update package code/tests/docs if needed, then refresh the snapshot.', | |
| ].join('\n'); | |
| try { | |
| await github.rest.issues.createLabel({ | |
| owner, | |
| repo, | |
| name: label, | |
| color: 'd73a4a', | |
| description: 'OpenAPI drift detected by API Spec Watch', | |
| }); | |
| } catch (error) { | |
| if (error.status !== 422) { | |
| throw error; | |
| } | |
| } | |
| const existing = await github.rest.issues.listForRepo({ | |
| owner, | |
| repo, | |
| state: 'open', | |
| labels: label, | |
| per_page: 100, | |
| }); | |
| const openIssue = existing.data.find((issue) => issue.title === title); | |
| if (openIssue) { | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number: openIssue.number, | |
| body: `Drift detected again.\n\n${body}`, | |
| }); | |
| core.info(`Updated existing issue #${openIssue.number}`); | |
| } else { | |
| const created = await github.rest.issues.create({ | |
| owner, | |
| repo, | |
| title, | |
| body, | |
| labels: [label], | |
| }); | |
| core.info(`Created issue #${created.data.number}`); | |
| } | |
| - name: Upload fetched OpenAPI snapshot | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: isbndb-openapi-candidate | |
| path: | | |
| /tmp/isbndb-openapi-candidate.json | |
| /tmp/isbndb-openapi-check.log | |
| if-no-files-found: ignore | |
| - name: Fail when drift is detected | |
| if: steps.openapi_check.outputs.drift == 'true' | |
| run: | | |
| echo "OpenAPI drift detected against api/upstream/isbndb-openapi.json." | |
| exit 1 |