yuqi1129 commented on code in PR #13049:
URL: https://github.com/apache/gravitino/pull/13049#discussion_r4337457177


##########
.github/workflows/fork-ci-status.yml:
##########
@@ -0,0 +1,90 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.
+#
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Fork CI Status
+
+on:
+  pull_request_target:
+    types: [opened, synchronize, reopened]
+
+permissions:
+  actions: read
+  checks: write
+
+jobs:
+  notify:
+    name: Notify fork CI
+    if: github.repository == 'apache/gravitino'
+    runs-on: ubuntu-slim
+    steps:
+      - name: Create fork CI check
+        uses: actions/github-script@v7
+        with:
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+          script: |
+            const pr = context.payload.pull_request;
+            const owner = pr.head.repo.owner.login;
+            const repo = pr.head.repo.name;
+            const branch = pr.head.ref;
+            const headSha = pr.head.sha;
+            const workflow = 'fork-ci.yml';
+
+            let run;
+            for (let attempt = 0; attempt < 3 && !run; attempt++) {
+              if (attempt > 0) {
+                await new Promise(resolve => setTimeout(resolve, 3000));
+              }
+              try {
+                const runs = await github.paginate(
+                  'GET 
/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs',
+                  { owner, repo, workflow_id: workflow, branch, per_page: 100 
});
+                run = runs.find(candidate => candidate.head_sha === headSha);
+              } catch (error) {
+                core.warning(`Unable to read fork Actions: ${error.message}`);
+              }
+            }
+
+            const detailsUrl = run
+              ? `https://github.com/${owner}/${repo}/actions/runs/${run.id}`
+              : 
`https://github.com/${owner}/${repo}/actions/workflows/${workflow}`;
+            const status = !run || run.status === 'completed' ? 'completed' : 
'queued';
+            const conclusion = run && run.status === 'completed'
+              ? run.conclusion
+              : (run ? undefined : 'action_required');

Review Comment:
   Documented in `CONTRIBUTING.md`: Known limitations of Fork CI, and a bullet 
for reviewers to check `.github/` changes before trusting a green `Fork CI`. In 
addition, `b7ea75c` runs the ASF allowlist check upstream for PRs that change 
`.github/`, so that gate no longer depends on the fork's result.



##########
.github/workflows/asf-allowlist-check.yml:
##########
@@ -20,15 +20,8 @@
 name: "ASF Allowlist Check"
 
 on:
+  workflow_call:

Review Comment:
   Fixed in `b7ea75c`: the allowlist check also runs on `pull_request` in 
`apache/gravitino` when `.github/**` changes. It checks out the merge commit 
and skips the sync. Verified in the sandbox (upstream run passed in seconds).



##########
.github/workflows/asf-allowlist-check.yml:
##########
@@ -40,6 +33,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           persist-credentials: false
+      - uses: ./.github/actions/checkout-and-sync

Review Comment:
   Fixed in `b7ea75c`: `checkout-and-sync` takes a `persist-credentials` input, 
and the allowlist job passes `false`. The sandbox log shows the token removed 
from the git config after the fetch.



##########
.github/actions/checkout-and-sync/action.yml:
##########
@@ -0,0 +1,150 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Checkout and sync
+description: Check out the upstream base branch and merge the contributor 
branch for fork CI.
+
+outputs:
+  base-ref:
+    description: Upstream branch used as the comparison base.
+    value: ${{ steps.base.outputs.base_ref }}
+  base-sha:
+    description: Upstream commit checked out before merging contributor 
changes.
+    value: ${{ steps.upstream.outputs.base_sha }}
+  head-sha:
+    description: Commit tested after contributor changes are merged.
+    value: ${{ steps.head.outputs.head_sha }}
+  synced:
+    description: Whether contributor changes were merged onto the upstream 
base.
+    value: ${{ steps.base.outputs.should_sync }}
+
+runs:
+  using: composite
+  steps:
+    - name: Resolve pull request base branch
+      id: base
+      shell: bash
+      env:
+        EVENT_BASE_REF: ${{ github.base_ref }}
+        GH_TOKEN: ${{ github.token }}
+        HEAD_OWNER: ${{ github.repository_owner }}
+        HEAD_BRANCH: ${{ github.ref_name }}
+        HEAD_REPOSITORY: ${{ github.repository }}
+        HEAD_SHA: ${{ github.sha }}
+      run: |
+        set -euo pipefail
+
+        if [[ "${GITHUB_REPOSITORY}" == "apache/gravitino" && \
+          ("${GITHUB_REF}" == "refs/heads/main" || "${GITHUB_REF}" == 
refs/heads/branch-*) ]]; then
+          echo "base_ref=${GITHUB_REF_NAME}" >> "${GITHUB_OUTPUT}"
+          echo "should_sync=false" >> "${GITHUB_OUTPUT}"
+          exit 0
+        fi
+
+        repository_response="$(curl --fail-with-body --silent --show-error \
+          --header "Accept: application/vnd.github+json" \
+          --header "Authorization: Bearer ${GH_TOKEN}" \
+          --header "X-GitHub-Api-Version: 2022-11-28" \
+          "${GITHUB_API_URL}/repos/${HEAD_REPOSITORY}")"
+        source_repository="$(jq -r '.source.full_name // empty' <<< 
"${repository_response}")"
+
+        if [[ "${HEAD_REPOSITORY}" != "apache/gravitino" && \
+          "${source_repository}" != "apache/gravitino" ]]; then
+          echo "base_ref=${EVENT_BASE_REF:-${GITHUB_REF_NAME}}" >> 
"${GITHUB_OUTPUT}"
+          echo "should_sync=false" >> "${GITHUB_OUTPUT}"
+          exit 0
+        fi
+
+        response="[]"
+        match_count=0
+        for attempt in 1 2 3; do
+          response="$(curl --fail-with-body --silent --show-error \
+            --header "Accept: application/vnd.github+json" \
+            --header "Authorization: Bearer ${GH_TOKEN}" \
+            --header "X-GitHub-Api-Version: 2022-11-28" \
+            --get \
+            --data-urlencode "state=open" \
+            --data-urlencode "head=${HEAD_OWNER}:${HEAD_BRANCH}" \
+            --data-urlencode "per_page=10" \
+            "https://api.github.com/repos/apache/gravitino/pulls";)"
+          match_count="$(jq -r \
+            --arg head_sha "${HEAD_SHA}" \
+            --arg head_repository "${HEAD_REPOSITORY}" \
+            '[.[] | select(.head.sha == $head_sha and .head.repo.full_name == 
$head_repository)]
+             | length' \
+            <<< "${response}")"
+          if [[ "${match_count}" == "1" ]]; then
+            break
+          fi
+          if [[ "${attempt}" != "3" ]]; then
+            sleep 3
+          fi
+        done
+
+        if [[ "${match_count}" != "1" ]]; then

Review Comment:
   A PR closed or merged during the run no longer fails the remaining jobs: no 
matching PR falls back to the same base inference as a push without a PR. 
Suites can still sync onto different base commits if the base moves during the 
run; each suite logs the PR and base it tested, and the merged result is 
checked again by the post-merge run on `main`. Passing one base commit from 
eligibility to every suite needs a new input on all suite workflows, so I'd 
leave that for a follow-up.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to