Run DR Legs policy with Warp-NN #1383
Workflow file for this run
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: Public API Change Detection | |
| permissions: {} | |
| on: | |
| pull_request_target: | |
| branches: | |
| - main | |
| - "release-*" | |
| concurrency: | |
| group: ${{ github.workflow }}-pr-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Safe under pull_request_target only because the trusted base-branch | |
| # detector parses the head statically; never execute head code here. | |
| detect-api-changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| if: github.repository == 'newton-physics/newton' | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 | |
| with: | |
| egress-policy: block | |
| allowed-endpoints: > | |
| api.github.com:443 | |
| github.com:443 | |
| release-assets.githubusercontent.com:443 | |
| - name: Checkout PR head | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name }} | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| path: head | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Checkout base branch history | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| ref: ${{ github.event.pull_request.base.sha }} | |
| path: base | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version-file: "base/.python-version" | |
| - name: Checkout PR merge base | |
| id: merge_base | |
| run: | | |
| script_path="${RUNNER_TEMP}/detect_api_changes.py" | |
| git -C base show "${{ github.event.pull_request.base.sha }}:scripts/ci/detect_api_changes.py" > "$script_path" | |
| git -C base fetch --no-tags ../head HEAD:refs/remotes/pr/head | |
| merge_base=$(git -C base merge-base HEAD refs/remotes/pr/head) | |
| git -C base checkout --detach "$merge_base" | |
| echo "script_path=$script_path" >> "$GITHUB_OUTPUT" | |
| - name: Detect API changes | |
| id: detect | |
| env: | |
| API_COMMENT_PATH: ${{ runner.temp }}/api-comment.md | |
| run: | | |
| output=$(python "${{ steps.merge_base.outputs.script_path }}" base head) | |
| needs_review=$(printf '%s' "$output" | python -c "import sys, json; print(str(json.load(sys.stdin)['needs_review']).lower())") | |
| echo "needs_review=$needs_review" >> "$GITHUB_OUTPUT" | |
| printf '%s' "$output" | python -c " | |
| import sys, json | |
| data = json.load(sys.stdin) | |
| print(data['comment']) | |
| " > "$API_COMMENT_PATH" | |
| - name: Sync API review | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| API_COMMENT_PATH: ${{ runner.temp }}/api-comment.md | |
| NEEDS_REVIEW: ${{ steps.detect.outputs.needs_review }} | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const needsReview = process.env.NEEDS_REVIEW === 'true'; | |
| const repo = { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| }; | |
| const issue = { | |
| ...repo, | |
| issue_number: context.issue.number, | |
| }; | |
| if (needsReview) { | |
| await github.rest.issues.addLabels({ | |
| ...issue, | |
| labels: ['api-changes'], | |
| }); | |
| } else { | |
| try { | |
| await github.rest.issues.removeLabel({ | |
| ...issue, | |
| name: 'api-changes', | |
| }); | |
| } catch (error) { | |
| // The current state is already correct when the label is absent. | |
| if (error.status !== 404) throw error; | |
| } | |
| } | |
| const marker = '<!-- newton-api-changes -->'; | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| ...issue, | |
| per_page: 100, | |
| }); | |
| const existing = comments.find((comment) => | |
| comment.user?.login === 'github-actions[bot]' && | |
| comment.user?.type === 'Bot' && | |
| comment.body?.startsWith(marker) | |
| ); | |
| if (!needsReview) { | |
| if (existing) { | |
| await github.rest.issues.deleteComment({ | |
| ...repo, | |
| comment_id: existing.id, | |
| }); | |
| } | |
| return; | |
| } | |
| const body = fs.readFileSync(process.env.API_COMMENT_PATH, 'utf8').trim(); | |
| if (!body) return; | |
| const fullBody = `${marker}\n${body}`; | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| ...repo, | |
| comment_id: existing.id, | |
| body: fullBody, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| ...issue, | |
| body: fullBody, | |
| }); | |
| } |