@@ -43,6 +43,9 @@ def main() -> None:
4343 print ("Migrating pyproject license metadata to SPDX format..." )
4444 migrate_pyproject_license ()
4545 print ("=" * 72 )
46+ print ("Migrating auto-dependabot workflow to use GitHub App token..." )
47+ migrate_auto_dependabot_token ()
48+ print ("=" * 72 )
4649 print ()
4750
4851 if _manual_steps :
@@ -119,21 +122,6 @@ def migrate_to_ubuntu_slim() -> None:
119122 "new" : ' needs: ["create-github-release"]\n runs-on: ubuntu-slim' ,
120123 },
121124 ],
122- "auto-dependabot.yaml" : [
123- {
124- "job" : "auto-merge" ,
125- "old" : (
126- " auto-merge:\n "
127- " if: github.actor == 'dependabot[bot]'\n "
128- " runs-on: ubuntu-latest"
129- ),
130- "new" : (
131- " auto-merge:\n "
132- " if: github.actor == 'dependabot[bot]'\n "
133- " runs-on: ubuntu-slim"
134- ),
135- }
136- ],
137125 "release-notes-check.yml" : [
138126 {
139127 "job" : "check-release-notes" ,
@@ -298,6 +286,76 @@ def migrate_pyproject_license() -> None: # pylint: disable=too-many-branches
298286 print (" Updated pyproject.toml: migrated license metadata" )
299287
300288
289+ def migrate_auto_dependabot_token () -> None :
290+ """Migrate auto-dependabot workflow to use a GitHub App installation token.
291+
292+ This replaces the GITHUB_TOKEN with a GitHub App installation token to
293+ ensure that auto-merge and merge queue events are properly triggered.
294+ Using GITHUB_TOKEN suppresses subsequent workflow runs (by design), which
295+ prevents merge queue CI from running and can cause auto-merge to silently
296+ fail.
297+
298+ This migration intentionally overwrites `.github/workflows/auto-dependabot.yaml`
299+ with the template version, as the workflow is small and user customizations
300+ are not supported.
301+ """
302+ filepath = Path (".github" ) / "workflows" / "auto-dependabot.yaml"
303+ # This is separated only to avoid flake8 errors about line length
304+ dependabot_auto_approve_version = (
305+ "3cad5f42e79296505473325ac6636be897c8b8a1 # v1.3.2"
306+ )
307+ desired_content = (
308+ r"""name: Auto-merge Dependabot PR
309+
310+ on:
311+ pull_request:
312+
313+ permissions:
314+ contents: read
315+ pull-requests: write
316+
317+ jobs:
318+ auto-merge:
319+ if: github.actor == 'dependabot[bot]'
320+ runs-on: ubuntu-slim
321+ steps:
322+ - name: Generate GitHub App token
323+ id: app-token
324+ uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
325+ with:
326+ app-id: ${{ secrets.FREQUENZ_AUTO_DEPENDABOT_APP_ID }}
327+ private-key: ${{ secrets.FREQUENZ_AUTO_DEPENDABOT_APP_PRIVATE_KEY }}
328+
329+ - name: Auto-merge Dependabot PR
330+ uses: frequenz-floss/dependabot-auto-approve@"""
331+ + dependabot_auto_approve_version
332+ + r"""
333+ with:
334+ github-token: ${{ steps.app-token.outputs.token }}
335+ dependency-type: 'all'
336+ auto-merge: 'true'
337+ merge-method: 'merge'
338+ add-label: 'tool:auto-merged'
339+ """
340+ )
341+
342+ if filepath .exists ():
343+ content = filepath .read_text (encoding = "utf-8" ).replace ("\r \n " , "\n " )
344+ if content == desired_content :
345+ print (f" Skipped { filepath } : already up to date" )
346+ return
347+
348+ print (
349+ f" Replacing { filepath } with updated workflow (overwriting any local changes)"
350+ )
351+ replace_file_atomically (filepath , desired_content )
352+ return
353+
354+ filepath .parent .mkdir (parents = True , exist_ok = True )
355+ replace_file_atomically (filepath , desired_content )
356+ print (f" Added { filepath } : installed updated workflow" )
357+
358+
301359def read_project_type () -> str | None :
302360 """Read the cookiecutter project type from the replay file."""
303361 replay_path = Path (".cookiecutter-replay.json" )
0 commit comments