From 297f250272d13a25152cdee2b8372bfca10df9f0 Mon Sep 17 00:00:00 2001 From: David Liu Date: Mon, 12 Oct 2026 17:14:01 +0000 Subject: [PATCH 1/2] Run fork integration's GitHub API jobs on allowlisted runners The databricks org IP allow list rejects GitHub API calls from GitHub-hosted runners, so `/integration-test` failed with HTTP 403 in the authorize job before anything ran. Move the authorize, reject, and report jobs to databricks-protected-runner-group, as ug-review and the user-journey gate already do, and read the PR through `gh api --jq` because that runner image does not guarantee a jq binary. Co-authored-by: Isaac --- .github/workflows/fork-integration.yml | 18 ++++++++++++------ tests/test_integration_contract.py | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/fork-integration.yml b/.github/workflows/fork-integration.yml index e7600f58d..3d93c41c6 100644 --- a/.github/workflows/fork-integration.yml +++ b/.github/workflows/fork-integration.yml @@ -21,7 +21,9 @@ jobs: startsWith(github.event.comment.body, '/integration-test ')) && contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) }} - runs-on: ubuntu-latest + runs-on: + group: databricks-protected-runner-group + labels: linux-ubuntu-latest timeout-minutes: 5 permissions: pull-requests: write @@ -47,9 +49,9 @@ jobs: [[ "$COMMENT_BODY" =~ ^/integration-test([[:space:]]+([0-9a-f]{7,40}))?[[:space:]]*$ ]] \ || refuse "use \`/integration-test\`, or \`/integration-test \` with the head commit you reviewed." requested="${BASH_REMATCH[2]}" - pr=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER") - sha=$(jq -r '.head.sha' <<<"$pr") - head_repo=$(jq -r '.head.repo.full_name // empty' <<<"$pr") + # gh's built-in --jq; the protected runner image does not guarantee a jq binary. + read -r sha head_repo < <(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" \ + --jq '[.head.sha, (.head.repo.full_name // "")] | @tsv') || true [[ "$sha" =~ ^[0-9a-f]{40}$ ]] || refuse "could not read the PR head commit." [ -n "$head_repo" ] || refuse "the fork repository no longer exists." # Naming the commit binds the run to what was reviewed, not to a later push. @@ -71,7 +73,9 @@ jobs: startsWith(github.event.comment.body, '/integration-test ')) && !contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) }} - runs-on: ubuntu-latest + runs-on: + group: databricks-protected-runner-group + labels: linux-ubuntu-latest timeout-minutes: 5 permissions: pull-requests: write @@ -104,7 +108,9 @@ jobs: name: Report fork integration needs: [authorize, integration] if: ${{ always() && needs.authorize.result == 'success' }} - runs-on: ubuntu-latest + runs-on: + group: databricks-protected-runner-group + labels: linux-ubuntu-latest timeout-minutes: 5 permissions: statuses: write diff --git a/tests/test_integration_contract.py b/tests/test_integration_contract.py index e46de2bb3..e14f12bc9 100644 --- a/tests/test_integration_contract.py +++ b/tests/test_integration_contract.py @@ -247,13 +247,13 @@ def test_fork_integration_authorize_pins_the_pr_head_or_the_reviewed_commit( script = textwrap.dedent(authorize.split(" run: |\n", 1)[1]) bin_dir = tmp_path / "bin" bin_dir.mkdir() - pr = {"head": {"sha": HEAD, "repo": {"full_name": head_repo} if head_repo else None}} - (tmp_path / "pr.json").write_text(json.dumps(pr)) + # What `gh api --jq '[.head.sha, (.head.repo.full_name // "")] | @tsv'` prints. + (tmp_path / "pr.tsv").write_text(f"{HEAD}\t{head_repo or ''}\n") fake_gh = bin_dir / "gh" fake_gh.write_text( "#!/bin/sh\n" f'echo "$*" >> "{tmp_path}/calls"\n' - f'case "$*" in "api repos/databricks/unity-gateway/pulls/7") cat "{tmp_path}/pr.json";; esac\n' + f'case "$*" in "api repos/databricks/unity-gateway/pulls/7 --jq "*) cat "{tmp_path}/pr.tsv";; esac\n' ) fake_gh.chmod(0o755) output = tmp_path / "github-output" @@ -284,6 +284,16 @@ def test_fork_integration_authorize_pins_the_pr_head_or_the_reviewed_commit( assert reason in calls and "statuses/" not in calls +def test_fork_integration_github_api_jobs_run_on_allowlisted_runners(): + # The org IP allow list rejects GitHub API calls from GitHub-hosted runners. + workflow = _workflow("fork-integration.yml") + protected = " runs-on:\n group: databricks-protected-runner-group\n" + + assert workflow.count(protected) == 3 + assert "runs-on: ubuntu-latest" not in workflow + assert not re.search(r"(?m)^\s*[^#\n]*\bjq\s+-", workflow) + + def test_no_workflow_uses_pull_request_target(): # GitHub disables pull_request_target by default in public repos from 2026-11-02. workflows = sorted((Path(__file__).parent.parent / ".github/workflows").glob("*.yml")) From 277b3dddd3fdd6f7c170e9e124b09efbe7ba4e7f Mon Sep 17 00:00:00 2001 From: David Liu Date: Mon, 12 Oct 2026 17:46:48 +0000 Subject: [PATCH 2/2] Tighten the fork integration runner and PR-read contract tests The fake gh now answers only the exact --jq query the authorize step sends, so changing that expression fails the test instead of passing on canned output. The runner test also checks the linux-ubuntu-latest label, since a misspelled label would leave the jobs queued. Co-authored-by: Isaac --- tests/test_integration_contract.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_integration_contract.py b/tests/test_integration_contract.py index e14f12bc9..5ca55ac3c 100644 --- a/tests/test_integration_contract.py +++ b/tests/test_integration_contract.py @@ -224,6 +224,8 @@ def test_fork_integration_runs_only_member_requested_pr_heads(): HEAD = "0123456789abcdef0123456789abcdef01234567" +# Verified against the live API on the protected runner; a text change here must be re-verified. +PR_HEAD_JQ = '[.head.sha, (.head.repo.full_name // "")] | @tsv' @pytest.mark.skipif(sys.platform == "win32", reason="the authorize step runs bash on Linux") @@ -247,13 +249,14 @@ def test_fork_integration_authorize_pins_the_pr_head_or_the_reviewed_commit( script = textwrap.dedent(authorize.split(" run: |\n", 1)[1]) bin_dir = tmp_path / "bin" bin_dir.mkdir() - # What `gh api --jq '[.head.sha, (.head.repo.full_name // "")] | @tsv'` prints. + # What real gh prints for that query; any other --jq expression gets no output and is refused. (tmp_path / "pr.tsv").write_text(f"{HEAD}\t{head_repo or ''}\n") fake_gh = bin_dir / "gh" fake_gh.write_text( "#!/bin/sh\n" f'echo "$*" >> "{tmp_path}/calls"\n' - f'case "$*" in "api repos/databricks/unity-gateway/pulls/7 --jq "*) cat "{tmp_path}/pr.tsv";; esac\n' + f"case \"$*\" in 'api repos/databricks/unity-gateway/pulls/7 --jq {PR_HEAD_JQ}')" + f' cat "{tmp_path}/pr.tsv";; esac\n' ) fake_gh.chmod(0o755) output = tmp_path / "github-output" @@ -287,7 +290,7 @@ def test_fork_integration_authorize_pins_the_pr_head_or_the_reviewed_commit( def test_fork_integration_github_api_jobs_run_on_allowlisted_runners(): # The org IP allow list rejects GitHub API calls from GitHub-hosted runners. workflow = _workflow("fork-integration.yml") - protected = " runs-on:\n group: databricks-protected-runner-group\n" + protected = " runs-on:\n group: databricks-protected-runner-group\n labels: linux-ubuntu-latest\n" assert workflow.count(protected) == 3 assert "runs-on: ubuntu-latest" not in workflow