Merge pull request #3088 from github/dependabot/github_actions/actions-f739f361ea

Bump the actions group with 4 updates
This commit is contained in:
Henry Mercer
2025-09-23 13:48:16 +01:00
committed by GitHub
54 changed files with 510 additions and 73 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'true'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+3 -3
View File
@@ -59,7 +59,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Remove CodeQL from toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
@@ -69,7 +69,7 @@ jobs:
- name: Install @actions/tool-cache
run: npm install @actions/tool-cache
- name: Check toolcache does not contain CodeQL
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const toolcache = require('@actions/tool-cache');
@@ -88,7 +88,7 @@ jobs:
output: ${{ runner.temp }}/results
upload-database: false
- name: Check CodeQL is installed within the toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const toolcache = require('@actions/tool-cache');
+2 -2
View File
@@ -59,7 +59,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Remove CodeQL from toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
@@ -84,7 +84,7 @@ jobs:
path: ${{ runner.temp }}/results/javascript.sarif
retention-days: 7
- name: Check diagnostic with expected tools URL appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
with:
+1 -1
View File
@@ -80,7 +80,7 @@ jobs:
path: ${{ runner.temp }}/results/javascript.sarif
retention-days: 7
- name: Check config properties appear in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
with:
+1 -1
View File
@@ -48,7 +48,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
+1 -1
View File
@@ -91,7 +91,7 @@ jobs:
path: ${{ runner.temp }}/results/javascript.sarif
retention-days: 7
- name: Check diagnostics appear in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
with:
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
@@ -74,7 +74,7 @@ jobs:
languages: go
tools: ${{ steps.prepare-test.outputs.tools-url }}
# Deliberately change Go after the `init` step
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: '1.20'
- name: Build code
@@ -84,7 +84,7 @@ jobs:
output: ${{ runner.temp }}/results
upload-database: false
- name: Check diagnostic appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/go.sarif
with:
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
@@ -85,7 +85,7 @@ jobs:
output: ${{ runner.temp }}/results
upload-database: false
- name: Check diagnostic appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/go.sarif
with:
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -99,7 +99,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -99,7 +99,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -99,7 +99,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -99,7 +99,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
@@ -74,7 +74,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
@@ -88,7 +88,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+2 -2
View File
@@ -74,7 +74,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
@@ -88,7 +88,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+2 -2
View File
@@ -74,7 +74,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
@@ -88,7 +88,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+2 -2
View File
@@ -74,7 +74,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
@@ -88,7 +88,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+2 -2
View File
@@ -133,7 +133,7 @@ jobs:
retention-days: 7
- name: Check quality query does not appear in security SARIF
if: contains(matrix.analysis-kinds, 'code-scanning')
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
EXPECT_PRESENT: 'false'
@@ -141,7 +141,7 @@ jobs:
script: ${{ env.CHECK_SCRIPT }}
- name: Check quality query appears in quality SARIF
if: contains(matrix.analysis-kinds, 'code-quality')
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.quality.sarif
EXPECT_PRESENT: 'true'
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -75,7 +75,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ inputs.go-version || '>=1.21.0' }}
cache: false
@@ -61,7 +61,7 @@ jobs:
uses: actions/checkout@v5
- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: '20'
cache: 'npm'
@@ -50,7 +50,7 @@ jobs:
uses: ./.github/actions/prepare-test
with:
version: ${{ matrix.version }}
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ^1.13.1
- uses: ./../action/init
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
uses: ./.github/actions/prepare-test
with:
version: ${{ matrix.version }}
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ^1.13.1
- uses: ./../action/init
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
- uses: actions/checkout@v5
with:
fetch-depth: 0 # ensure we have all tags and can push commits
- uses: actions/setup-node@v4
- uses: actions/setup-node@v5
- name: Update git config
run: |
+6 -2
View File
@@ -33,13 +33,13 @@ jobs:
- uses: actions/checkout@v5
- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: '20.x'
cache: 'npm'
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: 3.11
@@ -59,6 +59,10 @@ jobs:
- name: Run unit tests
run: npm test
- name: Run pr-checks tests
working-directory: pr-checks
run: python -m unittest discover
- name: Lint
if: matrix.os != 'windows-latest'
run: npm run lint-ci
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: 3.12
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
uses: actions/checkout@v5
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: 20.x
cache: npm
+15 -6
View File
@@ -15,6 +15,10 @@ jobs:
runs-on: ubuntu-latest
if: github.event.label.name == 'Rebuild' || github.event_name == 'workflow_dispatch'
env:
HEAD_REF: ${{ github.event.pull_request.head.ref || github.event.ref }}
BASE_BRANCH: ${{ github.event.pull_request.base.ref || 'main' }}
permissions:
contents: write # needed to push rebuilt commit
pull-requests: write # needed to comment on the PR
@@ -23,7 +27,7 @@ jobs:
uses: actions/checkout@v5
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref || github.event.ref }}
ref: ${{ env.HEAD_REF }}
- name: Remove label
if: github.event_name == 'pull_request'
@@ -41,8 +45,6 @@ jobs:
- name: Merge in changes from base branch
id: merge
env:
BASE_BRANCH: ${{ github.event.pull_request.base.ref || 'main' }}
run: |
git fetch origin "$BASE_BRANCH"
@@ -72,13 +74,20 @@ jobs:
npm run build
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: 3.11
- name: Generate workflows
- name: Sync back version updates to generated workflows
# Only sync back versions on Dependabot update PRs
if: startsWith(env.HEAD_REF, 'dependabot/')
working-directory: pr-checks
run: |
python3 sync_back.py -v
- name: Generate workflows
working-directory: pr-checks
run: |
cd pr-checks
python -m pip install --upgrade pip
pip install ruamel.yaml==0.17.31
python3 sync.py
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
git config --global user.name "github-actions[bot]"
- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: '20.x'
cache: 'npm'
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
(gh release view --repo "$GITHUB_REPOSITORY" --json "assets" "$RELEASE_TAG" && echo "Release found.") || exit 1
- name: Install Node
uses: actions/setup-node@v4
uses: actions/setup-node@v5
- name: Checkout repository
uses: actions/checkout@v5
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Setup Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Checkout CodeQL Action
+2
View File
@@ -1 +1,3 @@
env
__pycache__/
*.pyc
View File
+3 -3
View File
@@ -8,7 +8,7 @@ operatingSystems:
- windows
steps:
- name: Remove CodeQL from toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
@@ -18,7 +18,7 @@ steps:
- name: Install @actions/tool-cache
run: npm install @actions/tool-cache
- name: Check toolcache does not contain CodeQL
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const toolcache = require('@actions/tool-cache');
@@ -37,7 +37,7 @@ steps:
output: ${{ runner.temp }}/results
upload-database: false
- name: Check CodeQL is installed within the toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const toolcache = require('@actions/tool-cache');
+2 -2
View File
@@ -8,7 +8,7 @@ operatingSystems:
- windows
steps:
- name: Remove CodeQL from toolcache
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
@@ -33,7 +33,7 @@ steps:
path: ${{ runner.temp }}/results/javascript.sarif
retention-days: 7
- name: Check diagnostic with expected tools URL appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
with:
+1 -1
View File
@@ -18,7 +18,7 @@ steps:
path: "${{ runner.temp }}/results/javascript.sarif"
retention-days: 7
- name: Check config properties appear in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
with:
+1 -1
View File
@@ -31,7 +31,7 @@ steps:
path: "${{ runner.temp }}/results/javascript.sarif"
retention-days: 7
- name: Check diagnostics appear in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
with:
@@ -12,7 +12,7 @@ steps:
languages: go
tools: ${{ steps.prepare-test.outputs.tools-url }}
# Deliberately change Go after the `init` step
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: "1.20"
- name: Build code
@@ -22,7 +22,7 @@ steps:
output: "${{ runner.temp }}/results"
upload-database: false
- name: Check diagnostic appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/go.sarif"
with:
@@ -23,7 +23,7 @@ steps:
output: "${{ runner.temp }}/results"
upload-database: false
- name: Check diagnostic appears in SARIF
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/go.sarif"
with:
+2 -2
View File
@@ -54,7 +54,7 @@ steps:
retention-days: 7
- name: Check quality query does not appear in security SARIF
if: contains(matrix.analysis-kinds, 'code-scanning')
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
EXPECT_PRESENT: "false"
@@ -62,7 +62,7 @@ steps:
script: ${{ env.CHECK_SCRIPT }}
- name: Check quality query appears in quality SARIF
if: contains(matrix.analysis-kinds, 'code-quality')
uses: actions/github-script@v7
uses: actions/github-script@v8
env:
SARIF_PATH: "${{ runner.temp }}/results/javascript.quality.sarif"
EXPECT_PRESENT: "true"
+1 -1
View File
@@ -9,6 +9,6 @@ to one of the files in this directory.
1. Install https://github.com/casey/just by whichever way you prefer.
2. Run `just update-pr-checks` in your terminal.
### If you don't want to intall `just`
### If you don't want to install `just`
Manually run each step in the `justfile`.
+2 -2
View File
@@ -128,7 +128,7 @@ for file in sorted((this_dir / 'checks').glob('*.yml')):
steps.extend([
{
'name': 'Install Node.js',
'uses': 'actions/setup-node@v4',
'uses': 'actions/setup-node@v5',
'with': {
'node-version': '20.x',
'cache': 'npm',
@@ -166,7 +166,7 @@ for file in sorted((this_dir / 'checks').glob('*.yml')):
steps.append({
'name': 'Install Go',
'uses': 'actions/setup-go@v5',
'uses': 'actions/setup-go@v6',
'with': {
'go-version': '${{ inputs.go-version || \'' + baseGoVersionExpr + '\' }}',
# to avoid potentially misleading autobuilder results where we expect it to download
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env python3
"""
Sync-back script to automatically update action versions in source templates
from the generated workflow files after Dependabot updates.
This script scans the generated workflow files (.github/workflows/__*.yml) to find
all external action versions used, then updates:
1. Hardcoded action versions in pr-checks/sync.py
2. Action version references in template files in pr-checks/checks/
The script automatically detects all actions used in generated workflows and
preserves version comments (e.g., # v1.2.3) when syncing versions.
This ensures that when Dependabot updates action versions in generated workflows,
those changes are properly synced back to the source templates. Regular workflow
files are updated directly by Dependabot and don't need sync-back.
"""
import os
import re
import glob
import argparse
import sys
from pathlib import Path
from typing import Dict, List
def scan_generated_workflows(workflow_dir: str) -> Dict[str, str]:
"""
Scan generated workflow files to extract the latest action versions.
Args:
workflow_dir: Path to .github/workflows directory
Returns:
Dictionary mapping action names to their latest versions (including comments)
"""
action_versions = {}
generated_files = glob.glob(os.path.join(workflow_dir, "__*.yml"))
for file_path in generated_files:
with open(file_path, 'r') as f:
content = f.read()
# Find all action uses in the file, including potential comments
# This pattern captures: action_name@version_with_possible_comment
pattern = r'uses:\s+([^/\s]+/[^@\s]+)@([^@\n]+)'
matches = re.findall(pattern, content)
for action_name, version_with_comment in matches:
# Only track non-local actions (those with / but not starting with ./)
if not action_name.startswith('./'):
# Assume that version numbers are consistent (this should be the case on a Dependabot update PR)
action_versions[action_name] = version_with_comment.rstrip()
return action_versions
def update_sync_py(sync_py_path: str, action_versions: Dict[str, str]) -> bool:
"""
Update hardcoded action versions in pr-checks/sync.py
Args:
sync_py_path: Path to sync.py file
action_versions: Dictionary of action names to versions (may include comments)
Returns:
True if file was modified, False otherwise
"""
if not os.path.exists(sync_py_path):
raise FileNotFoundError(f"Could not find {sync_py_path}")
with open(sync_py_path, 'r') as f:
content = f.read()
original_content = content
# Update hardcoded action versions
for action_name, version_with_comment in action_versions.items():
# Extract just the version part (before any comment) for sync.py
version = version_with_comment.split('#')[0].strip() if '#' in version_with_comment else version_with_comment.strip()
# Look for patterns like 'uses': 'actions/setup-node@v4'
# Note that this will break if we store an Action uses reference in a
# variable - that's a risk we're happy to take since in that case the
# PR checks will just fail.
pattern = rf"('uses':\s*'){re.escape(action_name)}@(?:[^']+)(')"
replacement = rf"\1{action_name}@{version}\2"
content = re.sub(pattern, replacement, content)
if content != original_content:
with open(sync_py_path, 'w') as f:
f.write(content)
print(f"Updated {sync_py_path}")
return True
else:
print(f"No changes needed in {sync_py_path}")
return False
def update_template_files(checks_dir: str, action_versions: Dict[str, str]) -> List[str]:
"""
Update action versions in template files in pr-checks/checks/
Args:
checks_dir: Path to pr-checks/checks directory
action_versions: Dictionary of action names to versions (may include comments)
Returns:
List of files that were modified
"""
modified_files = []
template_files = glob.glob(os.path.join(checks_dir, "*.yml"))
for file_path in template_files:
with open(file_path, 'r') as f:
content = f.read()
original_content = content
# Update action versions
for action_name, version_with_comment in action_versions.items():
# Look for patterns like 'uses: actions/setup-node@v4' or 'uses: actions/setup-node@sha # comment'
pattern = rf"(uses:\s+{re.escape(action_name)})@(?:[^@\n]+)"
replacement = rf"\1@{version_with_comment}"
content = re.sub(pattern, replacement, content)
if content != original_content:
with open(file_path, 'w') as f:
f.write(content)
modified_files.append(file_path)
print(f"Updated {file_path}")
return modified_files
def main():
parser = argparse.ArgumentParser(description="Sync action versions from generated workflows back to templates")
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output")
args = parser.parse_args()
# Get the repository root (assuming script is in pr-checks/)
script_dir = Path(__file__).parent
repo_root = script_dir.parent
workflow_dir = repo_root / ".github" / "workflows"
checks_dir = script_dir / "checks"
sync_py_path = script_dir / "sync.py"
print("Scanning generated workflows for latest action versions...")
action_versions = scan_generated_workflows(str(workflow_dir))
if args.verbose:
print("Found action versions:")
for action, version in action_versions.items():
print(f" {action}@{version}")
if not action_versions:
print("No action versions found in generated workflows")
return 1
# Update files
print("\nUpdating source files...")
modified_files = []
# Update sync.py
if update_sync_py(str(sync_py_path), action_versions):
modified_files.append(str(sync_py_path))
# Update template files
template_modified = update_template_files(str(checks_dir), action_versions)
modified_files.extend(template_modified)
if modified_files:
print(f"\nSync completed. Modified {len(modified_files)} files:")
for file_path in modified_files:
print(f" {file_path}")
else:
print("\nNo files needed updating - all action versions are already in sync")
return 0
if __name__ == "__main__":
sys.exit(main())
+237
View File
@@ -0,0 +1,237 @@
#!/usr/bin/env python3
"""
Tests for the sync_back.py script
"""
import os
import shutil
import tempfile
import unittest
import sync_back
class TestSyncBack(unittest.TestCase):
def setUp(self):
"""Set up temporary directories and files for testing"""
self.test_dir = tempfile.mkdtemp()
self.workflow_dir = os.path.join(self.test_dir, ".github", "workflows")
self.checks_dir = os.path.join(self.test_dir, "pr-checks", "checks")
os.makedirs(self.workflow_dir)
os.makedirs(self.checks_dir)
# Create sync.py file
self.sync_py_path = os.path.join(self.test_dir, "pr-checks", "sync.py")
def tearDown(self):
"""Clean up temporary directories"""
shutil.rmtree(self.test_dir)
def test_scan_generated_workflows_basic(self):
"""Test basic workflow scanning functionality"""
# Create a test generated workflow file
workflow_content = """
name: Test Workflow
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v5
- uses: actions/setup-go@v6
"""
with open(os.path.join(self.workflow_dir, "__test.yml"), 'w') as f:
f.write(workflow_content)
result = sync_back.scan_generated_workflows(self.workflow_dir)
self.assertEqual(result['actions/checkout'], 'v4')
self.assertEqual(result['actions/setup-node'], 'v5')
self.assertEqual(result['actions/setup-go'], 'v6')
def test_scan_generated_workflows_with_comments(self):
"""Test scanning workflows with version comments"""
workflow_content = """
name: Test Workflow
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
- uses: actions/setup-python@v6 # Latest Python
"""
with open(os.path.join(self.workflow_dir, "__test.yml"), 'w') as f:
f.write(workflow_content)
result = sync_back.scan_generated_workflows(self.workflow_dir)
self.assertEqual(result['actions/checkout'], 'v4')
self.assertEqual(result['ruby/setup-ruby'], '44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0')
self.assertEqual(result['actions/setup-python'], 'v6 # Latest Python')
def test_scan_generated_workflows_ignores_local_actions(self):
"""Test that local actions (starting with ./) are ignored"""
workflow_content = """
name: Test Workflow
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/local-action
- uses: ./another-local-action@v1
"""
with open(os.path.join(self.workflow_dir, "__test.yml"), 'w') as f:
f.write(workflow_content)
result = sync_back.scan_generated_workflows(self.workflow_dir)
self.assertEqual(result['actions/checkout'], 'v4')
self.assertNotIn('./.github/actions/local-action', result)
self.assertNotIn('./another-local-action', result)
def test_update_sync_py(self):
"""Test updating sync.py file"""
sync_py_content = """
steps = [
{
'uses': 'actions/setup-node@v4',
'with': {'node-version': '16'}
},
{
'uses': 'actions/setup-go@v5',
'with': {'go-version': '1.19'}
}
]
"""
with open(self.sync_py_path, 'w') as f:
f.write(sync_py_content)
action_versions = {
'actions/setup-node': 'v5',
'actions/setup-go': 'v6'
}
result = sync_back.update_sync_py(self.sync_py_path, action_versions)
self.assertTrue(result)
with open(self.sync_py_path, 'r') as f:
updated_content = f.read()
self.assertIn("'uses': 'actions/setup-node@v5'", updated_content)
self.assertIn("'uses': 'actions/setup-go@v6'", updated_content)
def test_update_sync_py_with_comments(self):
"""Test updating sync.py file when versions have comments"""
sync_py_content = """
steps = [
{
'uses': 'actions/setup-node@v4',
'with': {'node-version': '16'}
}
]
"""
with open(self.sync_py_path, 'w') as f:
f.write(sync_py_content)
action_versions = {
'actions/setup-node': 'v5 # Latest version'
}
result = sync_back.update_sync_py(self.sync_py_path, action_versions)
self.assertTrue(result)
with open(self.sync_py_path, 'r') as f:
updated_content = f.read()
# sync.py should get the version without comment
self.assertIn("'uses': 'actions/setup-node@v5'", updated_content)
self.assertNotIn("# Latest version", updated_content)
def test_update_template_files(self):
"""Test updating template files"""
template_content = """
name: Test Template
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: 16
"""
template_path = os.path.join(self.checks_dir, "test.yml")
with open(template_path, 'w') as f:
f.write(template_content)
action_versions = {
'actions/checkout': 'v4',
'actions/setup-node': 'v5 # Latest'
}
result = sync_back.update_template_files(self.checks_dir, action_versions)
self.assertEqual(len(result), 1)
self.assertIn(template_path, result)
with open(template_path, 'r') as f:
updated_content = f.read()
self.assertIn("uses: actions/checkout@v4", updated_content)
self.assertIn("uses: actions/setup-node@v5 # Latest", updated_content)
def test_update_template_files_preserves_comments(self):
"""Test that updating template files preserves version comments"""
template_content = """
name: Test Template
steps:
- uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.256.0
"""
template_path = os.path.join(self.checks_dir, "test.yml")
with open(template_path, 'w') as f:
f.write(template_content)
action_versions = {
'ruby/setup-ruby': '55511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0'
}
result = sync_back.update_template_files(self.checks_dir, action_versions)
self.assertEqual(len(result), 1)
with open(template_path, 'r') as f:
updated_content = f.read()
self.assertIn("uses: ruby/setup-ruby@55511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0", updated_content)
def test_no_changes_needed(self):
"""Test that functions return False/empty when no changes are needed"""
# Test sync.py with no changes needed
sync_py_content = """
steps = [
{
'uses': 'actions/setup-node@v5',
'with': {'node-version': '16'}
}
]
"""
with open(self.sync_py_path, 'w') as f:
f.write(sync_py_content)
action_versions = {
'actions/setup-node': 'v5'
}
result = sync_back.update_sync_py(self.sync_py_path, action_versions)
self.assertFalse(result)
if __name__ == '__main__':
unittest.main()