Skip to content
Merged
2 changes: 1 addition & 1 deletion .github/actions/tidb_build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ inputs:
required: true
gcp_sa_key:
description: GCP service account key JSON content
required: true
required: false
runs:
using: composite
steps:
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/generate-bazel-files.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Generate Bazel Files
on:
pull_request:
branches:
- master
types:
- opened
- synchronize
- reopened
- ready_for_review

permissions:
contents: read

concurrency:
group: generate-bazel-files-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
generate:
name: Generate Bazel Files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
- name: Build Prepare
uses: pingcap/tidb/.github/actions/tidb_build@fb17a419f54d51f45fd031d8e5069b7022ecec92
with:
bazelrc: ""
gcp_sa_key: ""
go-version: 1.25
- name: Run Bazel Prepare
shell: bash
run: |
#!/bin/bash
unset CI
sed -i '/bazel-cache/d' DEPS.bzl
sed -i '/ats.apps.svc/d' DEPS.bzl
sed -i '/bazel-cache/d' WORKSPACE
sed -i '/ats.apps.svc/d' WORKSPACE
make bazel_prepare
- name: Restore non-generated files
shell: bash
run: |
git restore --worktree --source=HEAD -- WORKSPACE
- name: Create Bazel Patch
shell: bash
run: |
set -euo pipefail

mapfile -t tracked_changes < <(git diff --name-only --no-renames HEAD -- .)
mapfile -t untracked_changes < <(git ls-files --others --exclude-standard)
changed_files=("${tracked_changes[@]}" "${untracked_changes[@]}")

for path in "${changed_files[@]}"; do
if [[ -z "${path}" ]]; then
continue
fi

case "${path}" in
DEPS.bzl|*.bazel|*.bzl)
;;
*)
echo "Unexpected file changed by bazel_prepare: ${path}" >&2
exit 1
;;
esac
done

if ((${#untracked_changes[@]} > 0)); then
git add -N -- "${untracked_changes[@]}"
fi

mkdir -p bazel-artifact
git diff --binary --full-index --no-ext-diff -- \
DEPS.bzl \
':(glob)**/*.bazel' \
':(glob)**/*.bzl' \
> bazel-artifact/bazel.patch
- name: Upload Bazel Files Artifact
uses: actions/upload-artifact@v4
with:
name: bazel-files
path: bazel-artifact/bazel.patch
if-no-files-found: error
retention-days: 1
164 changes: 127 additions & 37 deletions .github/workflows/update-bazel-files.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,149 @@
name: Update Bazel Files
on:
pull_request_target:
branches:
- master
workflow_run:
workflows:
- Generate Bazel Files
types:
- opened
- synchronize
- reopened
- ready_for_review
- completed

permissions:
actions: read
contents: write
pull-requests: read

concurrency:
group: update-bazel-files-${{ github.event.pull_request.number }}
group: update-bazel-files-${{ github.event.workflow_run.id }}
cancel-in-progress: true

jobs:
update:
name: Update Bazel Files
if: >
github.event.pull_request.head.repo.full_name == github.repository ||
github.event.pull_request.maintainer_can_modify
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Resolve PR metadata
id: pr
shell: bash
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
set -euo pipefail

pr_number="$(gh api "repos/${REPOSITORY}/actions/runs/${RUN_ID}" --jq '.pull_requests[0].number')"
head_repo="$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.full_name')"
head_ref="$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.ref')"
pr_head_sha="$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.sha')"
run_head_sha="$(gh api "repos/${REPOSITORY}/actions/runs/${RUN_ID}" --jq '.head_sha')"

printf 'pr_number=%s\n' "${pr_number}" >> "${GITHUB_OUTPUT}"
printf 'head_repo=%s\n' "${head_repo}" >> "${GITHUB_OUTPUT}"
printf 'head_ref=%s\n' "${head_ref}" >> "${GITHUB_OUTPUT}"

if [[ "${head_repo}" != "${REPOSITORY}" ]]; then
echo "same_repo=false" >> "${GITHUB_OUTPUT}"
exit 0
fi

echo "same_repo=true" >> "${GITHUB_OUTPUT}"

if [[ "${pr_head_sha}" != "${run_head_sha}" ]]; then
echo "stale=true" >> "${GITHUB_OUTPUT}"
exit 0
fi

echo "stale=false" >> "${GITHUB_OUTPUT}"
Comment thread
hawkingrei marked this conversation as resolved.
- name: Skip stale workflow run
if: steps.pr.outputs.same_repo == 'true' && steps.pr.outputs.stale == 'true'
shell: bash
run: |
echo "Skip stale bazel update for PR #${{ steps.pr.outputs.pr_number }}."
- name: Checkout PR branch
if: steps.pr.outputs.same_repo == 'true' && steps.pr.outputs.stale != 'true'
uses: actions/checkout@v6
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ steps.pr.outputs.head_repo }}
ref: ${{ steps.pr.outputs.head_ref }}
path: pr
fetch-depth: 0
token: ${{ secrets.BAZEL_PREPARE_PUSH_TOKEN || github.token }}
- name: Build Prepare
uses: ./.github/actions/tidb_build
token: ${{ github.token }}
persist-credentials: false
- name: Download Bazel Files Artifact
if: steps.pr.outputs.same_repo == 'true' && steps.pr.outputs.stale != 'true'
uses: actions/download-artifact@v4
with:
bazelrc: ${{ secrets.BAZELRC }}
gcp_sa_key: ${{ secrets.GCP_SA_KEY }}
go-version: 1.25
- name: Run Bazel Prepare
name: bazel-files
path: bazel-artifact
repository: ${{ github.repository }}
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}
- name: Apply Bazel Files Artifact
if: steps.pr.outputs.same_repo == 'true' && steps.pr.outputs.stale != 'true'
shell: bash
run: |
#!/bin/bash
unset CI
sed -i '/bazel-cache/d' DEPS.bzl
sed -i '/ats.apps.svc/d' DEPS.bzl
sed -i '/bazel-cache/d' WORKSPACE
sed -i '/ats.apps.svc/d' WORKSPACE
make bazel_prepare
set -euo pipefail

patch_path="${PWD}/bazel-artifact/bazel.patch"
summary="$(git apply --summary "${patch_path}")"

while IFS= read -r line; do
case "${line}" in
" rename "*|" copy "*)
echo "Unsupported patch summary: ${line}" >&2
exit 1
;;
esac
done <<< "${summary}"

declare -A seen_paths=()

while IFS= read -r -d '' record; do
if [[ -z "${record}" ]]; then
continue
fi

IFS=$'\t' read -r _ _ path <<< "${record}"

case "${path}" in
""|/*|..|../*|*/..|*/../*)
echo "Unexpected patch path: ${path}" >&2
exit 1
;;
DEPS.bzl|*.bazel|*.bzl)
;;
*)
echo "Unexpected patch path: ${path}" >&2
exit 1
;;
esac

if [[ -n "${seen_paths[${path}]:-}" ]]; then
echo "Duplicate patch path: ${path}" >&2
exit 1
fi
seen_paths["${path}"]=1
done < <(git apply --numstat -z "${patch_path}")

git -C pr apply --check --index "${patch_path}"
git -C pr apply --index "${patch_path}"
- name: Commit Bazel Files
uses: stefanzweifel/git-auto-commit-action@v5
with:
branch: ${{ github.event.pull_request.head.ref }}
commit_message: "chore: update bazel file"
disable_globbing: true
file_pattern: >-
DEPS.bzl
:(top,glob)**/*.bazel
:(top,glob)**/*.bzl
if: steps.pr.outputs.same_repo == 'true' && steps.pr.outputs.stale != 'true'
shell: bash
env:
HEAD_REF: ${{ steps.pr.outputs.head_ref }}
PUSH_TOKEN: ${{ github.token }}
TARGET_REPOSITORY: ${{ steps.pr.outputs.head_repo }}
run: |
set -euo pipefail

if git -C pr diff --cached --quiet -- DEPS.bzl ':(glob)**/*.bazel' ':(glob)**/*.bzl'; then
echo "No generated Bazel changes to commit."
exit 0
fi

git -C pr config user.name "Ti Chi Robot"
git -C pr config user.email "ti-community-prow-bot@tidb.io"
git -C pr commit -m "chore: update bazel file"
git -C pr push "https://x-access-token:${PUSH_TOKEN}@github.com/${TARGET_REPOSITORY}.git" "HEAD:${HEAD_REF}"
Loading