Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 33 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: CI/CD

permissions:
contents: write
on:
push:
branches: [main]
Expand All @@ -16,7 +17,8 @@ jobs:

steps:
- uses: actions/checkout@v4

with:
fetch-depth: 0
- name: Install uv
uses: astral-sh/setup-uv@v5

Expand Down Expand Up @@ -64,6 +66,35 @@ jobs:
# Upload coverage (if tests are being run)
# - name: Upload coverage
# uses: codecov/codecov-action@v4
license-check:
name: License Compliance Check
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Cache Go bin path
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH

- name: Install addlicense
run: go install github.com/google/addlicense@latest

- name: Run addlicense check (only on relevant files)
run: |
year=$(date +'%Y')
find . -type f \( -name '*.py' -o -name '*.sh' -o -name '*.go' \) \
-not -path './.git/*' \
-not -path './.venv/*' \
-not -path './vendor/*' \
| xargs $(go env GOPATH)/bin/addlicense -check -c "Steve Morin" -l mit -y "$year" -s -v

# Only run security checks on pull requests from the main repository
security:
Expand Down
17 changes: 15 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
Expand Down Expand Up @@ -47,4 +46,18 @@ repos:
language: system
types: [python]
pass_filenames: false # Run full test suite
stages: [pre-commit] # Only run on pre-commit
stages: [pre-commit] # Only run on commit
- repo: local
hooks:
- id: license-check
name: Check license headers
entry: python scripts/check_license.py
language: system
types: [python, shell]
- repo: local
hooks:
- id: check-vscode-extension-sync
name: Check VSCode Extension Sync
entry: uvx scripts/check_extension_sync.py
language: system
types: [json]
52 changes: 52 additions & 0 deletions scripts/check_extension_sync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3

import json
import sys
import os
from pathlib import Path

EXTENSIONS_FILE = Path(".vscode/extensions.json")
DEVCONTAINER_FILE = Path(".devcontainer/devcontainer.json")

def load_json(file_path):
try:
with open(file_path) as f:
return json.load(f)
except FileNotFoundError:
print(f"❌ Error: {file_path} not found.")
sys.exit(2)
except json.JSONDecodeError as e:
print(f"❌ Error parsing {file_path}: {e}")
sys.exit(2)

def extract_recommended_extensions(data):
return set(data.get("recommendations", []))

def extract_devcontainer_extensions(data):
try:
return set(data["customizations"]["vscode"]["extensions"])
except KeyError:
return set()

def main():
vscode_data = load_json(EXTENSIONS_FILE)
devcontainer_data = load_json(DEVCONTAINER_FILE)

vscode_exts = extract_recommended_extensions(vscode_data)
dev_exts = extract_devcontainer_extensions(devcontainer_data)

missing = vscode_exts - dev_exts

if missing:
print("❌ VSCode extensions not synced with devcontainer configuration!\n")
print("Missing from .devcontainer/devcontainer.json:")
for ext in sorted(missing):
print(f"- {ext}")
print("\nTo fix: Add these extensions to the `customizations.vscode.extensions` array in `.devcontainer/devcontainer.json`")
sys.exit(1)

print("✅ VSCode extensions are in sync.")
sys.exit(0)

if __name__ == "__main__":
main()
Loading