This document describes CI/CD best practices that significantly improve the quality and reliability of AI-driven development workflows. When properly configured, AI solvers are forced to iterate with CI/CD checks until all tests pass, ensuring code quality meets the highest standards.
AI-driven development creates a powerful feedback loop:
- AI creates a solution - The solver generates code based on issue requirements
- CI/CD validates the solution - Automated checks verify code quality
- AI iterates until passing - The solver fixes issues until all checks pass
- Quality is guaranteed - No code merges without passing all gates
This approach ensures consistent quality regardless of whether the team consists of humans, AIs, or both.
This template implements the following best practices from the hive-mind project:
Maximum of 1500 lines per code file (enforced via ESLint max-lines rule).
This constraint benefits both AI and human developers:
- AI models can read and understand entire files within context windows
- Humans can navigate and comprehend files without cognitive overload
- Forces modular, well-organized code architecture
Consistent formatting eliminates style debates and reduces diff noise:
| Tool | Purpose |
|---|---|
| ESLint | Code quality and style rules |
| Prettier | Code formatting |
| Husky | Pre-commit hooks |
Catch bugs and enforce patterns before code reaches review:
- ESLint with strict rules
- Strict unused variables rule (no
_prefix exceptions) - Async/await best practices enforcement
Tests run across multiple dimensions:
- Cross-runtime: Node.js, Bun, and Deno
- Cross-platform: Ubuntu, macOS, and Windows
- Test framework: test-anywhere for universal compatibility
The changeset system:
- Eliminates merge conflicts - Each PR creates an independent changeset file
- Automates version bumps - Highest bump type wins when merging
- Generates changelogs - Release notes are compiled automatically
- Supports semantic versioning - patch/minor/major bumps are explicit
Local quality gates prevent broken commits from reaching CI:
- Format check and auto-fix
- Lint and static analysis
- File size validation
Automated release workflows ensure:
- No manual version management - Versions update automatically
- OIDC trusted publishing - No API tokens needed in CI
- Validated releases only - All checks must pass before publishing
- Dual trigger modes - Both automatic (on merge) and manual (workflow dispatch)
The workflow implements several critical features from hive-mind issues #1274 and #1278:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref == 'refs/heads/main' }}This configuration (implemented in this template) ensures:
- Main branch: Newer runs cancel older runs, preventing blocking (Issue #1274 fix)
- PR branches: Runs are queued to preserve check history
See DETAILED-COMPARISON.md for the full analysis of best practices from both repositories.
Before running checks on PRs, the workflow:
- Fetches the latest base branch
- Attempts to merge it into the PR branch
- Runs checks against the merged state
This prevents "stale merge preview" issues where checks pass on outdated code.
The simulation logic is extracted to scripts/simulate-fresh-merge.sh for reuse across jobs.
Run fast checks before slow checks to give the fastest possible feedback:
Fast checks (~7-30s each): Slow checks (~1-10 min each):
├── test-compilation └── test matrix (3 runtimes x 3 OS)
├── lint (format + ESLint)
└── check-file-line-limits
Slow test matrix only runs after all fast checks pass. This dramatically reduces feedback time for AI solvers — a syntax error is caught in ~7 seconds instead of waiting for the full test matrix.
In addition to the ESLint max-lines rule (which only covers source files), a separate CI check enforces the 1500-line limit on:
- All
.mjsfiles (including scripts) .github/workflows/release.yml(to prevent workflow bloat)
This is enforced by scripts/check-file-line-limits.sh.
Automated scanning for accidental credential leaks using secretlint:
- Runs in the lint job to catch secrets before code reaches review
- Configured via
.secretlintrc.jsonwith recommended rules - Prevents API tokens, passwords, and private keys from being committed
Documentation files are validated in CI just like code:
- File size limits (2500 lines for docs)
- Required files check (README.md, CHANGELOG.md, CONTRIBUTING.md, BEST-PRACTICES.md)
- Only runs when documentation files change
Use !cancelled() instead of always() in job conditions (hive-mind issue #1278):
# Bad - always() prevents cancellation from propagating
if: always() && needs.lint.result == 'success'
# Good - !cancelled() allows cancellation to propagate
if: !cancelled() && needs.lint.result == 'success'When a workflow run is cancelled, always() still evaluates to true, causing dependent jobs to run unnecessarily. !cancelled() properly stops the chain.
The template implements a defense-in-depth approach:
Developer Machine -> CI/CD Pipeline -> Release
├── Pre-commit hooks ├── Fast checks (~7-30s) ├── All checks pass
├── Local tests │ ├── test-compilation ├── Version bump
└── IDE integration │ ├── lint + secrets scan ├── Changelog update
│ └── file line limits └── Publish package
├── Slow checks (~1-10 min)
│ └── test matrix (9 combos)
├── Documentation validation
└── Changeset verify
Each layer catches different issues, ensuring no problematic code reaches production.
- Code Architecture Principles
- hive-mind CI/CD Best Practices
- hive-mind CI/CD Case Studies
- Issue #1274 Analysis - Concurrency blocking
- Issue #1278 Analysis - always() cancellation prevention
- Issue #29 Analysis - CI/CD best practices alignment