|
| 1 | +name: techapi-pr-validation-comment |
| 2 | + |
| 3 | +# TechAPI data PRs can ask this repository to validate their head commit and |
| 4 | +# leave a curator-facing comment back on the PR. This keeps the PR owned by the |
| 5 | +# human contributor while TechEngineBot reports the engine verdict. |
| 6 | +on: |
| 7 | + repository_dispatch: |
| 8 | + types: [techapi-pr-validate] |
| 9 | + workflow_dispatch: |
| 10 | + inputs: |
| 11 | + pr_number: |
| 12 | + description: "TechAPI PR number to comment on" |
| 13 | + type: string |
| 14 | + required: true |
| 15 | + head_sha: |
| 16 | + description: "TechAPI commit SHA to validate" |
| 17 | + type: string |
| 18 | + required: true |
| 19 | + pr_url: |
| 20 | + description: "TechAPI PR URL" |
| 21 | + type: string |
| 22 | + required: false |
| 23 | + default: "" |
| 24 | + |
| 25 | +permissions: |
| 26 | + contents: read |
| 27 | + |
| 28 | +concurrency: |
| 29 | + group: techapi-pr-validation-${{ github.event.client_payload.pr_number || inputs.pr_number }} |
| 30 | + cancel-in-progress: true |
| 31 | + |
| 32 | +jobs: |
| 33 | + validate: |
| 34 | + runs-on: ubuntu-latest |
| 35 | + env: |
| 36 | + TECHAPI_COMMENT_TOKEN: ${{ secrets.TECHENGINEBOT_TOKEN || secrets.TECHAPI_TOKEN }} |
| 37 | + TECHAPI_PR_NUMBER: ${{ github.event.client_payload.pr_number || inputs.pr_number }} |
| 38 | + TECHAPI_HEAD_SHA: ${{ github.event.client_payload.head_sha || inputs.head_sha }} |
| 39 | + TECHAPI_HEAD_REF: ${{ github.event.client_payload.head_ref || '' }} |
| 40 | + TECHAPI_PR_URL: ${{ github.event.client_payload.pr_url || inputs.pr_url }} |
| 41 | + REQUESTED_BY: ${{ github.event.client_payload.requested_by || github.actor }} |
| 42 | + TECHAPI_DATA_DIR: ${{ github.workspace }}/TechAPI/data |
| 43 | + steps: |
| 44 | + - name: Checkout TechEngine |
| 45 | + uses: actions/checkout@v4 |
| 46 | + |
| 47 | + - name: Checkout TechAPI PR head |
| 48 | + uses: actions/checkout@v4 |
| 49 | + with: |
| 50 | + repository: GetTechAPI/TechAPI |
| 51 | + ref: ${{ env.TECHAPI_HEAD_SHA }} |
| 52 | + path: TechAPI |
| 53 | + |
| 54 | + - uses: actions/setup-python@v5 |
| 55 | + with: |
| 56 | + python-version: "3.12" |
| 57 | + cache: pip |
| 58 | + |
| 59 | + - name: Install TechEngine |
| 60 | + run: pip install -e . |
| 61 | + |
| 62 | + - name: Validate TechAPI data |
| 63 | + id: validate |
| 64 | + shell: bash |
| 65 | + run: | |
| 66 | + set +e |
| 67 | + { |
| 68 | + echo "## app.validate" |
| 69 | + python -m app.validate |
| 70 | + echo "app_validate_status=$?" |
| 71 | + } > validation.log 2>&1 |
| 72 | + app_status=$(grep "app_validate_status=" validation.log | tail -n 1 | cut -d= -f2) |
| 73 | +
|
| 74 | + { |
| 75 | + echo |
| 76 | + echo "## integrity_check.py --strict" |
| 77 | + python integrity_check.py TechAPI/data --strict |
| 78 | + echo "integrity_status=$?" |
| 79 | + } >> validation.log 2>&1 |
| 80 | + integrity_status=$(grep "integrity_status=" validation.log | tail -n 1 | cut -d= -f2) |
| 81 | +
|
| 82 | + sed -i '/_status=/d' validation.log |
| 83 | +
|
| 84 | + status="success" |
| 85 | + if [ "${app_status:-1}" != "0" ] || [ "${integrity_status:-1}" != "0" ]; then |
| 86 | + status="failure" |
| 87 | + fi |
| 88 | +
|
| 89 | + echo "status=$status" >> "$GITHUB_OUTPUT" |
| 90 | + echo "app_status=${app_status:-1}" >> "$GITHUB_OUTPUT" |
| 91 | + echo "integrity_status=${integrity_status:-1}" >> "$GITHUB_OUTPUT" |
| 92 | +
|
| 93 | + - name: Build PR comment |
| 94 | + shell: bash |
| 95 | + run: | |
| 96 | + short_sha="${TECHAPI_HEAD_SHA:0:7}" |
| 97 | + result="PASS" |
| 98 | + if [ "${{ steps.validate.outputs.status }}" != "success" ]; then |
| 99 | + result="FAIL" |
| 100 | + fi |
| 101 | +
|
| 102 | + { |
| 103 | + echo "<!-- techengine-pr-validation -->" |
| 104 | + echo "## TechEngine validation: ${result}" |
| 105 | + echo |
| 106 | + echo "- PR: #${TECHAPI_PR_NUMBER}" |
| 107 | + echo "- Ref: \`${TECHAPI_HEAD_REF:-detached}\`" |
| 108 | + echo "- Commit: \`${short_sha}\`" |
| 109 | + echo "- Requested by: @${REQUESTED_BY}" |
| 110 | + echo "- Run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" |
| 111 | + echo |
| 112 | + echo "| Check | Result |" |
| 113 | + echo "| --- | --- |" |
| 114 | + echo "| \`python -m app.validate\` | $([ "${{ steps.validate.outputs.app_status }}" = "0" ] && echo PASS || echo FAIL) |" |
| 115 | + echo "| \`python integrity_check.py TechAPI/data --strict\` | $([ "${{ steps.validate.outputs.integrity_status }}" = "0" ] && echo PASS || echo FAIL) |" |
| 116 | + echo |
| 117 | + echo "<details><summary>Validation log</summary>" |
| 118 | + echo |
| 119 | + echo '```text' |
| 120 | + tail -c 6000 validation.log |
| 121 | + echo '```' |
| 122 | + echo |
| 123 | + echo "</details>" |
| 124 | + } > comment.md |
| 125 | +
|
| 126 | + - name: Comment on TechAPI PR |
| 127 | + if: env.TECHAPI_COMMENT_TOKEN != '' |
| 128 | + env: |
| 129 | + GH_TOKEN: ${{ env.TECHAPI_COMMENT_TOKEN }} |
| 130 | + shell: bash |
| 131 | + run: | |
| 132 | + set -euo pipefail |
| 133 | + marker="<!-- techengine-pr-validation -->" |
| 134 | + comment_id="$(gh api "repos/GetTechAPI/TechAPI/issues/${TECHAPI_PR_NUMBER}/comments" --paginate \ |
| 135 | + --jq ".[] | select(.body | contains(\"${marker}\")) | .id" | tail -n 1)" |
| 136 | + jq -n --rawfile body comment.md '{body: $body}' > comment.json |
| 137 | + if [ -n "$comment_id" ]; then |
| 138 | + gh api "repos/GetTechAPI/TechAPI/issues/comments/${comment_id}" \ |
| 139 | + --method PATCH \ |
| 140 | + --input comment.json |
| 141 | + else |
| 142 | + gh api "repos/GetTechAPI/TechAPI/issues/${TECHAPI_PR_NUMBER}/comments" \ |
| 143 | + --method POST \ |
| 144 | + --input comment.json |
| 145 | + fi |
| 146 | +
|
| 147 | + - name: Warn when comment token is unset |
| 148 | + if: env.TECHAPI_COMMENT_TOKEN == '' |
| 149 | + run: echo "::warning::TECHENGINEBOT_TOKEN/TECHAPI_TOKEN is not configured; validation ran but no PR comment was posted." |
| 150 | + |
| 151 | + - name: Fail on validation errors |
| 152 | + if: steps.validate.outputs.status != 'success' |
| 153 | + run: exit 1 |
0 commit comments