Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7a6a322
chore(codex): bootstrap PR for issue #2
github-actions[bot] Dec 17, 2025
6f97a7b
Add stubs to enable workflow tests
stranske Dec 17, 2025
69c0a86
fix: format Python files with Black and add missing test deps (reques…
stranske Dec 17, 2025
440d0ca
chore: trigger CI after enabling branch protection ruleset
stranske Dec 17, 2025
325ea9c
fix: sort imports with ruff
stranske Dec 17, 2025
c1a1329
fix: add pandas to test dependencies
stranske Dec 17, 2025
6996139
fix: add secrets inherit to Gate workflow for reusable-10
stranske Dec 17, 2025
009e38b
fix: add permissions to python-ci job for reusable workflow
stranske Dec 17, 2025
b5f740f
fix: add missing tools/post_ci_summary.py for Gate workflow
stranske Dec 18, 2025
66d76d6
fix: use github.token instead of SERVICE_BOT_PAT for PR comments
stranske Dec 18, 2025
416219f
fix: remove duplicate license classifier for PEP-639 compliance
stranske Dec 18, 2025
390bc67
fix: add module_file and announce params to setup_script_logging
stranske Dec 18, 2025
35d0243
feat(tools): add resolve_mypy_pin.py script
stranske Dec 20, 2025
dc468cd
test: verify pre-push hook works
stranske Dec 20, 2025
8a6ff2e
Revert "test: verify pre-push hook works"
stranske Dec 20, 2025
40d0065
fix(tests): add --disable-error-code=import-untyped to mypy invocations
stranske Dec 20, 2025
94c48fd
fix(mypy): disable import-untyped error code in pyproject.toml
stranske Dec 20, 2025
63dad77
fix(mypy): use correct config key disable_error_code (singular)
stranske Dec 20, 2025
a3f0385
fix(ci): add missing tools/coverage_trend.py script
stranske Dec 20, 2025
2d96e14
fix(scripts): handle ImportError for trend_analysis in CI environment
stranske Dec 20, 2025
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
141 changes: 141 additions & 0 deletions .github/workflows/maint-51-dependency-refresh.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: Maint 51 Dependency Refresh

on:
schedule:
- cron: '0 4 1,15 * *' # 1st and 15th of each month at 04:00 UTC
workflow_dispatch:
inputs:
dry-run:
description: 'Preview only (do not open a pull request)'
required: false
default: 'false'

permissions:
contents: write
pull-requests: write

jobs:
refresh:
name: Refresh dependency pins
runs-on: ubuntu-latest
env:
DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry-run || 'false' }}
BASE_BRANCH: ${{ github.event.repository.default_branch }}
steps:
- name: Checkout default branch
uses: actions/checkout@v4
with:
ref: ${{ env.BASE_BRANCH }}
fetch-depth: 0

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install uv
run: |
set -euo pipefail
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- name: Refresh requirements.lock
run: |
set -euo pipefail
uv pip compile --upgrade pyproject.toml --extra app --extra dev --extra notebooks -o requirements.lock

- name: Verify lockfile aligns with current compile
env:
TREND_FORCE_DEP_LOCK_CHECK: "1"
run: |
set -euo pipefail
python - <<'PY'
import re
import subprocess
from pathlib import Path

def normalize(content: str) -> str:
lines: list[str] = []
for line in content.splitlines():
stripped = line.strip()
if not stripped:
continue
if stripped.startswith('#'):
if re.match(r'^#.*autogenerated.*by.*', stripped, re.IGNORECASE):
continue
if re.match(r'^#\s*uv pip compile.*', stripped):
lines.append('# uv pip compile pyproject.toml --extra app --extra dev --extra notebooks -o requirements.lock')
continue
if re.search(r'\d{4}-\d{2}-\d{2}', stripped) or re.search(r'\d{2}:\d{2}', stripped):
continue
if (
stripped == '# via'
or stripped.startswith('# ')
or re.match(r'^#\s+via\s+\w', stripped)
):
continue
lines.append(stripped)
else:
lines.append(stripped)
return '\n'.join(lines) + ('\n' if lines else '')

compiled_proc = subprocess.run(
['uv', 'pip', 'compile', 'pyproject.toml', '--extra', 'app', '--extra', 'dev', '--extra', 'notebooks'],
check=True,
capture_output=True,
text=True,
)
compiled = normalize(compiled_proc.stdout)
lock_path = Path('requirements.lock')
existing = normalize(lock_path.read_text())
if compiled != existing:
raise SystemExit('requirements.lock is out of date; run the scheduled refresh workflow to update it.')
PY

- name: Verify tool pins remain aligned
run: python -m scripts.sync_tool_versions --check

- name: Detect changes
id: diff
run: |
set -euo pipefail
if git diff --stat --exit-code >/dev/null; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No dependency updates detected."
else
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "Dependency updates detected:" >> "$GITHUB_STEP_SUMMARY"
git status --short | sed 's/^/ /'
fi

- name: Run dependency verification
if: steps.diff.outputs.changed == 'true'
run: |
set -euo pipefail
python scripts/sync_test_dependencies.py --verify

- name: Create dependency refresh PR
if: steps.diff.outputs.changed == 'true' && env.DRY_RUN != 'true'
uses: peter-evans/create-pull-request@v6
with:
branch: maintenance/dependency-refresh/${{ github.run_id }}
base: ${{ env.BASE_BRANCH }}
commit-message: "chore(deps): refresh dependency snapshot"
title: "chore(deps): refresh dependency snapshot"
body: |
## Dependency snapshot refresh

* Workflow run: ${{ github.run_id }}
* Trigger: ${{ github.event_name }}

Changes produced by `Maint 51 Dependency Refresh`.
labels: maintenance,dependencies

- name: Dry-run summary
if: steps.diff.outputs.changed == 'true' && env.DRY_RUN == 'true'
run: |
echo "Dry run requested. Pending changes were detected but no PR was opened." >> "$GITHUB_STEP_SUMMARY"

- name: No-op summary
if: steps.diff.outputs.changed != 'true'
run: echo "Dependency snapshot already up to date." >> "$GITHUB_STEP_SUMMARY"
6 changes: 5 additions & 1 deletion .github/workflows/pr-00-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ jobs:
needs: detect
if: ${{ needs.detect.outputs.doc_only != 'true' && needs.detect.outputs.run_core == 'true' && fromJSON(needs.detect.outputs.run_core || 'true') }}
uses: ./.github/workflows/reusable-10-ci-python.yml
secrets: inherit
permissions:
contents: read
actions: read
with:
primary-python-version: '3.11'
python-versions: '["3.11", "3.12"]'
Expand Down Expand Up @@ -625,7 +629,7 @@ jobs:
if: always()
uses: actions/github-script@v7
with:
github-token: ${{ secrets.SERVICE_BOT_PAT || github.token }}
github-token: ${{ github.token }}
script: |
const path = require('path');
const fs = require('fs');
Expand Down
19 changes: 2 additions & 17 deletions .github/workflows/selftest-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,11 @@ jobs:

- name: Install dependencies
run: |
pip install pytest pytest-cov pyyaml
pip install pytest pytest-cov pyyaml requests numpy pandas

- name: Run Python tests
run: |
python -m pytest tests/workflows/ \
--ignore=tests/workflows/test_autofix_full_pipeline.py \
--ignore=tests/workflows/test_autofix_pipeline.py \
--ignore=tests/workflows/test_autofix_pipeline_diverse.py \
--ignore=tests/workflows/test_autofix_pipeline_live_docs.py \
--ignore=tests/workflows/test_autofix_pipeline_tools.py \
--ignore=tests/workflows/test_autofix_pr_comment.py \
--ignore=tests/workflows/test_autofix_probe_module.py \
--ignore=tests/workflows/test_autofix_repo_regressions.py \
--ignore=tests/workflows/test_autofix_samples.py \
--ignore=tests/workflows/test_chatgpt_topics_parser.py \
--ignore=tests/workflows/test_ci_probe_faults.py \
--ignore=tests/workflows/test_disable_legacy_workflows.py \
--ignore=tests/workflows/test_workflow_multi_failure.py \
--ignore=tests/workflows/github_scripts/ \
-v
python -m pytest tests/workflows/ -v

lint:
name: Lint & Format Check
Expand Down
1 change: 1 addition & 0 deletions agents/codex-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- bootstrap for codex on issue #2 -->
21 changes: 3 additions & 18 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down Expand Up @@ -90,23 +89,7 @@ skip_glob = ["archive/*", ".extraction/*"]
[tool.ruff]
line-length = 100
target-version = "py311"
# Exclude tests that require project-specific modules not present in this repo
exclude = [
"tests/workflows/test_autofix_full_pipeline.py",
"tests/workflows/test_autofix_pipeline.py",
"tests/workflows/test_autofix_pipeline_diverse.py",
"tests/workflows/test_autofix_pipeline_live_docs.py",
"tests/workflows/test_autofix_pipeline_tools.py",
"tests/workflows/test_autofix_pr_comment.py",
"tests/workflows/test_autofix_probe_module.py",
"tests/workflows/test_autofix_repo_regressions.py",
"tests/workflows/test_autofix_samples.py",
"tests/workflows/test_chatgpt_topics_parser.py",
"tests/workflows/test_ci_probe_faults.py",
"tests/workflows/test_disable_legacy_workflows.py",
"tests/workflows/test_workflow_multi_failure.py",
"tests/workflows/github_scripts/",
]
exclude = []

[tool.ruff.lint]
select = [
Expand All @@ -126,6 +109,7 @@ python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disable_error_code = "import-untyped"
exclude = [
"^archive/",
"^\\.extraction/",
Expand All @@ -147,6 +131,7 @@ markers = [
"cosmetic: marks tests for cosmetic/formatting changes",
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"serial: marks tests that must run serially",
"xdist_group: marks tests that must share a single xdist worker",
]
filterwarnings = [
"error",
Expand Down
11 changes: 9 additions & 2 deletions scripts/auto_type_hygiene.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
re.compile(r"(^|/)notebooks/old(/|$)"),
]
DEFAULT_ALLOWLIST = ["yaml"]
TYPED_FALLBACK = {"yaml"}


def _load_allowlist() -> list[str]:
Expand Down Expand Up @@ -87,6 +88,9 @@ def _has_stub_package(module: str) -> bool:
def module_has_types(module: str) -> bool:
"""Return ``True`` if ``module`` has typing support available."""

if module.split(".")[0] in TYPED_FALLBACK:
return True

parts = module.split(".")
for base in SRC_DIRS:
package_path = base.joinpath(*parts)
Expand Down Expand Up @@ -208,7 +212,10 @@ def main() -> int:


if __name__ == "__main__": # pragma: no cover
from trend_analysis.script_logging import setup_script_logging
try:
from trend_analysis.script_logging import setup_script_logging

setup_script_logging(module_file=__file__)
setup_script_logging(module_file=__file__)
except ImportError:
pass
raise SystemExit(main())
Loading
Loading