Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions .github/workflows/security-updates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

name: "Security Updates"

on:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9am UTC
workflow_dispatch:

# Declare default permissions as read only.
permissions: read-all

jobs:
update:
name: Update vulnerable dependencies
runs-on: ubuntu-latest

permissions:
contents: write
pull-requests: write
security-events: read

steps:
- name: Harden Runner
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
with:
egress-policy: audit

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v4
Comment thread
lilyydu marked this conversation as resolved.
with:
dotnet-version: '8.x'

- name: Install nbgv
run: dotnet tool install -g nbgv

Comment thread
lilyydu marked this conversation as resolved.
Comment thread
lilyydu marked this conversation as resolved.
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
Comment on lines +42 to +44
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

astral-sh/setup-uv@v6 is referenced by tag. To match the supply-chain hardening already applied to other actions in this workflow, pin setup-uv to a commit SHA (and update it intentionally when needed).

Suggested change
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
run: |
python3 -m pip install uv
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

Copilot uses AI. Check for mistakes.

- name: Get vulnerable pip packages
id: alerts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
packages=$(gh api --paginate "repos/${{ github.repository }}/dependabot/alerts?state=open" \
--slurp \
--jq '[.[]
| .[]
| select(.dependency.package.ecosystem == "pip")
| .dependency.package.name] | unique | join(" ")')
echo "packages=$packages" >> $GITHUB_OUTPUT
echo "Vulnerable packages: $packages"

- name: Update packages in lockfile
if: steps.alerts.outputs.packages != ''
env:
PACKAGES: ${{ steps.alerts.outputs.packages }}
run: |
for pkg in $PACKAGES; do
echo "Upgrading $pkg..."
uv lock --upgrade-package "$pkg"
done

- name: Open Pull Request
if: steps.alerts.outputs.packages != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PACKAGES: ${{ steps.alerts.outputs.packages }}
run: |
branch="deps/security-updates"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "$branch" 2>/dev/null || git checkout "$branch"
git add uv.lock
git diff --staged --quiet && echo "No changes to uv.lock" && exit 0
git commit -m "fix(deps): update packages with security vulnerabilities"
git push origin "$branch" --force
pr_create_output=$(gh pr create \
--title "fix(deps): update packages with security vulnerabilities" \
--body "Updates the following packages flagged by Dependabot security alerts: \`$PACKAGES\`" \
--head "$branch" \
2>&1) || pr_create_status=$?

if [ -z "${pr_create_status:-}" ]; then
echo "$pr_create_output"
elif printf '%s\n' "$pr_create_output" | grep -Fq "A pull request already exists for"; then
echo "$pr_create_output"
echo "PR already open for this branch"
else
echo "$pr_create_output"
exit "$pr_create_status"
fi
Loading