code-foundry 0.1.0 → 0.1.2

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
- source="https://github.com/0xPlayerOne/template-repo.git"
4
+ source="https://github.com/0xPlayerOne/repo-foundry.git"
5
5
  ref="main"
6
6
  protection=false
7
7
  dry_run=false
@@ -9,6 +9,7 @@ prune=false
9
9
  languages="auto"
10
10
  features="all"
11
11
  package_manager="auto"
12
+ bootstrap=true
12
13
  tool_dir=""
13
14
 
14
15
  cleanup() {
@@ -32,6 +33,7 @@ Options:
32
33
  --dry-run Preview changes without writing files
33
34
  --prune Remove disabled standard workflows (never custom workflows)
34
35
  --protection Synchronize main branch required checks
36
+ --no-bootstrap Skip mise/hooks/doctor bootstrap after init
35
37
  -h, --help Show this help
36
38
 
37
39
  Examples:
@@ -51,6 +53,7 @@ while [ "$#" -gt 0 ]; do
51
53
  --dry-run) dry_run=true; shift ;;
52
54
  --prune) prune=true; shift ;;
53
55
  --protection) protection=true; shift ;;
56
+ --no-bootstrap) bootstrap=false; shift ;;
54
57
  -h|--help) usage; exit 0 ;;
55
58
  *)
56
59
  printf 'Unknown option: %s\n' "$1" >&2
@@ -99,6 +102,11 @@ features: $features
99
102
  package_manager: $package_manager
100
103
  EOF
101
104
 
105
+ if [ "$bootstrap" = false ]; then
106
+ printf '%s\n' 'Bootstrap skipped.'
107
+ exit 0
108
+ fi
109
+
102
110
  bash .github/scripts/bootstrap.sh
103
111
 
104
112
  if [ "$protection" = true ]; then
@@ -26,6 +26,9 @@ features="all"
26
26
  prune=false
27
27
  languages_set=false
28
28
  features_set=false
29
+ package_manager=""
30
+ gitignore_backup=""
31
+ custom_ignores=""
29
32
 
30
33
  valid_languages="typescript rust python solidity"
31
34
  valid_features="ci codeql security test draft-pr release-pr release dependabot"
@@ -56,6 +59,8 @@ workflow_enabled() {
56
59
 
57
60
  cleanup() {
58
61
  if [ -n "$temp_dir" ]; then rm -rf "$temp_dir"; fi
62
+ if [ -n "$gitignore_backup" ]; then rm -f "$gitignore_backup"; fi
63
+ if [ -n "$custom_ignores" ]; then rm -f "$custom_ignores"; fi
59
64
  }
60
65
  trap cleanup EXIT
61
66
 
@@ -83,6 +88,7 @@ if [ -f .github/template.yml ]; then
83
88
  configured_features="$(awk -F': ' '/^features:/ {print $2; exit}' .github/template.yml)"
84
89
  [ -n "$configured_features" ] && features="$configured_features"
85
90
  fi
91
+ package_manager="$(awk -F': ' '/^package_manager:/ {print $2; exit}' .github/template.yml)"
86
92
  fi
87
93
  validate_list language "$languages" "$valid_languages"
88
94
  validate_list feature "$features" "$valid_features"
@@ -193,7 +199,28 @@ for file in "${files[@]}"; do
193
199
  printf 'Would sync %s\n' "$file"
194
200
  else
195
201
  mkdir -p "$(dirname "$file")"
196
- cp "$template_file" "$file"
202
+ if [ "$file" = .gitignore ] && [ -f "$file" ]; then
203
+ # Keep repository-specific ignore rules while refreshing the shared
204
+ # baseline. This prevents a template sync from hiding generated files
205
+ # or local tooling that only one project uses.
206
+ gitignore_backup="$(mktemp)"
207
+ custom_ignores="$(mktemp)"
208
+ cp "$file" "$gitignore_backup"
209
+ cp "$template_file" "$file"
210
+ awk 'NR == FNR { seen[$0] = 1; next } NF && !seen[$0] { print }' \
211
+ "$template_file" "$gitignore_backup" > "$custom_ignores"
212
+ if [ -s "$custom_ignores" ]; then
213
+ {
214
+ printf '\n# Repository-specific rules\n'
215
+ cat "$custom_ignores"
216
+ } >> "$file"
217
+ fi
218
+ rm -f "$gitignore_backup" "$custom_ignores"
219
+ gitignore_backup=""
220
+ custom_ignores=""
221
+ else
222
+ cp "$template_file" "$file"
223
+ fi
197
224
  case "$file" in
198
225
  .githooks/*|.github/scripts/*) chmod +x "$file" ;;
199
226
  esac
@@ -217,11 +244,14 @@ done
217
244
  if [ "$mode" = "apply" ]; then
218
245
  git config core.hooksPath .githooks
219
246
  mkdir -p .github
220
- cat > .github/template.yml <<EOF
221
- version: 1
222
- languages: $languages
223
- features: $features
224
- EOF
247
+ {
248
+ printf 'version: 1\n'
249
+ printf 'languages: %s\n' "$languages"
250
+ printf 'features: %s\n' "$features"
251
+ if [ -n "$package_manager" ]; then
252
+ printf 'package_manager: %s\n' "$package_manager"
253
+ fi
254
+ } > .github/template.yml
225
255
  fi
226
256
 
227
257
  if [ "$prune" = true ]; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-or-later",
package/src/cli.mjs CHANGED
@@ -42,6 +42,8 @@ function parseArgs(argv) {
42
42
  languages: 'auto',
43
43
  features: 'all',
44
44
  packageManager: 'auto',
45
+ languagesSet: false,
46
+ featuresSet: false,
45
47
  dryRun: false,
46
48
  prune: false,
47
49
  protection: false,
@@ -66,6 +68,8 @@ function parseArgs(argv) {
66
68
  const value = argv.shift()
67
69
  if (!value || value.startsWith('-')) fail(`${arg} requires a value`)
68
70
  options[values.get(arg)] = value
71
+ if (arg === '--languages') options.languagesSet = true
72
+ if (arg === '--features') options.featuresSet = true
69
73
  continue
70
74
  }
71
75
  if (arg === '--dry-run') options.dryRun = true
@@ -93,35 +97,26 @@ function run(script, args, target) {
93
97
  function main() {
94
98
  const { command, options } = parseArgs(process.argv.slice(2))
95
99
  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
- ]
100
+ const common = ['--source', options.source, '--ref', options.ref]
101
+ if (options.languagesSet) common.push('--languages', options.languages)
102
+ if (options.featuresSet) common.push('--features', options.features)
102
103
  if (options.prune) common.push('--prune')
103
104
  if (options.dryRun) common.push('--check')
104
105
  else common.push('--apply')
105
106
 
106
107
  if (command === 'init') {
107
- const initArgs = [...common]
108
+ const initArgs = [
109
+ '--source', options.source,
110
+ '--ref', options.ref,
111
+ '--languages', options.languages,
112
+ '--features', options.features,
113
+ '--package-manager', options.packageManager,
114
+ ]
108
115
  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
- }
116
+ if (options.dryRun) initArgs.push('--dry-run')
117
+ if (options.prune) initArgs.push('--prune')
118
+ if (!options.bootstrap) initArgs.push('--no-bootstrap')
119
+ run('init-repo.sh', initArgs, target)
125
120
  } else if (command === 'sync') {
126
121
  run('sync-template.sh', common, target)
127
122
  } else if (command === 'doctor') {