diff --git a/.github/workflows/analyze-dependabot-reusable.yaml b/.github/workflows/analyze-dependabot-reusable.yaml
new file mode 100644
index 00000000..326656d4
--- /dev/null
+++ b/.github/workflows/analyze-dependabot-reusable.yaml
@@ -0,0 +1,59 @@
+#
+# 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: Dependabot Analyze PR
+
+on:
+ workflow_call: { }
+
+# Explicitly drop all permissions inherited from the caller for security.
+# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions
+permissions: { }
+
+jobs:
+
+ analyze-pull-request:
+ # Defense-in-depth (in case the caller forgets):
+ # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR;
+ # `github.event.pull_request.user.login` skips PRs not opened by Dependabot.
+ if: ${{
+ github.actor == 'dependabot[bot]'
+ && github.event.pull_request.user.login == 'dependabot[bot]'
+ }}
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: Fetch Dependabot metadata
+ id: dependabot
+ uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # 3.0.0
+ with:
+ github-token: ${{ github.token }}
+
+ # Creates the data required by the `process-dependabot-reusable` workflow as a JSON file.
+ - name: Create artifact
+ shell: bash
+ env:
+ UPDATED_DEPENDENCIES: ${{ steps.dependabot.outputs.updated-dependencies-json }}
+ run: |
+ echo "$UPDATED_DEPENDENCIES" > updated_dependencies.json
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1
+ with:
+ name: dependabot-metadata
+ path: updated_dependencies.json
diff --git a/.github/workflows/process-dependabot-reusable.yaml b/.github/workflows/process-dependabot-reusable.yaml
new file mode 100644
index 00000000..b46491a0
--- /dev/null
+++ b/.github/workflows/process-dependabot-reusable.yaml
@@ -0,0 +1,142 @@
+#
+# 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: Dependabot Process PR
+
+on:
+ workflow_call:
+ inputs:
+ changelog-path:
+ description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`)
+ required: true
+ type: string
+ secrets:
+ RECURSIVE_TOKEN:
+ description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run"
+ required: true
+
+# Explicitly drop all permissions inherited from the caller for security.
+# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions
+permissions: { }
+
+jobs:
+
+ generate-changelog:
+ # Defense-in-depth (in case the caller forgets):
+ # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR;
+ # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow.
+ if: ${{
+ github.actor == 'dependabot[bot]'
+ && github.event.workflow_run.conclusion == 'success'
+ }}
+ runs-on: ubuntu-latest
+ permissions:
+ # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR
+ # This requires the following two permissions:
+ contents: write
+ pull-requests: write
+
+ steps:
+
+ - name: Get pull request metadata
+ id: pr
+ env:
+ # Reference of the payload: https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run
+ #
+ # The structure of `pull_requests` is not documented, so we'll dump it for debugging purposes.
+ PULL_REQUESTS: ${{ toJSON(github.event.workflow_run.pull_requests) }}
+ run: |
+ # Print payload for debugging
+ jq <<< "$PULL_REQUESTS"
+ echo "id=$(echo "$PULL_REQUESTS" | jq -r '.[0].number')" >> "$GITHUB_OUTPUT"
+ echo "head-ref=$(echo "$PULL_REQUESTS" | jq -r '.[0].head.ref')" >> "$GITHUB_OUTPUT"
+
+ - name: Fetch Dependabot metadata
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # 8.0.1
+ with:
+ github-token: ${{ github.token }}
+ name: dependabot-metadata
+ path: ${{ runner.temp }}
+ run-id: ${{ github.event.workflow_run.id }}
+
+ - name: Check out repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
+ with:
+ ref: ${{ steps.pr.outputs.head-ref }}
+ token: ${{ secrets.RECURSIVE_TOKEN }}
+
+ - name: Create changelog entries
+ shell: bash
+ env:
+ PR_ID: ${{ steps.pr.outputs.id }}
+ PR_URL: ${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.pr.outputs.id }}
+ CHANGELOG_PATH: ${{ inputs.changelog-path }}
+ UPDATED_DEPENDENCIES: ${{ runner.temp }}/updated_dependencies.json
+ run: |
+ # Escapes special XML characters in a string
+ xml_escape() { sed 's/&/\&/g; s/\</g; s/>/\>/g; s/"/\"/g'; }
+
+ # Generates the content of a changelog entry
+ function generate_changelog_entry() {
+ local dependency="$1"
+ local issue_id=$(xml_escape <<< "$PR_ID")
+ local issue_link=$(xml_escape <<< "$PR_URL")
+ local dependency_name=$(echo "$dependency" | jq -r '.dependencyName' | xml_escape)
+ local new_version=$(echo "$dependency" | jq -r '.newVersion' | xml_escape)
+ cat << CHANGELOG_ENTRY
+
+
+
+ Update \`$dependency_name\` to version \`$new_version\`
+
+ CHANGELOG_ENTRY
+ }
+
+ # Ensure the changelog directory exists
+ mkdir -p "$CHANGELOG_PATH"
+ cd "$CHANGELOG_PATH"
+
+ # Generate the changelog entries for each updated dependency
+ cat "$UPDATED_DEPENDENCIES" | jq --compact-output '.[]' | while read -r dependency; do
+ # Extract the dependency name and version
+ dependency_name=$(echo "$dependency" | jq -r '.dependencyName')
+ changelog_file_name=$(echo "update_${dependency_name,,}.xml" | sed -r -e 's/[^a-z0-9.-]/_/g' -e 's/_+/_/g')
+ generate_changelog_entry "$dependency" > "$changelog_file_name"
+ done
+
+ - name: Add & commit changes
+ shell: bash
+ env:
+ CHANGELOG_PATH: ${{ inputs.changelog-path }}
+ PR_ID: ${{ steps.pr.outputs.id }}
+ run: |
+ git add "$CHANGELOG_PATH"
+ git config user.name "github-actions[bot]"
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git commit -m "Generate changelog entries for #$PR_ID"
+ git push origin
+
+ - name: Enable auto-merge on PR
+ shell: bash
+ env:
+ GH_TOKEN: ${{ github.token }}
+ PR_ID: ${{ steps.pr.outputs.id }}
+ run: |
+ gh pr merge --squash --auto "$PR_ID"
diff --git a/src/changelog/.12.x.x/add-deploy-profile.xml b/src/changelog/.12.x.x/add-deploy-profile.xml
new file mode 100644
index 00000000..a34fffff
--- /dev/null
+++ b/src/changelog/.12.x.x/add-deploy-profile.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ Added `process-dependabot-reusable` to handle Dependabot PRs under RTC restrictions.
+
+
diff --git a/.github/workflows/merge-dependabot.yaml b/src/site/antora/modules/ROOT/examples/analyze-dependabot.yaml
similarity index 52%
rename from .github/workflows/merge-dependabot.yaml
rename to src/site/antora/modules/ROOT/examples/analyze-dependabot.yaml
index 2d611cc1..81aefb12 100644
--- a/.github/workflows/merge-dependabot.yaml
+++ b/src/site/antora/modules/ROOT/examples/analyze-dependabot.yaml
@@ -15,28 +15,23 @@
# limitations under the License.
#
-name: merge-dependabot
+name: "Dependabot Analyze PR"
on:
- pull_request_target:
- paths-ignore:
- - "**.adoc"
- - "**.md"
- - "**.txt"
+ pull_request:
-permissions: read-all
+permissions: { }
jobs:
- build:
- if: github.repository == 'apache/logging-parent' && github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]'
- uses: ./.github/workflows/build-reusable.yaml
-
- merge-dependabot:
- needs: build
- uses: ./.github/workflows/merge-dependabot-reusable.yaml
- permissions:
- contents: write # to push changelog commits
- pull-requests: write # to close the PR
- secrets:
- GPG_SECRET_KEY: ${{ secrets.LOGGING_GPG_SECRET_KEY }} # to sign commits
+# tag::analyze-dependabot[]
+ analyze-dependabot:
+ # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR;
+ # `github.event.pull_request.user.login` skips PRs not opened by Dependabot.
+ if: ${{
+ github.repository == 'apache/logging-parent'
+ && github.actor == 'dependabot[bot]'
+ && github.event.pull_request.user.login == 'dependabot[bot]'
+ }}
+ uses: apache/logging-parent/.github/workflows/analyze-dependabot-reusable.yaml@rel/{project-version}
+# end::analyze-dependabot[]
diff --git a/src/site/antora/modules/ROOT/examples/process-dependabot.yaml b/src/site/antora/modules/ROOT/examples/process-dependabot.yaml
new file mode 100644
index 00000000..f40be8fc
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/process-dependabot.yaml
@@ -0,0 +1,50 @@
+#
+# 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: "Dependabot Process PR"
+
+on:
+ workflow_run:
+ workflows:
+ - "Dependabot Analyze PR"
+ types:
+ - completed
+
+permissions: { }
+
+jobs:
+
+# tag::process-dependabot[]
+ process-dependabot:
+ # Skip this workflow on commits not pushed by Dependabot
+ if: ${{
+ github.repository == 'apache/logging-parent'
+ && github.actor == 'dependabot[bot]'
+ && github.event.workflow_run.conclusion == 'success'
+ }}
+ uses: apache/logging-parent/.github/workflows/process-dependabot-reusable.yaml@rel/{project-version}
+ permissions:
+ # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR
+ # This requires the following two permissions:
+ contents: write
+ pull-requests: write
+ secrets:
+ RECURSIVE_TOKEN: ${{ secrets.DEPENDABOT_TOKEN }}
+ with:
+ # The path to the changelog directory for the current development branch.
+ changelog-path: src/changelog/.2.x.x
+# end::process-dependabot[]
diff --git a/src/site/antora/modules/ROOT/pages/workflows.adoc b/src/site/antora/modules/ROOT/pages/workflows.adoc
index e9ed9f90..62c64ca2 100644
--- a/src/site/antora/modules/ROOT/pages/workflows.adoc
+++ b/src/site/antora/modules/ROOT/pages/workflows.adoc
@@ -104,10 +104,64 @@ To verify the reproducibility of a release, you can use:
include::example$build.yaml[tag=verify-reproducibility-release,indent=0]
----
-[#merge-dependabot]
-== {project-github-url}/blob/main/.github/workflows/merge-dependabot-reusable.yaml[`merge-dependabot-reusable.yaml`]
+[#analyze-dependabot]
+== {project-github-url}/blob/main/.github/workflows/analyze-dependabot-reusable.yaml[`analyze-dependabot-reusable.yaml`]
-Merges Dependabot PRs along with changelog entries.
+Analyzes Dependabot pull requests to collect detailed information about updated dependencies.
+Stores the results in the `dependabot-metadata` artifact,
+which is later consumed by the <> workflow to automate changelog generation and PR processing.
+
+[NOTE]
+====
+This workflow must be triggered by an event that includes the `pull_request` payload and does not require any privileges.
+It can then be used in a `pull_request` workflow.
+====
+
+.Snippet from an {examples-base-link}/analyze-dependabot.yaml[example `analyze-dependabot.yaml`] using this workflow
+[source,yaml,subs=+attributes]
+----
+include::example$analyze-dependabot.yaml[tag=analyze-dependabot,indent=0]
+----
+
+[#process-dependabot]
+== {project-github-url}/blob/main/.github/workflows/process-dependabot-reusable.yaml[`process-dependabot-reusable.yaml`]
+
+Helps to process Dependabot pull requests by:
+
+* Generating changelog entries for the updated dependencies.
+* Enabling the "auto-merge" option for the pull request.
+
+The workflow needs the following privileged tokens:
+
+`GITHUB_TOKEN`::
+The default GitHub token with `contents:write` and `pull_requests:write` permissions,
+used to enable auto-merge on pull requests.
++
+This token is automatically provided by GitHub Actions, but needs to be configured in the `permissions` property.
+
+`RECURSIVE_TOKEN`::
+A GitHub token required to push generated changelog files as a new commit to the repository.
+The default `GITHUB_TOKEN` can **not** be used,
+as it will not trigger required check runs and will prevent the pull request from being merged.
+A Personal Access Token (PAT) with `contents:write` permission must be provided instead.
++
+The token must be passed as a secret named `RECURSIVE_TOKEN`.
+
+This workflow is designed to be triggered by the `workflow_run` event,
+as soon as the <> workflow completes.
+
+[NOTE]
+====
+When this workflow is triggered by `workflow_run`,
+GitHub Actions uses the "Actions" secret context instead of "Dependabot" secrets,
+even if the `github.actor` is `dependabot[bot]`.
+====
+
+.Snippet from an {examples-base-link}/process-dependabot.yaml[example `process-dependabot.yaml`] using this workflow
+[source,yaml,subs=+attributes]
+----
+include::example$process-dependabot.yaml[tag=process-dependabot,indent=0]
+----
[#deploy-site]
== {project-github-url}/blob/main/.github/workflows/deploy-site-reusable.yaml[`deploy-site-reusable.yaml`]