Skip to content
Closed
Show file tree
Hide file tree
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
19 changes: 3 additions & 16 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,10 @@ updates:
schedule:
interval: "weekly"
groups:
production-dependencies:
patterns:
- "*"
exclude-patterns:
- "pytest*"
- "ruff"
runtime-dependencies:
dependency-type: "production"
dev-dependencies:
patterns:
- "pytest*"
- "ruff"
dependency-type: "development"
commit-message:
prefix: "chore(deps)"
open-pull-requests-limit: 10

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

This change removes Dependabot updates for the github-actions ecosystem. If actions versions are not managed elsewhere, this will stop automated security/version updates for workflow actions; consider re-adding the github-actions entry or documenting the replacement update mechanism.

Suggested change
open-pull-requests-limit: 10
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "chore(deps)"
open-pull-requests-limit: 10

Copilot uses AI. Check for mistakes.

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "chore(deps)"
42 changes: 27 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,45 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
push:
branches: [main]
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run linter
run: uv run ruff check .
- name: Lint with ruff
run: |
pip install ruff

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

The workflow installs ruff again even though it’s already installed via pip install -e "..[dev]" above. This can unintentionally upgrade/downgrade the tool version used in CI relative to the project’s dependency constraints. Prefer relying on the version from the dev extras (or pin the version explicitly in this step).

Suggested change
pip install ruff

Copilot uses AI. Check for mistakes.
ruff check .
ruff format --check .

- name: Test with pytest
run: |
pip install pytest pytest-asyncio pytest-cov

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Similarly, pytest/pytest-asyncio/pytest-cov are installed again even though they’re already part of the .[dev] extras installed earlier. This adds time and can cause CI to use different versions than local/dev. Prefer removing this extra install (or pinning explicitly if intended).

Suggested change
pip install pytest pytest-asyncio pytest-cov

Copilot uses AI. Check for mistakes.
pytest --cov=src --cov-report=xml

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Coverage is collected with --cov=src, but this project does not use a src/ layout/package, so coverage will be empty or misleading. Point --cov at the actual modules/packages in this repo (or use --cov=. / a specific package name).

Suggested change
pytest --cov=src --cov-report=xml
pytest --cov=. --cov-report=xml

Copilot uses AI. Check for mistakes.

- name: Run tests
run: uv run pytest tests/ -v
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: coverage.xml
continue-on-error: true
39 changes: 39 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Dependabot auto-merge

on:
pull_request_target:
types:
- opened
- reopened
- synchronize
- ready_for_review

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Fetch Dependabot metadata
id: meta
uses: dependabot/fetch-metadata@v2

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

This workflow uses third-party actions by mutable tags (e.g. dependabot/fetch-metadata@v2). Consider pinning action references to commit SHAs to reduce supply-chain risk, especially since this job runs with pull_request_target and write permissions.

Suggested change
uses: dependabot/fetch-metadata@v2
uses: dependabot/fetch-metadata@d7267f607e9d3fb96fc2fbe83e0af444713e90b7

Copilot uses AI. Check for mistakes.
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Approve and enable auto-merge
if: |
steps.meta.outputs.update-type != 'version-update:semver-major' ||
steps.meta.outputs.package-ecosystem == 'github_actions'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
CURRENT_LOGIN="$(gh api user --jq .login)"
ALREADY_APPROVED="$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews" --jq '[.[] | select(.user.login == "'"$CURRENT_LOGIN"'" and .state == "APPROVED")] | length')"
if [ "$ALREADY_APPROVED" -eq 0 ]; then
gh pr review --approve "$PR_URL"
fi
gh pr merge --auto --squash "$PR_URL"
6 changes: 3 additions & 3 deletions .github/workflows/pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ jobs:
exit 0
fi

echo "PR title must use Conventional Commits so squash-merge commits on main stay clean."
echo "PR title must use Conventional Commits so squash-merge commits on main have clean, consistent messages."
echo "Allowed prefixes: feat, fix, docs, chore, refactor, test, perf, build, ci, revert"
echo "Examples:"
echo " feat: add desktop profile writer"
echo " fix(profile): preserve native image paths"
echo " fix: harden push approval auth flow"
echo " feat(auth): add TOTP support"
exit 1
103 changes: 33 additions & 70 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,112 +1,75 @@
name: Release Please
# Release workflow for Python packages
#
# How it works:
# 1. Create a git tag (e.g., v1.0.0)
# 2. Push the tag to trigger this workflow
# 3. Workflow builds and publishes to PyPI using Trusted Publishing
#
# PyPI Trusted Publishing:
# No API tokens needed! Configure at:
# https://pypi.org/manage/project/{package-name}/settings/publishing/
# Add this repository as a trusted publisher.

name: Release

on:
push:
branches:
- main
workflow_dispatch:
tags:
- "v*"

permissions:
contents: write
issues: write
pull-requests: write
id-token: write

jobs:
release-please:
name: Release Please
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
sha: ${{ steps.release.outputs.sha }}
steps:
- uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4
id: release
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

build-release:
name: Build Release
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.release-please.outputs.sha }}
persist-credentials: false
- uses: actions/checkout@v4

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
- uses: actions/setup-python@v5
with:
python-version: "3.11"

Comment on lines +28 to 33

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Workflow actions are referenced by mutable tags (e.g. actions/checkout@v4, actions/setup-python@v5). For supply-chain hardening, pin these to full commit SHAs (as the prior workflow did) so a compromised tag can’t change the executed code.

Copilot uses AI. Check for mistakes.
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0

- name: Install dependencies
- name: Install build dependencies
run: |
uv venv
uv pip install -e ".[dev]"

- name: Run linter
run: uv run ruff check .

- name: Run tests
run: uv run pytest tests/ -v
python -m pip install --upgrade pip
pip install build

- name: Build package
run: uv build --out-dir dist
run: python -m build

- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

publish-pypi:
name: Publish to PyPI
needs: build-release
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@v4
with:
name: dist
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
with:
skip-existing: true
uses: pypa/gh-action-pypi-publish@release/v1

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

pypa/gh-action-pypi-publish@release/v1 is a floating ref. Pin to a commit SHA to prevent unexpected changes in the publishing step (supply-chain hardening).

Suggested change
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@<FULL_40_CHARACTER_COMMIT_SHA> # release/v1

Copilot uses AI. Check for mistakes.

upload-release-artifacts:
name: Upload Release Artifacts
needs:
- release-please
- build-release
if: ${{ needs.release-please.outputs.release_created == 'true' }}
create-release:
needs: publish-pypi
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist/
- uses: actions/checkout@v4

- name: Upload release artifacts
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v2
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
Comment on lines +72 to 74

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

softprops/action-gh-release@v1 is a mutable tag. Pin to a commit SHA to reduce supply-chain risk for the release creation step.

Copilot uses AI. Check for mistakes.
tag_name: ${{ needs.release-please.outputs.tag_name }}
files: |
dist/*
fail_on_unmatched_files: true
overwrite_files: true
generate_release_notes: true
14 changes: 8 additions & 6 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
name: CodeQL Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
Expand All @@ -35,9 +35,9 @@ jobs:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- uses: actions/setup-python@v6
- uses: actions/setup-python@v5
with:
python-version: "3.11"

Expand All @@ -49,19 +49,21 @@ jobs:

- name: Audit dependencies
run: pip-audit
continue-on-error: true

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

continue-on-error: true on dependency auditing means the Security workflow will pass even when vulnerabilities are found. If the intent is to enforce a security gate on PRs/main, remove continue-on-error (or gate it to non-default branches / scheduled runs only).

Suggested change
continue-on-error: true

Copilot uses AI. Check for mistakes.

bandit:
name: Bandit Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- uses: actions/setup-python@v6
- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install bandit
run: pip install bandit

- name: Run bandit
run: bandit -r . -x .venv,tests -ll
run: bandit -r src/ -ll

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

bandit is configured to scan src/, but this repository doesn’t have a src/ directory, so the scan will either error or effectively scan nothing (and with continue-on-error: true this can silently mask that). Update the scan target to match the actual code layout (e.g., repo root with appropriate excludes, or the real package/module directories).

Suggested change
run: bandit -r src/ -ll
run: bandit -r . -ll

Copilot uses AI. Check for mistakes.
continue-on-error: true
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ classifiers = [
"Programming Language :: Python :: 3.12",
]
dependencies = [
"mcp[cli]>=1.6.0",
"mcp>=1.0.0",
"streamdeck>=0.9.0",
"pillow>=10.0.0",
]
Expand Down
Loading