feat(ci): implement CI dry-run workflow and PR checklist for history rewrite process
This commit is contained in:
@@ -540,3 +540,178 @@ Implement real CrowdSec Hub preset sync + apply on backend (using cscli or direc
|
||||
- Existing curated presets remain but are marked as bundled; UI should continue to show them even if hub unreachable.
|
||||
- Stub endpoint `POST /admin/crowdsec/presets/pull/apply` is replaced by separate `pull` and `apply`; frontend must switch to new API paths before backend removal to avoid 404.
|
||||
- Backward compatibility: keep returning 501 from old endpoint until frontend merged; remove once new routes live and tested.
|
||||
|
||||
---
|
||||
|
||||
**Automated CI Dry-Run & PR Checklist Plan**
|
||||
-------------------------------------------
|
||||
Objective: Add a CI dry-run workflow and a PR checklist enforcement job and template to reduce release/merge regressions. The dry-run will validate build/test/lint/packaging steps without publishing or writing secrets. The PR checklist job ensures contributors used the PR template.
|
||||
|
||||
Files to add / edit
|
||||
- Add: `.github/workflows/dry-run.yml` — main dry-run workflow triggered on PR and schedule (weekly)
|
||||
- Add: `.github/workflows/pr-checklist.yml` — PR body validation workflow to ensure PR checklist compliance
|
||||
- Add: `.github/PULL_REQUEST_TEMPLATE/pr_template.md` — PR template with developer checklist
|
||||
- Add: `scripts/ci/dry_run_build.sh` — wrapper script used by dry-run to orchestrate checks
|
||||
- Add: `scripts/ci/dry_run_goreleaser.sh` — goreleaser snapshot dry-run runner
|
||||
- Add: `scripts/ci/check_pr_checklist.sh` — standalone PR-checklist script (for local/CI usage)
|
||||
- Edit: `.pre-commit-config.yaml` — recommend add `tsc --noEmit` and `golangci-lint` local hooks (if not present as mandatory checks)
|
||||
- Review: `.gitignore`, `.gitattributes` — ensure `scripts/ci` temp artifacts are ignored and LFS/gitattribute rules still appropriate
|
||||
|
||||
Suggested job names & responsibilities
|
||||
- `dry-run-backend` (backend build: `go build`, `go test` with coverage, `go vet`)
|
||||
- `dry-run-frontend` (frontend build & tests, `npm ci`, `npm run build`, `npm run test:ci`)
|
||||
- `dry-run-docker` (docker build only, `docker build`, no push; multi-platform on branches only)
|
||||
- `dry-run-goreleaser` (goreleaser release in dry-run mode; `--snapshot` or `--skip-publish`)
|
||||
- `dry-run-security` (Trivy fs scan of built binary and optional static scans; non-publish SARIF upload disabled for fork PRs)
|
||||
- `validate-pr-checklist` (validate PR body contains required checklist items)
|
||||
|
||||
Workflow triggers
|
||||
- `pull_request` (types: opened, edited, synchronize, reopened)
|
||||
- `workflow_dispatch` (manual run)
|
||||
- `schedule` (cron — e.g., `0 3 * * 0` weekly; optional daily lightweight run for repo health exists already via `repo-health.yml`)
|
||||
|
||||
Permissions and secrets considerations
|
||||
- Default minimal perms: `contents: read` for checkout; use `checks: write` to set check statuses if necessary.
|
||||
- Do not use `packages: write` or `GITHUB_TOKEN` write duties on PRs (unless gated to branch-origin PRs). Dry-run avoids publishing and won't require `packages: write`.
|
||||
- Conditionally run `goreleaser` or any publish checks only when PR originates from repo owner and/or is a branch on the main repo (forks cannot access secrets): `if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}`.
|
||||
- `CHARON_TOKEN` or custom PAT should not be used in PR runs from forks to avoid secret leakage.
|
||||
|
||||
YAML job snippet samples
|
||||
1) Example `dry-run-backend` job
|
||||
```yaml
|
||||
jobs:
|
||||
dry-run-backend:
|
||||
name: Backend Dry-Run
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v4
|
||||
with: { go-version: '1.25' }
|
||||
- name: Run repo health check
|
||||
run: bash scripts/repo_health_check.sh
|
||||
- name: Run backend tests
|
||||
run: bash scripts/go-test-coverage.sh
|
||||
```
|
||||
|
||||
2) Example `dry-run-frontend` job
|
||||
```yaml
|
||||
dry-run-frontend:
|
||||
name: Frontend Dry-Run
|
||||
runs-on: ubuntu-latest
|
||||
needs: dry-run-backend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with: { node-version: '24' }
|
||||
- name: Install + Test
|
||||
working-directory: frontend
|
||||
run: |
|
||||
npm ci
|
||||
bash ../scripts/frontend-test-coverage.sh 2>&1 | tee frontend/test-output.txt
|
||||
```
|
||||
|
||||
3) Example `dry-run-docker` job
|
||||
```yaml
|
||||
dry-run-docker:
|
||||
name: Build Docker Image (No Push)
|
||||
runs-on: ubuntu-latest
|
||||
needs: dry-run-frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build Docker
|
||||
run: docker build --platform linux/amd64 -t charon:pr-${{ github.sha }} .
|
||||
```
|
||||
|
||||
4) Example `dry-run-goreleaser` job protected from fork PR secrets exposure
|
||||
```yaml
|
||||
dry-run-goreleaser:
|
||||
name: GoReleaser Dry-Run
|
||||
runs-on: ubuntu-latest
|
||||
needs: dry-run-docker
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.repository == github.event.pull_request.head.repo.full_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v4
|
||||
with: { go-version: '1.25' }
|
||||
- name: Run GoReleaser (dry-run)
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with: { args: 'release --snapshot --rm-dist --skip-publish' }
|
||||
```
|
||||
|
||||
5) PR checklist validation job (using `github-script` or local script)
|
||||
```yaml
|
||||
jobs:
|
||||
validate-pr-checklist:
|
||||
name: Validate PR Checklist
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Validate checklist
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = await github.rest.pulls.get({owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number});
|
||||
const body = (pr.data && pr.data.body) || '';
|
||||
const required = [ 'Tests (backend/frontend) pass', 'Pre-commit checks pass', 'Lints and type checks pass', 'Changelog updated (if applicable)' ];
|
||||
for (const r of required) {
|
||||
if (!body.toLowerCase().includes(r.toLowerCase())) { core.setFailed('Missing checklist item: '+r); return; }
|
||||
}
|
||||
```
|
||||
|
||||
Expected behavior and gating strategy
|
||||
- The dry-run workflow runs on PRs and fails the PR if build/test/goreleaser dry-run steps fail.
|
||||
- For PRs from forks, goreleaser/publish and other actions requiring secrets must be gated and skipped.
|
||||
- Maintain only lightweight jobs for PRs (run code checks, not artifact uploads). For nightly schedules, run heavier checks.
|
||||
|
||||
Edge cases & mitigation
|
||||
- Fork PRs: secrets are not available. Skip secret-dependent steps and run only build/test/lint steps.
|
||||
- Large builds or timeouts: Break checks into small jobs with `needs` to fail early, set timeouts on longest-running jobs and precautions for cache usage.
|
||||
- Flaky tests: mark flaky steps non-blocking but create an issue/annotation when flaky tests flake.
|
||||
|
||||
CI Scheduler recommendation
|
||||
- Keep the existing `repo-health.yml` schedule (daily). Add `dry-run.yml` with weekly schedule (`0 3 * * 0`) to validate the entire build pipeline weekly.
|
||||
|
||||
PR Template (simply create `.github/PULL_REQUEST_TEMPLATE/pr_template.md`) — basic checklist
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
## Checklist
|
||||
- [ ] Tests (backend & frontend) validated locally and CI
|
||||
- [ ] All tests pass in CI (Quality Checks)
|
||||
- [ ] Lint and type checks pass (pre-commit hooks run locally)
|
||||
- [ ] Changelog updated (if relevant)
|
||||
- [ ] Docs updated (if user-facing change)
|
||||
- [ ] No sensitive info or secrets in this PR
|
||||
```
|
||||
|
||||
`.gitattributes`, `.gitignore`, and pre-commit checks review
|
||||
- `.gitattributes`: ensure `*.db`, `*.sqlite`, `codeql-db/**` are LFS/binary as appropriate (file exists): verify no changes required; add new file patterns for scripts/ci artifacts if necessary.
|
||||
- `.gitignore`: add `/.tmp-ci` or other ephemeral artifact patterns for CI scripts to avoid noise.
|
||||
- `.pre-commit-config.yaml`: add a local `tsc` or `npx tsc --noEmit` hook if not present; keep `check-lfs-large-files` and `block-codeql-db-commits` enforced. Consider adding a new local `ci-dry-run` hook for pre-push gating (manual stage) but mainly rely on the CI workflows.
|
||||
|
||||
Testing plan & acceptance criteria
|
||||
- Run `dry-run.yml` via `workflow_dispatch` for a test branch (internal) and validate the dry-run jobs pass.
|
||||
- Open a sample PR with an incomplete checklist and confirm `pr-checklist` fails with actionable message.
|
||||
- Verify `goreleaser` dry-run step will not run for forked PRs and is only executed for branches in the same repository.
|
||||
- Acceptance: job completes successfully under normal code status; PR blocking on failures for `main` + `feature/beta-release`.
|
||||
|
||||
Next steps for maintainers
|
||||
1) Create the initial `dry-run.yml` & `pr-checklist.yml` workflows and a test PR to check behavior.
|
||||
2) Add `scripts/ci/dry_run_*` scripts and link them from the new workflows.
|
||||
3) Add the PR template file in `.github/PULL_REQUEST_TEMPLATE` and update `CONTRIBUTING.md` to require PR checklist checks.
|
||||
4) Test behavior for fork PRs and set branch protection rules to require these checks on relevant branches.
|
||||
5) Iterate in a small number of PRs to tune the threshold and gating behavior.
|
||||
|
||||
Status: Implemented
|
||||
|
||||
Files added and wired into CI:
|
||||
- `.github/workflows/dry-run-history-rewrite.yml` — runs a non-destructive history/large-file check on PRs and schedule.
|
||||
- `.github/PULL_REQUEST_TEMPLATE/history-rewrite.md` — PR checklist for history rewrite PRs.
|
||||
- `scripts/ci/dry_run_history_rewrite.sh` — CI wrapper that fails when banned paths or large historical objects are found.-.github/workflows/pr-checklist.yml — validates the PR body contains required checklist items for history-rewrite PRs.
|
||||
Validation steps performed locally and via CI (dry-run):
|
||||
- `scripts/ci/dry_run_history_rewrite.sh` returns non-zero when repo history contains objects or commits touching `backend/codeql-db` or other listed paths.
|
||||
- The workflow uses `actions/checkout@v4` with `fetch-depth: 0` to ensure history is available for the check.
|
||||
- PR template ensures contributors attach dry-run output and backup logs prior to destructive cleanups.
|
||||
|
||||
Next considerations:
|
||||
- Add a `validate-pr-checklist` workflow to enforce general PR checklist items for all PRs if desired (future improvement).
|
||||
|
||||
@@ -76,3 +76,8 @@ Post rewrite maintenance
|
||||
Communication & Approval
|
||||
------------------------
|
||||
Open a PR with dry-run logs and `preview_removals` output, tag maintainers for approval before `--force` is used.
|
||||
|
||||
CI automation
|
||||
-------------
|
||||
- A CI dry-run workflow `.github/workflows/dry-run-history-rewrite.yml` runs a non-destructive check that fails CI when banned history entries or large objects are found. It is triggered on PRs and a daily schedule.
|
||||
- A PR checklist template `.github/PULL_REQUEST_TEMPLATE/history-rewrite.md` and a checklist validator `.github/workflows/pr-checklist.yml` ensure contributors attach the preview output and backups before seeking approval.
|
||||
|
||||
Reference in New Issue
Block a user