name: Check generated models # Verifies the committed generated files are still in sync with the Java OpenAPI # spec: the request models (toolApiTypes.ts, tool_models.py) and the tool I/O # tables saying what each endpoint accepts and produces (toolIO.ts, tool_io.py). # Regenerates them all with the single top-level `task tool-models` and fails if # any committed file is out of date. Called from build.yml when the # backend Java, frontend, or engine changes; also runs on push to main as a # post-merge safety net. on: workflow_call: push: branches: [main] permissions: contents: read jobs: generated-models: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 with: egress-policy: audit - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install uv uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true cache-dependency-glob: | engine/pyproject.toml engine/uv.lock cache-suffix: generated-models - name: Set up JDK 25 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 with: java-version: "25" distribution: "temurin" - name: Cache Gradle User Home uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'buildSrc/**', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }} restore-keys: | gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25- gradle-${{ runner.os }}-${{ runner.arch }}- - name: Set up Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" cache: "npm" cache-dependency-path: frontend/package-lock.json - name: Install Task uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0 - name: Verify generated models are up to date id: models-check continue-on-error: true run: task tool-models:check - name: Comment on generated models check failure # Only post a comment on PRs. github-script's PR helpers need an # issue/PR number, which doesn't exist on merge_group runs. if: steps.models-check.outcome == 'failure' && github.event_name == 'pull_request' continue-on-error: true uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const marker = ''; const body = [ marker, '### Generated Models Check Failed', '', 'One or more generated files are out of date with the Java OpenAPI spec and will need to be regenerated before they can be merged in.', '', 'Run `task tool-models` to regenerate them, then commit the updated files.', ].join('\n'); const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const existing = comments.find(c => c.body.includes(marker)); if (existing) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body, }); } else { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body, }); } - name: Fail if generated models check failed if: steps.models-check.outcome == 'failure' run: | echo "============================================" echo " Generated Models Check Failed" echo "============================================" echo "" echo "One or more generated files are out of date with the Java" echo "OpenAPI spec and will need to be regenerated before merging." echo "" echo "Run 'task tool-models' to regenerate them, then" echo "commit the updated files." echo "============================================" exit 1 - name: Remove generated models check comment on success if: steps.models-check.outcome == 'success' && github.event_name == 'pull_request' continue-on-error: true uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const marker = ''; const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const existing = comments.find(c => c.body.includes(marker)); if (existing) { await github.rest.issues.deleteComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, }); }