This is an automated email from the ASF dual-hosted git repository.
mfordjody pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git
The following commit(s) were added to refs/heads/master by this push:
new 72ab0d54 Add /lgtm merge docs and automatic project labels (#973)
72ab0d54 is described below
commit 72ab0d547fcc3b353bb396a50c1e2d4fd5c99405
Author: mfordjody <[email protected]>
AuthorDate: Mon Jul 20 14:34:27 2026 +0800
Add /lgtm merge docs and automatic project labels (#973)
* Document lgtm merge authorization
* Add automatic project labels
* Use native auto merge for lgtm
* Reset lgtm label after new commits
---
.asf.yaml | 2 +
.github/labeler.yml | 128 ++++++++++++++++++++++++++++++++++++++
.github/pull_request_template.md | 3 +
.github/workflows/ci.yml | 2 +-
.github/workflows/commands.yml | 124 +++---------------------------------
.github/workflows/labels.yml | 40 ++++++++++++
.github/workflows/review-gate.yml | 14 +++++
7 files changed, 197 insertions(+), 116 deletions(-)
diff --git a/.asf.yaml b/.asf.yaml
index 32f23cb0..9368bdf1 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -21,6 +21,8 @@ notifications:
github:
homepage: "https://kdubbo.github.io"
description: "Build a native mesh using gRPC and xDS"
+ pull_requests:
+ allow_auto_merge: true
labels:
- dubbo
- consul
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 00000000..e91a89a2
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,128 @@
+# 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.
+
+bug:
+ - head-branch:
+ - '^bug/'
+ - '^bugfix/'
+ - '^fix/'
+
+feature:
+ - head-branch:
+ - '^feat/'
+ - '^feature/'
+
+dependencies:
+ - any:
+ - head-branch:
+ - '^dependabot/'
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/go.mod'
+ - '**/go.sum'
+ - '.github/dependabot.yml'
+
+github_actions:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '.github/actions/**'
+ - '.github/workflows/**'
+
+go:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/*.go'
+ - '**/go.mod'
+ - '**/go.sum'
+
+python:
+ - changed-files:
+ - any-glob-to-any-file: '**/*.py'
+
+cni:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'cni/**'
+ - 'pkg/cni/**'
+
+dubboctl:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'cli/**'
+ - 'dubboctl/**'
+
+dubbod:
+ - changed-files:
+ - any-glob-to-any-file: 'dubbod/**'
+
+operator:
+ - changed-files:
+ - any-glob-to-any-file: 'operator/**'
+
+helm:
+ - changed-files:
+ - any-glob-to-any-file: 'manifests/charts/**'
+
+documentation:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/*.md'
+ - 'site/**'
+
+testing:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/*_test.go'
+ - 'tests/**'
+
+performance:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/*benchmark*'
+ - '**/benchmark/**'
+ - '.github/workflows/benchmark.yml'
+
+security:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '**/security/**'
+ - 'tools/govulncheck.py'
+ - '.github/workflows/security.yml'
+
+networking:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'dubbod/discovery/pkg/networking/**'
+ - 'pkg/adsc/**'
+ - 'pkg/xds/**'
+
+samples:
+ - changed-files:
+ - any-glob-to-any-file: 'samples/**'
+
+build:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'Makefile'
+ - 'tools/make/**'
+ - 'tools/ci/**'
+ - '**/Dockerfile*'
+ - '**/dockerfile*'
+
+release:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '.github/workflows/release.yaml'
+ - 'tools/release/**'
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 4de780b5..8ca27b42 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -31,6 +31,9 @@ limitations under the License.
<!-- List exact commands, environments, and results. Add screenshots or
cluster evidence when behavior is user-visible. -->
+> Merge authorization: after required checks pass, only an `/lgtm` comment
+> from `@mfordjody` authorizes the automatic squash merge.
+
## Compatibility and rollout
<!-- Describe upgrade, downgrade, API, configuration, performance, security,
and rollback implications. Write "None" when not applicable. -->
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0af3edaf..c5539223 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-name: Dubbo Kubernetes CI
+name: CI
on:
push:
diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml
index d5db43db..8c45f579 100644
--- a/.github/workflows/commands.yml
+++ b/.github/workflows/commands.yml
@@ -20,8 +20,8 @@
# /unassign [@user ...] remove assignees
# /lgtm (PR only) only an approver in the root OWNERS file
# can record Maintainer Approval. The PR is squash
-# merged immediately when CI is green, or by the
-# workflow-run handler when CI finishes.
+# merged immediately when CI is green, or queued with
+# GitHub Auto-merge while required checks finish.
# /lgtm cancel remove the `lgtm` label and reset approval
# /close close the issue/PR (author or write access)
# /reopen reopen the issue/PR (author or write access)
@@ -41,20 +41,8 @@ on:
issue_comment:
types:
- created
- workflow_run:
- workflows:
- - Dubbo Kubernetes CI
- types:
- - completed
- workflow_dispatch:
- inputs:
- pr_number:
- description: Pull request to reconsider for an approved merge
- required: true
- type: number
permissions:
- checks: read
contents: write
issues: write
pull-requests: write
@@ -273,14 +261,13 @@ jobs:
await reply(`Merged on behalf of @${commenter} via
\`/lgtm\`.`);
} catch (mergeErr) {
core.info(`Merge deferred until CI finishes:
${mergeErr.message}`);
- await github.rest.actions.createWorkflowDispatch({
- owner,
- repo,
- workflow_id: 'commands.yml',
- ref: pr.base.ref,
- inputs: {pr_number: String(pr.number)},
- });
- await reply(`\`/lgtm\` recorded by @${commenter}. The PR
will be squash merged automatically after required CI passes.`);
+ if (!pr.auto_merge) {
+ await github.graphql(
+ `mutation($id: ID!) { enablePullRequestAutoMerge(input:
{pullRequestId: $id, mergeMethod: SQUASH}) { pullRequest { number } } }`,
+ {id: pr.node_id},
+ );
+ }
+ await reply(`\`/lgtm\` recorded by @${commenter}. GitHub
Auto-merge will squash merge the PR after required CI passes.`);
}
return;
}
@@ -329,96 +316,3 @@ jobs:
return;
}
}
-
- merge-approved:
- name: Merge Approved Pull Request
- runs-on: ubuntu-latest
- timeout-minutes: 5
- if: |
- github.repository == 'apache/dubbo-kubernetes' &&
- (github.event_name == 'workflow_dispatch' ||
- (github.event_name == 'workflow_run' &&
- github.event.workflow_run.event == 'pull_request' &&
- github.event.workflow_run.conclusion == 'success'))
- steps:
- - name: Merge current-head pull request approved via /lgtm
- uses: actions/github-script@v7
- with:
- script: |
- const {owner, repo} = context.repo;
- let headSha;
- let candidates;
- if (context.eventName === 'workflow_dispatch') {
- const pullNumber = Number(context.payload.inputs.pr_number);
- const {data: pr} = await github.rest.pulls.get({owner, repo,
pull_number: pullNumber});
- headSha = pr.head.sha;
- candidates = [pr];
- } else {
- headSha = context.payload.workflow_run.head_sha;
- const {data: associated} = await
github.rest.repos.listPullRequestsAssociatedWithCommit({
- owner,
- repo,
- commit_sha: headSha,
- });
- candidates = associated.filter((pr) =>
- pr.state === 'open' &&
- pr.head.sha === headSha &&
- ['master', 'main'].includes(pr.base.ref),
- );
- }
-
- for (const candidate of candidates) {
- const {data: pr} = await github.rest.pulls.get({
- owner,
- repo,
- pull_number: candidate.number,
- });
- const labels = new Set(pr.labels.map((label) => label.name));
- if (pr.state !== 'open' || pr.head.sha !== headSha ||
- !['master', 'main'].includes(pr.base.ref) ||
!labels.has('lgtm')) {
- core.info(`#${pr.number}: missing lgtm label`);
- continue;
- }
-
- const {data: combined} = await
github.rest.repos.getCombinedStatusForRef({
- owner,
- repo,
- ref: headSha,
- });
- const approval = combined.statuses.find((status) =>
- status.context === 'Maintainer Approval Gate',
- );
- if (approval?.state !== 'success') {
- core.info(`#${pr.number}: maintainer approval is
${approval?.state || 'missing'}`);
- continue;
- }
-
- const {data: checks} = await github.rest.checks.listForRef({
- owner,
- repo,
- ref: headSha,
- per_page: 100,
- });
- const requiredCI = checks.check_runs.find((check) =>
- check.name === 'CI Required' && check.app?.slug ===
'github-actions',
- );
- if (requiredCI?.conclusion !== 'success') {
- core.info(`#${pr.number}: CI Required is
${requiredCI?.conclusion || requiredCI?.status || 'missing'}`);
- continue;
- }
-
- try {
- const {data: result} = await github.rest.pulls.merge({
- owner,
- repo,
- pull_number: pr.number,
- merge_method: 'squash',
- sha: headSha,
- });
- if (!result.merged) {
- core.setFailed(`#${pr.number}: ${result.message}`);
- }
- } catch (error) {
- core.setFailed(`#${pr.number}: ${error.message}`);
- }
- }
diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml
new file mode 100644
index 00000000..9de471b0
--- /dev/null
+++ b/.github/workflows/labels.yml
@@ -0,0 +1,40 @@
+# 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: Labels
+
+on:
+ pull_request_target:
+ types:
+ - opened
+ - reopened
+ - synchronize
+ - ready_for_review
+
+permissions:
+ contents: read
+ pull-requests: write
+
+jobs:
+ changed-files:
+ name: Apply PR Labels
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+ if: github.repository == 'apache/dubbo-kubernetes'
+ steps:
+ - name: Apply labels from changed paths
+ uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
+ with:
+ repo-token: ${{ github.token }}
diff --git a/.github/workflows/review-gate.yml
b/.github/workflows/review-gate.yml
index 855c8bab..e18c2eec 100644
--- a/.github/workflows/review-gate.yml
+++ b/.github/workflows/review-gate.yml
@@ -34,6 +34,7 @@ on:
permissions:
contents: read
+ issues: write
pull-requests: read
statuses: write
@@ -81,6 +82,19 @@ jobs:
return;
}
+ if (context.eventName === 'pull_request_target' &&
context.payload.action === 'synchronize') {
+ try {
+ await github.rest.issues.removeLabel({
+ owner,
+ repo,
+ issue_number: pr.number,
+ name: 'lgtm',
+ });
+ } catch (error) {
+ if (error.status !== 404) throw error;
+ }
+ }
+
await publish(
pr.head.sha,
'pending',