code-foundry 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.editorconfig +18 -0
  2. package/.env.example +3 -0
  3. package/.gitattributes +9 -0
  4. package/.githooks/pre-commit +52 -0
  5. package/.github/CODEOWNERS +2 -0
  6. package/.github/CODE_OF_CONDUCT.md +41 -0
  7. package/.github/CONTRIBUTING.md +194 -0
  8. package/.github/ISSUE_TEMPLATE/bug_report.yml +56 -0
  9. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  10. package/.github/ISSUE_TEMPLATE/feature_request.yml +38 -0
  11. package/.github/PULL_REQUEST_TEMPLATE.md +29 -0
  12. package/.github/SECURITY.md +23 -0
  13. package/.github/actions/setup/action.yml +20 -0
  14. package/.github/dependabot.yml +42 -0
  15. package/.github/scripts/bootstrap.sh +13 -0
  16. package/.github/scripts/ci.sh +245 -0
  17. package/.github/scripts/codeql-languages.sh +22 -0
  18. package/.github/scripts/doctor.sh +103 -0
  19. package/.github/scripts/init-repo.sh +109 -0
  20. package/.github/scripts/security.sh +51 -0
  21. package/.github/scripts/sitecustomize.py +17 -0
  22. package/.github/scripts/sync-protection.sh +124 -0
  23. package/.github/scripts/sync-template.sh +242 -0
  24. package/.github/template.yml.example +5 -0
  25. package/.github/workflows/ci.yml +72 -0
  26. package/.github/workflows/codeql.yml +56 -0
  27. package/.github/workflows/draft-pr.yml +62 -0
  28. package/.github/workflows/publish.yml +25 -0
  29. package/.github/workflows/release-pr.yml +61 -0
  30. package/.github/workflows/release.yml +23 -0
  31. package/.github/workflows/security.yml +38 -0
  32. package/.github/workflows/test.yml +84 -0
  33. package/.gitignore +73 -0
  34. package/.mise.toml +8 -0
  35. package/.prettierrc +6 -0
  36. package/AGENTS.md +154 -0
  37. package/LICENSE +616 -0
  38. package/NOTICE +7 -0
  39. package/README.md +94 -0
  40. package/package.json +42 -0
  41. package/ruff.toml +6 -0
  42. package/src/cli.mjs +134 -0
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Repo Foundry
2
+
3
+ `repo-foundry` is a repository factory for TypeScript, Rust, Python, Solidity,
4
+ and mixed-language projects. It installs agent-ready instructions, fast native
5
+ testing, security automation, release workflows, hooks, and repository policy
6
+ from one versioned package.
7
+
8
+ ## Quick start
9
+
10
+ ```bash
11
+ npx repo-foundry init
12
+ ```
13
+
14
+ Or select the project profile explicitly:
15
+
16
+ ```bash
17
+ npx repo-foundry init \
18
+ --languages typescript,python \
19
+ --features all \
20
+ --package-manager bun
21
+ ```
22
+
23
+ Use `repo-foundry sync` to update an existing repository and
24
+ `repo-foundry doctor` to validate it. Add `--dry-run` to preview changes.
25
+
26
+ ## Setup
27
+
28
+ 1. Install [mise](https://mise.jdx.dev/).
29
+ 2. Run `bash .github/scripts/bootstrap.sh` to install the pinned toolchain, enable hooks, and validate the repository.
30
+ 3. Add the repository's standard scripts (`format:check`, `lint`, `type-check`, `build`, `test:unit`, `test:integration`, `test:e2e`, and `test:smoke`) when available. The shared scripts also recognize legacy aliases and skip checks that do not apply to the repository's languages or package manager.
31
+
32
+ ## Applying the baseline to an existing repository
33
+
34
+ Run the sync script from the repository root. It updates shared workflows, GitHub forms, hooks, policy files, and tool configuration while preserving the repository's README, `.mise.toml` selections, extra workflows, and application code.
35
+
36
+ ```bash
37
+ bash .github/scripts/init-repo.sh
38
+ ```
39
+
40
+ Use `bash .github/scripts/sync-template.sh --source ... --check` to preview differences. For local template development, pass the template checkout as `--source` and `--ref staging`.
41
+
42
+ The initializer is intentionally flag-driven so the same baseline can be used as a small repository package. Language selection controls CodeQL and records the repository profile; feature selection controls which standard workflows are installed. `auto` detects supported languages, while `all` enables every standard workflow.
43
+
44
+ ```bash
45
+ # Preview a TypeScript + Python repository without changing files
46
+ bash .github/scripts/init-repo.sh \
47
+ --languages typescript,python \
48
+ --features all \
49
+ --dry-run
50
+
51
+ # Initialize a Rust repository with only the core automation
52
+ bash .github/scripts/init-repo.sh \
53
+ --languages rust \
54
+ --features ci,codeql,security,test
55
+ ```
56
+
57
+ Supported languages are `typescript`, `rust`, `python`, and `solidity`. Supported feature flags are `ci`, `codeql`, `security`, `test`, `draft-pr`, `release-pr`, `release`, and `dependabot`. Use `--prune` only when you explicitly want disabled standard workflows removed; custom workflows are always preserved. The selected profile is stored in `.github/template.yml`, which makes later syncs repeatable and lets workflows consume repository-specific settings without duplicating the template scripts.
58
+
59
+ For a repository that does not yet contain the scripts, the initializer can be invoked directly from the published template checkout or a downloaded copy of `init-repo.sh`; it fetches the matching sync helper automatically. The generated `.github/template.yml` is the stable configuration contract for a future npm/package wrapper around these same operations.
60
+
61
+ Branch protection is an administrator operation and is opt-in:
62
+
63
+ ```bash
64
+ bash .github/scripts/init-repo.sh --protection
65
+ ```
66
+
67
+ The protection helper preserves unrelated provider checks, replaces stale template check names, and skips CodeQL analysis checks for private repositories where the workflow is intentionally skipped.
68
+
69
+ The repository name, owner, branch names, and release metadata are resolved by GitHub Actions at runtime through `${{ github.* }}` values. Keep organization-specific details out of this baseline.
70
+
71
+ CI and hooks use Prettier and ESLint for JavaScript/TypeScript, default `rustfmt` and Clippy with warnings-as-errors for Rust, and Ruff formatting/linting for Python.
72
+
73
+ Coverage is enforced at 80% for Python and Bun test suites when those ecosystems expose coverage support. Rust projects must keep their native test suites green; repositories with `cargo-llvm-cov` should enforce the same 80% line target in their Cargo coverage configuration.
74
+
75
+ ## Test runner standard
76
+
77
+ For TypeScript and JavaScript tests, use Bun's native test runner by default. Do not add Vitest to projects based on this template. Preserve specialized native runners such as Matchstick for The Graph and Hardhat for smart contracts.
78
+
79
+ ## Optional Turborepo remote caching
80
+
81
+ Turborepo repositories can use Vercel Remote Caching without changing the workflows. Add these repository settings:
82
+
83
+ - Secret: `TURBO_TOKEN`
84
+ - Repository variable: `TURBO_TEAM`
85
+
86
+ CI and Test pass those values to every job. Non-Turborepo repositories and repositories without the settings simply use their normal local cache behavior. This does not require the repository to deploy to Vercel.
87
+
88
+ ## License
89
+
90
+ Unless a repository says otherwise, new material is licensed under the GNU Affero General Public License v3.0-or-later. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
91
+
92
+ ## GitHub security behavior
93
+
94
+ The CodeQL workflow uses GitHub's official CodeQL actions, detects Actions, TypeScript, Python, and Rust automatically, and runs each language in parallel. It runs automatically for public repositories and skips itself for private repositories unless GitHub Code Security is enabled. Dependency Review is isolated in the Security workflow and runs only for public pull requests.
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "code-foundry",
3
+ "version": "0.1.0",
4
+ "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
+ "type": "module",
6
+ "license": "AGPL-3.0-or-later",
7
+ "packageManager": "bun@1.3.14",
8
+ "bin": {
9
+ "code-foundry": "src/cli.mjs"
10
+ },
11
+ "files": [
12
+ "src",
13
+ ".github",
14
+ ".githooks",
15
+ ".editorconfig",
16
+ ".gitattributes",
17
+ ".gitignore",
18
+ ".mise.toml",
19
+ ".prettierrc",
20
+ ".env.example",
21
+ "AGENTS.md",
22
+ "LICENSE",
23
+ "NOTICE",
24
+ "README.md",
25
+ "ruff.toml"
26
+ ],
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "scripts": {
31
+ "build": "node --check src/cli.mjs",
32
+ "format:check": "node --check src/cli.mjs",
33
+ "lint": "node --check src/cli.mjs",
34
+ "test": "node --check src/cli.mjs",
35
+ "type-check": "node --check src/cli.mjs",
36
+ "pack:check": "npm pack --dry-run",
37
+ "prepublishOnly": "npm test && npm run pack:check"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ }
42
+ }
package/ruff.toml ADDED
@@ -0,0 +1,6 @@
1
+ target-version = "py311"
2
+ line-length = 100
3
+
4
+ [lint]
5
+ select = ["E", "F", "W", "I", "UP", "B", "SIM"]
6
+ ignore = ["E501"]
package/src/cli.mjs ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync } from 'node:fs'
4
+ import { resolve } from 'node:path'
5
+ import { spawnSync } from 'node:child_process'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)))
9
+
10
+ const usage = `repo-foundry — initialize and maintain agent-ready repositories
11
+
12
+ Usage:
13
+ repo-foundry init [options]
14
+ repo-foundry sync [options]
15
+ repo-foundry doctor [--target PATH]
16
+
17
+ Init/sync options:
18
+ --target PATH Repository directory (default: current directory)
19
+ --source PATH_OR_URL Template source override
20
+ --ref REF Template branch or tag (default: main)
21
+ --languages LIST auto or typescript,rust,python,solidity
22
+ --features LIST all or ci,codeql,security,test,draft-pr,release-pr,release,dependabot
23
+ --package-manager NAME auto, bun, pnpm, yarn, or npm
24
+ --dry-run Preview changes without writing files
25
+ --prune Remove disabled standard workflows
26
+ --protection Synchronize main branch protections (init only)
27
+ --no-bootstrap Skip mise/hooks/doctor bootstrap after init
28
+ -h, --help Show this help
29
+ `
30
+
31
+ function fail(message) {
32
+ console.error(`repo-foundry: ${message}`)
33
+ process.exit(2)
34
+ }
35
+
36
+ function parseArgs(argv) {
37
+ const command = argv[0] && !argv[0].startsWith('-') ? argv.shift() : 'init'
38
+ const options = {
39
+ target: process.cwd(),
40
+ source: packageRoot,
41
+ ref: 'main',
42
+ languages: 'auto',
43
+ features: 'all',
44
+ packageManager: 'auto',
45
+ dryRun: false,
46
+ prune: false,
47
+ protection: false,
48
+ bootstrap: true,
49
+ }
50
+ const values = new Map([
51
+ ['--target', 'target'],
52
+ ['--source', 'source'],
53
+ ['--ref', 'ref'],
54
+ ['--languages', 'languages'],
55
+ ['--features', 'features'],
56
+ ['--package-manager', 'packageManager'],
57
+ ])
58
+
59
+ while (argv.length) {
60
+ const arg = argv.shift()
61
+ if (arg === '-h' || arg === '--help') {
62
+ console.log(usage)
63
+ process.exit(0)
64
+ }
65
+ if (values.has(arg)) {
66
+ const value = argv.shift()
67
+ if (!value || value.startsWith('-')) fail(`${arg} requires a value`)
68
+ options[values.get(arg)] = value
69
+ continue
70
+ }
71
+ if (arg === '--dry-run') options.dryRun = true
72
+ else if (arg === '--prune') options.prune = true
73
+ else if (arg === '--protection') options.protection = true
74
+ else if (arg === '--no-bootstrap') options.bootstrap = false
75
+ else fail(`unknown option: ${arg}`)
76
+ }
77
+
78
+ return { command, options }
79
+ }
80
+
81
+ function run(script, args, target) {
82
+ const scriptPath = resolve(packageRoot, '.github/scripts', script)
83
+ if (!existsSync(scriptPath)) fail(`package is missing ${script}`)
84
+ const result = spawnSync('bash', [scriptPath, ...args], {
85
+ cwd: target,
86
+ stdio: 'inherit',
87
+ env: process.env,
88
+ })
89
+ if (result.error) fail(result.error.message)
90
+ if (result.status !== 0) process.exit(result.status ?? 1)
91
+ }
92
+
93
+ function main() {
94
+ const { command, options } = parseArgs(process.argv.slice(2))
95
+ const target = resolve(options.target)
96
+ const common = [
97
+ '--source', options.source,
98
+ '--ref', options.ref,
99
+ '--languages', options.languages,
100
+ '--features', options.features,
101
+ ]
102
+ if (options.prune) common.push('--prune')
103
+ if (options.dryRun) common.push('--check')
104
+ else common.push('--apply')
105
+
106
+ if (command === 'init') {
107
+ const initArgs = [...common]
108
+ if (options.protection) initArgs.push('--protection')
109
+ if (!options.bootstrap) {
110
+ // The shell initializer is intentionally composable; sync first and let
111
+ // callers run bootstrap separately when installing into a CI image.
112
+ run('sync-template.sh', initArgs, target)
113
+ } else {
114
+ run('init-repo.sh', [
115
+ '--source', options.source,
116
+ '--ref', options.ref,
117
+ '--languages', options.languages,
118
+ '--features', options.features,
119
+ '--package-manager', options.packageManager,
120
+ ...(options.dryRun ? ['--dry-run'] : []),
121
+ ...(options.prune ? ['--prune'] : []),
122
+ ...(options.protection ? ['--protection'] : []),
123
+ ], target)
124
+ }
125
+ } else if (command === 'sync') {
126
+ run('sync-template.sh', common, target)
127
+ } else if (command === 'doctor') {
128
+ run('doctor.sh', [], target)
129
+ } else {
130
+ fail(`unknown command: ${command}`)
131
+ }
132
+ }
133
+
134
+ main()