ci: isolate private execution and refresh Actions dependencies [skip ci]

This commit is contained in:
spiritlhl 2026-10-13 11:06:32 +08:00
parent 609490c5fe
commit 90693fbf25
9 changed files with 146 additions and 17 deletions

View File

@ -1,7 +1,19 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
- package-ecosystem: github-actions
directory: /
schedule:
interval: "weekly"
interval: weekly
open-pull-requests-limit: 5
groups:
actions-patch-minor:
patterns:
- '*'
update-types:
- minor
- patch
actions-major:
patterns:
- '*'
update-types:
- major

66
.github/scripts/merge_action_updates.py vendored Normal file
View File

@ -0,0 +1,66 @@
"""Merge Dependabot Action patch/minor updates after all head checks pass."""
import json
import os
import re
import time
import urllib.request
repository = os.environ['GITHUB_REPOSITORY']
event = json.load(open(os.environ['GITHUB_EVENT_PATH']))
def call(path, method='GET', body=None):
req = urllib.request.Request('https://api.github.com/repos/' + repository + path, method=method,
data=None if body is None else json.dumps(body).encode(),
headers={'Authorization': 'Bearer ' + os.environ['GH_TOKEN'], 'Accept': 'application/vnd.github+json', 'Content-Type': 'application/json'})
with urllib.request.urlopen(req, timeout=40) as response:
value = response.read()
return json.loads(value) if value else None
def versioned_changes(files):
count = 0
for file in files:
path = file['filename']
if not path.startswith('.github/') or not path.endswith(('.yml', '.yaml')) or 'patch' not in file:
return False
old, new = {}, {}
for line in file['patch'].splitlines():
if not line.startswith(('-', '+')) or line.startswith(('---', '+++')):
continue
match = re.match(r'[+-]\s*(?:-\s*)?uses:\s*([^\s@]+)@[0-9a-f]{40}\s+#\s*v?(\d+)(?:\.(\d+))?(?:\.(\d+))?\s*$', line)
if not match:
# Updating any workflow behavior or an unversioned action
# remains a reviewed change.
return False
(old if line[0] == '-' else new)[match[1]] = tuple(int(x or 0) for x in match.groups()[1:])
if set(old) != set(new):
return False
for action in old:
if old[action][0] != new[action][0] or new[action] < old[action]:
return False
count += 1
return count > 0
run = event['workflow_run']
if run['conclusion'] == 'success' and run['event'] == 'pull_request':
for reference in run.get('pull_requests', []):
number = reference['number']
pr = call('/pulls/' + str(number))
if pr['state'] != 'open' or pr['user']['login'] != 'dependabot[bot]' or pr['head']['repo']['full_name'] != repository:
continue
if pr['head']['sha'] != run['head_sha'] or pr.get('draft'):
continue
files = call('/pulls/' + str(number) + '/files?per_page=100')
if pr['changed_files'] > 100 or not versioned_changes(files):
continue
sha = pr['head']['sha']
for attempt in range(90):
checks = call('/commits/' + sha + '/check-runs?per_page=100')['check_runs']
statuses = call('/commits/' + sha + '/status')['statuses']
if any(x['status'] == 'completed' and x['conclusion'] not in ('success', 'neutral', 'skipped') for x in checks) or any(x['state'] in ('failure', 'error') for x in statuses):
break
if checks and all(x['status'] == 'completed' for x in checks) and all(x['state'] == 'success' for x in statuses):
latest = call('/pulls/' + str(number))
if latest['head']['sha'] == sha and latest['state'] == 'open':
call('/pulls/' + str(number) + '/merge', 'PUT', {'sha': sha, 'merge_method': 'squash'})
break
time.sleep(20)

28
.github/workflows/action-policy.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Action policy
'on':
pull_request:
paths:
- .github/**
workflow_dispatch: {}
permissions:
contents: read
jobs:
validate:
name: Validate Actions
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26'
cache: false
- name: Validate workflows
run: |
go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12
"$(go env GOPATH)/bin/actionlint" -shellcheck= -pyflakes= -ignore 'label .* is unknown'
- name: Verify private output isolation
run: |
if [[ -d .github/tests ]]; then python3 -m unittest discover -s .github/tests -p "test_*.py"; fi

View File

@ -17,12 +17,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: 设置 Go
uses: actions/setup-go@v7
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod

View File

@ -18,8 +18,8 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
check-latest: true

View File

@ -19,7 +19,7 @@ jobs:
outputs:
tag: ${{ steps.release.outputs.tag }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
fetch-depth: 0
@ -40,7 +40,7 @@ jobs:
version="$(sed -n 's/^const BackTraceVersion = "\(v[0-9.]*\)"$/\1/p' model/model.go)"
[[ "$version" == "$tag" ]]
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- uses: actions/setup-go@v7
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
check-latest: true
@ -100,10 +100,10 @@ jobs:
- {goos: windows, goarch: amd64}
- {goos: windows, goarch: arm64}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
- uses: actions/setup-go@v7
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
check-latest: true

View File

@ -0,0 +1,23 @@
name: Merge safe Action updates
'on':
workflow_run:
workflows:
- Action policy
types:
- completed
permissions:
contents: write
pull-requests: write
jobs:
merge:
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 35
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Merge validated patch and minor updates
env:
GH_TOKEN: ${{ github.token }}
run: python3 .github/scripts/merge_action_updates.py

View File

@ -19,12 +19,12 @@ jobs:
prepare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: main
fetch-depth: 0
fetch-tags: true
- uses: actions/setup-go@v7
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
check-latest: true

View File

@ -28,8 +28,8 @@ jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true