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.
- package/.github/scripts/init-repo.sh +9 -1
- package/.github/scripts/sync-template.sh +36 -6
- package/package.json +1 -1
- package/src/cli.mjs +18 -23
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
-
source="https://github.com/0xPlayerOne/
|
|
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
|
-
|
|
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
|
-
|
|
221
|
-
version: 1
|
|
222
|
-
languages: $languages
|
|
223
|
-
features: $features
|
|
224
|
-
|
|
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
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
|
-
|
|
98
|
-
|
|
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 = [
|
|
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 (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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') {
|