ci: ubuntu-latest workflows + dependabot (#18)
* ci: migrate workflows + dependabot from opencode * ci: replace self-hosted with ubuntu-latest + update paths * ci: add bootstrap job + hashFiles conditions for bootstrapping * docs(handoff): add pr-6 handoff + ADR-002 * fix(ci): wrap hashFiles in expression syntax for job-level if * fix(ci): replace hashFiles with output-based skip conditions * docs(handoff): update pr-6 handoff + ADR-002 for output-based * docs(handoff): fix PR number in handoff filename * docs: add project map for PR #18 --------- Co-authored-by: opencode-agent <agent@slaid098.dev>
This commit is contained in:
parent
e1f427511e
commit
1dbec56140
7 changed files with 271 additions and 0 deletions
17
.github/dependabot.yml
vendored
Normal file
17
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/config"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 5
|
||||
33
.github/workflows/adr-check.yml
vendored
Normal file
33
.github/workflows/adr-check.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: ADR References Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.opencode/**'
|
||||
- '**/*.md'
|
||||
- '.github/workflows/adr-check.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: check
|
||||
run: |
|
||||
if [ -f .opencode/scripts/check-adr-refs.py ]; then
|
||||
echo "has_script=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_script=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- uses: actions/setup-python@v5
|
||||
if: steps.check.outputs.has_script == 'true'
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: python3 .opencode/scripts/check-adr-refs.py
|
||||
if: steps.check.outputs.has_script == 'true'
|
||||
93
.github/workflows/ci.yml
vendored
Normal file
93
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths-ignore: ['**/*.md', 'docs/**', 'LICENSE']
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore: ['**/*.md', 'docs/**', 'LICENSE']
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
has_src: ${{ steps.check.outputs.has_src }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: check
|
||||
run: |
|
||||
if [ -n "$(find src/ -name '*.py' -print -quit 2>/dev/null)" ]; then
|
||||
echo "has_src=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_src=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- run: echo "CI bootstrap OK"
|
||||
|
||||
lint:
|
||||
needs: bootstrap
|
||||
if: needs.bootstrap.outputs.has_src == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- uses: astral-sh/setup-uv@v3
|
||||
- run: uv sync --extra dev
|
||||
- run: uv run ruff check src/ tests/ .opencode/scripts/
|
||||
- run: uv run ruff format --check src/ tests/ .opencode/scripts/
|
||||
|
||||
typecheck:
|
||||
needs: bootstrap
|
||||
if: needs.bootstrap.outputs.has_src == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- uses: astral-sh/setup-uv@v3
|
||||
- run: uv sync --extra dev
|
||||
- run: uv run mypy src/
|
||||
|
||||
test:
|
||||
needs: bootstrap
|
||||
if: needs.bootstrap.outputs.has_src == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python: ["3.12", "3.13", "3.14"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
- uses: astral-sh/setup-uv@v3
|
||||
- run: uv sync --extra dev --python ${{ matrix.python }}
|
||||
- run: uv run --python ${{ matrix.python }} pytest
|
||||
|
||||
complexity:
|
||||
needs: bootstrap
|
||||
if: needs.bootstrap.outputs.has_src == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- uses: astral-sh/setup-uv@v3
|
||||
- run: uv sync --extra dev
|
||||
- run: uv run xenon --max-absolute B --max-modules A --max-average A src/
|
||||
33
.github/workflows/permissions-check.yml
vendored
Normal file
33
.github/workflows/permissions-check.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: Permission Security Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.opencode/opencode.json'
|
||||
- '.opencode/agents/**'
|
||||
- '.opencode/scripts/check-permissions.py'
|
||||
- '.github/workflows/permissions-check.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: check
|
||||
run: |
|
||||
if [ -f .opencode/scripts/check-permissions.py ]; then
|
||||
echo "has_script=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_script=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- uses: actions/setup-python@v5
|
||||
if: steps.check.outputs.has_script == 'true'
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: python3 .opencode/scripts/check-permissions.py
|
||||
if: steps.check.outputs.has_script == 'true'
|
||||
22
docs/decisions/001-pr-18-ci-bootstrap.md
Normal file
22
docs/decisions/001-pr-18-ci-bootstrap.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# ADR-001: CI bootstrap job + output-based skip conditions
|
||||
|
||||
## Статус
|
||||
|
||||
Accepted
|
||||
|
||||
## Контекст
|
||||
|
||||
Chicken-and-egg: pipeline-driver требует CI ✅ для merge, но CI не может работать без #7 (scripts) и #5 (src/tests). Нужен способ иметь CI runs на каждом PR даже когда src/ и scripts/ ещё не мигрированы.
|
||||
|
||||
## Решение
|
||||
|
||||
1. ci.yml: bootstrap job (checkout + file check + always passes) — гарантирует CI run → pipeline_status CI phase = DONE
|
||||
2. lint/test/typecheck/complexity jobs: `if: needs.bootstrap.outputs.has_src == 'true'` — skip без src/*.py
|
||||
3. permissions-check/adr-check: step-level file checks (checkout → check script exists → conditional run)
|
||||
|
||||
## Альтернативы
|
||||
|
||||
- `hashFiles()` в job-level `if` — отклонено: GitHub Actions не распознаёт `hashFiles` как функцию в job-level `if` (ошибка "Unrecognized function: 'hashFiles'"). Заменено на output-based conditions.
|
||||
- Объединить #5+#6+#7 в один PR — отклонено (пользователь хочет атомарные PR)
|
||||
- Merge без pipeline-driver (admin override) — отклонено (нарушает pipeline протокол)
|
||||
- ci.yml без modifications (перенести как есть) — отклонено (CI падает без src/tests, нет runs → AMBIGUOUS → pipeline STOP)
|
||||
36
docs/handoff/pr-18-ci-ubuntu-latest-workflows.md
Normal file
36
docs/handoff/pr-18-ci-ubuntu-latest-workflows.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# PR #18: CI workflows (ubuntu-latest) + dependabot
|
||||
|
||||
## Что сделано
|
||||
|
||||
- Перенесены .github/workflows/ (ci.yml, permissions-check.yml, adr-check.yml) + dependabot.yml
|
||||
- runs-on: [self-hosted, linux] → ubuntu-latest (security risk для public repo)
|
||||
- config/scripts/ → .opencode/scripts/ (пути в run steps + trigger paths)
|
||||
- ci.yml: branches [master] → [main] (новый репо использует main)
|
||||
- ci.yml: matrix 3.14 добавлен (ubuntu-latest поддерживает, self-hosted комментарий убран)
|
||||
- ci.yml: добавлен bootstrap job (checkout + file check + always passes) + output-based skip conditions на lint/test/typecheck/complexity (skip без src/*.py)
|
||||
- permissions-check.yml, adr-check.yml: step-level file checks (skip script execution без .opencode/scripts/)
|
||||
|
||||
## Почему
|
||||
|
||||
Bootstrapping: CI нужен до #7 (.opencode/ scripts) и #5 (src/tests). bootstrap job гарантирует CI run на каждом PR. Output-based conditions skip jobs которые не могут работать без src/ или scripts/.
|
||||
|
||||
## Отклонение от spec
|
||||
|
||||
- hashFiles() не распознан GitHub Actions в job-level `if` — заменён на output-based conditions (bootstrap job checks files, sets `has_src` output, jobs use `if: needs.bootstrap.outputs.has_src == 'true'`)
|
||||
- permissions-check/adr-check: job-level `if` заменён на step-level file checks (checkout → check → conditional run)
|
||||
- Дополнительно: branches [master] → [main], trigger paths config/ → .opencode/ (spec не упоминал)
|
||||
|
||||
## Pending
|
||||
|
||||
- После #7: permissions-check/adr-check jobs активируются (scripts доступны)
|
||||
- После #5 (merge PR#17): lint/test/typecheck/complexity jobs активируются (src/ доступен)
|
||||
- Matrix 3.14 — проверить совместимость с ubuntu-latest
|
||||
|
||||
## Watch out
|
||||
|
||||
- ci.yml НЕ перенесён "как есть" — добавлен bootstrap job + output-based conditions (адаптация для bootstrapping)
|
||||
- hashFiles() не работает в GitHub Actions job-level `if` — это известное ограничение, см. ADR-001
|
||||
- branches: [master] → [main] — старый репо использовал master, новый main
|
||||
- trigger paths в permissions-check.yml/adr-check.yml: config/ → .opencode/ (config/ не существует в новом репо)
|
||||
- permissions-check.yml, adr-check.yml — skip до #7 (нет .opencode/scripts/)
|
||||
- dependabot.yml — без изменений (directory: "/config" для npm безвреден — директория не существует, dependabot просто пропустит)
|
||||
37
docs/project-map/README.md
Normal file
37
docs/project-map/README.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Project Map
|
||||
|
||||
opencode-config — Docker-based AI coding assistant with persistent memory (opencode configuration).
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
opencode-config/
|
||||
├── .github/
|
||||
│ ├── workflows/
|
||||
│ │ ├── ci.yml # Lint, test, typecheck, complexity (bootstrap + output-based skip)
|
||||
│ │ ├── permissions-check.yml # .opencode/scripts/permissions.py validator (step-level skip)
|
||||
│ │ └── adr-check.yml # ADR cross-reference validator (step-level skip)
|
||||
│ └── dependabot.yml # pip + github-actions ecosystem updates
|
||||
├── docs/
|
||||
│ ├── handoff/ # PR handoffs (pr-<N>-<slug>.md)
|
||||
│ ├── decisions/ # ADRs (NNN-pr-<N>-<slug>.md)
|
||||
│ └── project-map/ # This file — structure snapshot
|
||||
├── app_data/
|
||||
│ ├── workspaces/ # Agent working directory (.gitkeep)
|
||||
│ └── ssh/ # SSH keys, not in git (.gitkeep)
|
||||
├── .editorconfig
|
||||
├── .gitignore
|
||||
├── .python-version
|
||||
├── LICENSE
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Pending (future PRs)
|
||||
|
||||
- `.opencode/` — global opencode config (agents, skills, tools, scripts) — after #7
|
||||
- `src/` — Python RAG CLI (second-brain) — after #5 (PR#17)
|
||||
- `tests/` — pytest test suite — after #5
|
||||
|
||||
## Update Protocol
|
||||
|
||||
Updated by docs-reviewer subagent on each PR. Reflects tracked files only (`git ls-files`).
|
||||
Loading…
Add table
Reference in a new issue