|
name: Dependabot auto-merge |
|
|
|
# Two auto-merge policies in one workflow. Sibling ExaDev packages (documents.js/odf.js) merge unconditionally once green -- no cooldown, matching this family's existing convention. Every other (third-party) dependency merges only for a minor or patch bump; a major bump still opens a PR via Dependabot but is left for manual review. Third-party updates additionally carry dependabot.yml's own 7-day cooldown before Dependabot proposes them at all. Auto-merge is enforced by main's own CI actually passing on the PR's head commit -- this workflow only requests the merge, GitHub itself withholds it until checks conclude -- and the merge authenticates via a GitHub App installation token specifically so the resulting push cascades into ci.yml/release, unlike a GITHUB_TOKEN-authenticated push. |
|
|
|
on: |
|
# pull_request_target, not pull_request -- a workflow run triggered by dependabot[bot]'s own pull_request |
|
# event gets NO secret access at all (a hard GitHub Actions security restriction against a compromised |
|
# dependency update exfiltrating secrets), so secrets.AUTOMERGE_APP_PRIVATE_KEY would resolve empty |
|
# regardless of how correctly the secret itself is configured. pull_request_target runs using the base |
|
# branch's own workflow file and normal secret access instead. Safe here specifically because this job |
|
# never checks out or executes the PR's own code -- it only calls the GitHub API (fetch-metadata, gh pr |
|
# merge), which is exactly the case pull_request_target's own security guidance calls out as safe. |
|
pull_request_target: |
|
|
|
permissions: |
|
contents: write |
|
pull-requests: write |
|
|
|
jobs: |
|
auto-merge: |
|
if: github.actor == 'dependabot[bot]' |
|
runs-on: ubuntu-latest |
|
timeout-minutes: 10 |
|
steps: |
|
- name: Fetch Dependabot metadata |
|
id: metadata |
|
uses: dependabot/fetch-metadata@v2 |
|
with: |
|
github-token: "${{ secrets.GITHUB_TOKEN }}" |
|
- name: Decide whether to auto-merge |
|
id: decide |
|
env: |
|
DEPENDENCY_NAMES: ${{ steps.metadata.outputs.dependency-names }} |
|
UPDATE_TYPE: ${{ steps.metadata.outputs.update-type }} |
|
run: | |
|
siblings="documents.js odf.js" |
|
is_sibling=false |
|
for name in $(echo "$DEPENDENCY_NAMES" | tr ',' ' '); do |
|
name=$(echo "$name" | xargs) |
|
for sib in $siblings; do |
|
if [ "$name" = "$sib" ]; then |
|
is_sibling=true |
|
fi |
|
done |
|
done |
|
if [ "$is_sibling" = "true" ]; then |
|
echo "merge=true" >> "$GITHUB_OUTPUT" |
|
elif [ "$UPDATE_TYPE" = "version-update:semver-minor" ] || [ "$UPDATE_TYPE" = "version-update:semver-patch" ]; then |
|
echo "merge=true" >> "$GITHUB_OUTPUT" |
|
else |
|
echo "merge=false" >> "$GITHUB_OUTPUT" |
|
fi |
|
- name: Generate a token for the merge |
|
id: app-token |
|
uses: actions/create-github-app-token@v2 |
|
with: |
|
app-id: "4473709" |
|
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }} |
|
- name: Enable auto-merge |
|
if: steps.decide.outputs.merge == 'true' |
|
run: gh pr merge --auto --rebase "$PR_URL" |
|
env: |
|
PR_URL: ${{ github.event.pull_request.html_url }} |
|
GH_TOKEN: ${{ steps.app-token.outputs.token }} |