xgem-cli 2.0.0-alpha.12 → 2.0.0-alpha.14
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/README.md +8 -0
- package/bin/xgem +41 -2
- package/bin/xgem.js +22 -35
- package/lib/bootstrap.sh +165 -0
- package/lib/ci.sh +44 -0
- package/lib/create.sh +1 -9
- package/lib/git.sh +240 -14
- package/lib/registry.sh +45 -0
- package/lib/release.sh +185 -0
- package/lib/status.sh +42 -0
- package/lib/utils.sh +11 -0
- package/lib/version.sh +1 -1
- package/lib-win/bootstrap.js +189 -0
- package/lib-win/ci.js +43 -0
- package/lib-win/git.js +221 -5
- package/lib-win/registry.js +43 -0
- package/lib-win/release.js +143 -0
- package/lib-win/scaffold.js +41 -1
- package/lib-win/status.js +53 -0
- package/lib-win/utils.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,14 @@ xgem git init Setup local repo, attach remote tracker shortcuts
|
|
|
62
62
|
xgem git branch Pick, create, or switch branches; remembers your choice
|
|
63
63
|
xgem git rm-remote Drop a configured remote
|
|
64
64
|
xgem git rm-branch Safely drop local and/or remote branch
|
|
65
|
+
xgem git pr Push current branch and open a GitHub PR (gh-backed)
|
|
66
|
+
xgem git sync Rebase current branch onto the repo's base branch
|
|
67
|
+
xgem git clean-branches Delete local branches already merged into the base branch
|
|
68
|
+
xgem git hooks <install|uninstall> Manage a pre-commit lint/test hook
|
|
69
|
+
xgem release [major|minor|patch] Bump version, update CHANGELOG.md, tag, push
|
|
70
|
+
xgem status Dashboard across every xgem-tracked project
|
|
71
|
+
xgem bootstrap Clone-to-running: detect framework, install, .env, migrate, launch
|
|
72
|
+
xgem ci Run lint/test/build for every configured framework, summarized
|
|
65
73
|
xgem --version Print xgem's version
|
|
66
74
|
|
|
67
75
|
Flags (any command): --yes (skip confirmations), --dry-run (show, don't apply), --verbose
|
package/bin/xgem
CHANGED
|
@@ -35,6 +35,16 @@ source "$XGEM_HOME/lib/flutter.sh"
|
|
|
35
35
|
source "$XGEM_HOME/lib/scaffold.sh"
|
|
36
36
|
# shellcheck source=lib/create.sh
|
|
37
37
|
source "$XGEM_HOME/lib/create.sh"
|
|
38
|
+
# shellcheck source=lib/release.sh
|
|
39
|
+
source "$XGEM_HOME/lib/release.sh"
|
|
40
|
+
# shellcheck source=lib/registry.sh
|
|
41
|
+
source "$XGEM_HOME/lib/registry.sh"
|
|
42
|
+
# shellcheck source=lib/status.sh
|
|
43
|
+
source "$XGEM_HOME/lib/status.sh"
|
|
44
|
+
# shellcheck source=lib/bootstrap.sh
|
|
45
|
+
source "$XGEM_HOME/lib/bootstrap.sh"
|
|
46
|
+
# shellcheck source=lib/ci.sh
|
|
47
|
+
source "$XGEM_HOME/lib/ci.sh"
|
|
38
48
|
|
|
39
49
|
CONFIG_DIR=".xgem-automate"
|
|
40
50
|
|
|
@@ -75,6 +85,14 @@ print_usage() {
|
|
|
75
85
|
echo " xgem git branch - Pick, create, or switch branches; remembers your choice"
|
|
76
86
|
echo " xgem git rm-remote - Drop specified target remote tracing rules"
|
|
77
87
|
echo " xgem git rm-branch - Safely drop local and remote workspace branch states"
|
|
88
|
+
echo " xgem git pr - Push current branch and open a GitHub PR (gh-backed)"
|
|
89
|
+
echo " xgem git sync - Rebase current branch onto the repo's base branch"
|
|
90
|
+
echo " xgem git clean-branches - Delete local branches already merged into the base branch"
|
|
91
|
+
echo " xgem git hooks <install|uninstall> - Manage a pre-commit lint/test hook"
|
|
92
|
+
echo " xgem release [major|minor|patch] - Bump version, update CHANGELOG.md, tag, push"
|
|
93
|
+
echo " xgem status - Dashboard across every xgem-tracked project"
|
|
94
|
+
echo " xgem bootstrap - Clone-to-running: detect framework, install, .env, migrate, launch"
|
|
95
|
+
echo " xgem ci - Run lint/test/build for every configured framework, summarized"
|
|
78
96
|
echo " xgem --version - Print xgem's version"
|
|
79
97
|
echo ""
|
|
80
98
|
echo "Flags (any command): --yes (skip confirmations), --dry-run (show, don't apply), --verbose"
|
|
@@ -161,7 +179,7 @@ case "${1:-}" in
|
|
|
161
179
|
else
|
|
162
180
|
scaffold_run_script "$FRAMEWORK" "$SCRIPT_NAME" "$CONFIG_DIR"
|
|
163
181
|
fi
|
|
164
|
-
exit
|
|
182
|
+
exit $?
|
|
165
183
|
;;
|
|
166
184
|
|
|
167
185
|
terminate)
|
|
@@ -178,6 +196,7 @@ case "${1:-}" in
|
|
|
178
196
|
rm -rf "${CONFIG_DIR:?}/$fw"
|
|
179
197
|
done
|
|
180
198
|
rm -rf "$CONFIG_DIR"
|
|
199
|
+
registry_remove "$(pwd)"
|
|
181
200
|
|
|
182
201
|
if [ -f .gitignore ]; then
|
|
183
202
|
grep -v "^$CONFIG_DIR/" .gitignore > tmp_gitignore && mv tmp_gitignore .gitignore
|
|
@@ -189,7 +208,7 @@ case "${1:-}" in
|
|
|
189
208
|
;;
|
|
190
209
|
|
|
191
210
|
git)
|
|
192
|
-
[ -n "${2:-}" ] || die "Usage: xgem git <cmt|init|branch|rm-remote|rm-branch>"
|
|
211
|
+
[ -n "${2:-}" ] || die "Usage: xgem git <cmt|init|branch|rm-remote|rm-branch|pr|sync|clean-branches|hooks>"
|
|
193
212
|
cmd_git "$2" "${3:-}"
|
|
194
213
|
exit 0
|
|
195
214
|
;;
|
|
@@ -199,6 +218,26 @@ case "${1:-}" in
|
|
|
199
218
|
exit 0
|
|
200
219
|
;;
|
|
201
220
|
|
|
221
|
+
release)
|
|
222
|
+
cmd_release "${2:-}"
|
|
223
|
+
exit 0
|
|
224
|
+
;;
|
|
225
|
+
|
|
226
|
+
status)
|
|
227
|
+
cmd_status
|
|
228
|
+
exit 0
|
|
229
|
+
;;
|
|
230
|
+
|
|
231
|
+
bootstrap)
|
|
232
|
+
cmd_bootstrap
|
|
233
|
+
exit 0
|
|
234
|
+
;;
|
|
235
|
+
|
|
236
|
+
ci)
|
|
237
|
+
cmd_ci
|
|
238
|
+
exit $?
|
|
239
|
+
;;
|
|
240
|
+
|
|
202
241
|
--version|-V|version)
|
|
203
242
|
print_version
|
|
204
243
|
exit 0
|
package/bin/xgem.js
CHANGED
|
@@ -21,6 +21,11 @@ const { cmdDoctor } = require('../lib-win/doctor');
|
|
|
21
21
|
const { cmdGit } = require('../lib-win/git');
|
|
22
22
|
const { cmdFlutter } = require('../lib-win/flutter');
|
|
23
23
|
const scaffold = require('../lib-win/scaffold');
|
|
24
|
+
const { cmdRelease } = require('../lib-win/release');
|
|
25
|
+
const { registryAdd, registryRemove } = require('../lib-win/registry');
|
|
26
|
+
const { cmdStatus } = require('../lib-win/status');
|
|
27
|
+
const { cmdBootstrap } = require('../lib-win/bootstrap');
|
|
28
|
+
const { cmdCi } = require('../lib-win/ci');
|
|
24
29
|
|
|
25
30
|
const CONFIG_DIR = '.xgem-automate';
|
|
26
31
|
|
|
@@ -48,6 +53,14 @@ function printUsage() {
|
|
|
48
53
|
console.log(' xgem git branch - Pick, create, or switch branches; remembers your choice');
|
|
49
54
|
console.log(' xgem git rm-remote - Drop specified target remote tracing rules');
|
|
50
55
|
console.log(' xgem git rm-branch - Safely drop local and remote workspace branch states');
|
|
56
|
+
console.log(' xgem git pr - Push current branch and open a GitHub PR (gh-backed)');
|
|
57
|
+
console.log(' xgem git sync - Rebase current branch onto the repo\'s base branch');
|
|
58
|
+
console.log(' xgem git clean-branches - Delete local branches already merged into the base branch');
|
|
59
|
+
console.log(' xgem git hooks <install|uninstall> - Manage a pre-commit lint/test hook');
|
|
60
|
+
console.log(' xgem release [major|minor|patch] - Bump version, update CHANGELOG.md, tag, push');
|
|
61
|
+
console.log(' xgem status - Dashboard across every xgem-tracked project');
|
|
62
|
+
console.log(' xgem bootstrap - Clone-to-running: detect framework, install, .env, migrate, launch');
|
|
63
|
+
console.log(' xgem ci - Run lint/test/build for every configured framework, summarized');
|
|
51
64
|
console.log(' xgem --version - Print xgem\'s version');
|
|
52
65
|
console.log('');
|
|
53
66
|
console.log('Flags (any command): --yes (skip confirmations), --dry-run (show, don\'t apply), --verbose');
|
|
@@ -61,35 +74,6 @@ async function selectFramework(options) {
|
|
|
61
74
|
return options[idx];
|
|
62
75
|
}
|
|
63
76
|
|
|
64
|
-
// Some teams want the generated scripts checked in so collaborators get the
|
|
65
|
-
// same automation; others want them private/local-only. Ask instead of
|
|
66
|
-
// always gitignoring.
|
|
67
|
-
async function updateGitignore() {
|
|
68
|
-
const gitignorePath = '.gitignore';
|
|
69
|
-
const ignoreChoice = ((await prompt(`Should ${CONFIG_DIR}/ be ignored by git (private to you), or tracked so collaborators get the same scripts? [ignore/track]`, 'ignore'))).toLowerCase();
|
|
70
|
-
|
|
71
|
-
if (ignoreChoice.startsWith('t')) {
|
|
72
|
-
if (fs.existsSync(gitignorePath)) {
|
|
73
|
-
const lines = fs.readFileSync(gitignorePath, 'utf8').split(/\r?\n/).filter((l) => l !== `${CONFIG_DIR}/`);
|
|
74
|
-
fs.writeFileSync(gitignorePath, lines.join('\n'));
|
|
75
|
-
logInfo(`Removed existing ${CONFIG_DIR}/ entry from .gitignore since you chose to track it.`);
|
|
76
|
-
}
|
|
77
|
-
logSuccess(`${CONFIG_DIR}/ will be tracked in git.`);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (fs.existsSync(gitignorePath)) {
|
|
82
|
-
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
83
|
-
if (!content.includes(`${CONFIG_DIR}/`)) {
|
|
84
|
-
fs.appendFileSync(gitignorePath, `\n${CONFIG_DIR}/\n`);
|
|
85
|
-
logSuccess('Added automation tracking to .gitignore');
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
fs.writeFileSync(gitignorePath, `${CONFIG_DIR}/\n`);
|
|
89
|
-
logSuccess('Created .gitignore and hidden tracking layer folder references.');
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
77
|
async function cmdInit() {
|
|
94
78
|
printBanner();
|
|
95
79
|
if (fs.existsSync(CONFIG_DIR)) {
|
|
@@ -97,14 +81,12 @@ async function cmdInit() {
|
|
|
97
81
|
return;
|
|
98
82
|
}
|
|
99
83
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
84
|
+
registryAdd(process.cwd());
|
|
100
85
|
|
|
101
86
|
console.log('Select your starting framework architecture:');
|
|
102
87
|
const fw = await selectFramework(scaffold.ALL_FRAMEWORKS);
|
|
103
88
|
if (!fw) die('Invalid selection.');
|
|
104
|
-
scaffold.
|
|
105
|
-
logSuccess(`Successfully appended standard scripts for: ${CONFIG_DIR}/${fw}`);
|
|
106
|
-
|
|
107
|
-
await updateGitignore();
|
|
89
|
+
await scaffold.bookkeeping(fw, CONFIG_DIR);
|
|
108
90
|
}
|
|
109
91
|
|
|
110
92
|
async function cmdAdd() {
|
|
@@ -154,6 +136,7 @@ async function cmdTerminate() {
|
|
|
154
136
|
fs.rmSync(path.join(CONFIG_DIR, fw), { recursive: true, force: true });
|
|
155
137
|
}
|
|
156
138
|
fs.rmSync(CONFIG_DIR, { recursive: true, force: true });
|
|
139
|
+
registryRemove(process.cwd());
|
|
157
140
|
|
|
158
141
|
if (fs.existsSync('.gitignore')) {
|
|
159
142
|
const lines = fs.readFileSync('.gitignore', 'utf8').split(/\r?\n/).filter((l) => l !== `${CONFIG_DIR}/`);
|
|
@@ -203,9 +186,13 @@ async function main() {
|
|
|
203
186
|
case 'run': return cmdRun(a2, a3);
|
|
204
187
|
case 'terminate': return cmdTerminate();
|
|
205
188
|
case 'git':
|
|
206
|
-
if (!a2) die('Usage: xgem git <cmt|init|branch|rm-remote|rm-branch>');
|
|
207
|
-
return cmdGit(a2, a3);
|
|
189
|
+
if (!a2) die('Usage: xgem git <cmt|init|branch|rm-remote|rm-branch|pr|sync|clean-branches|hooks>');
|
|
190
|
+
return cmdGit(a2, a3, CONFIG_DIR);
|
|
208
191
|
case 'doctor': return cmdDoctor(a2);
|
|
192
|
+
case 'release': return cmdRelease(a2);
|
|
193
|
+
case 'status': return cmdStatus(CONFIG_DIR);
|
|
194
|
+
case 'bootstrap': return cmdBootstrap(CONFIG_DIR);
|
|
195
|
+
case 'ci': return cmdCi(CONFIG_DIR);
|
|
209
196
|
case '--version':
|
|
210
197
|
case '-V':
|
|
211
198
|
case 'version': {
|
package/lib/bootstrap.sh
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# xgem bootstrap: clone-to-running in one command, for a project you just
|
|
3
|
+
# checked out (not creating a new one — that's `xgem init`'s job).
|
|
4
|
+
# Depends on lib/logger.sh, lib/utils.sh, lib/scaffold.sh, lib/create.sh.
|
|
5
|
+
|
|
6
|
+
# _detect_framework -> a name from ALL_FRAMEWORKS, or empty if nothing
|
|
7
|
+
# recognizable was found. Never assumes; probes for marker files the same
|
|
8
|
+
# way lib/doctor.sh probes for tools instead of guessing.
|
|
9
|
+
_detect_framework() {
|
|
10
|
+
[ -f pubspec.yaml ] && { echo flutter; return 0; }
|
|
11
|
+
[ -f go.mod ] && { echo go; return 0; }
|
|
12
|
+
[ -f Cargo.toml ] && { echo rust; return 0; }
|
|
13
|
+
{ [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; } && { echo python; return 0; }
|
|
14
|
+
[ -f Package.swift ] && { echo swift; return 0; }
|
|
15
|
+
if [ -f package.json ]; then
|
|
16
|
+
if grep -q '"next"' package.json; then echo next
|
|
17
|
+
elif grep -q '"@angular/core"' package.json; then echo angular
|
|
18
|
+
elif grep -q '"vue"' package.json; then echo vue
|
|
19
|
+
elif grep -q '"react"' package.json; then echo react
|
|
20
|
+
else echo node
|
|
21
|
+
fi
|
|
22
|
+
return 0
|
|
23
|
+
fi
|
|
24
|
+
[ -f Dockerfile ] && { echo docker; return 0; }
|
|
25
|
+
return 1
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
_bootstrap_env_file() {
|
|
29
|
+
[ -f .env ] && { log_debug ".env already exists, leaving it as-is."; return 0; }
|
|
30
|
+
local example
|
|
31
|
+
for example in .env.example .env.sample; do
|
|
32
|
+
[ -f "$example" ] || continue
|
|
33
|
+
cp "$example" .env
|
|
34
|
+
log_success "Created .env from $example."
|
|
35
|
+
local missing
|
|
36
|
+
missing=$(grep -E '^[A-Za-z_][A-Za-z0-9_]*=[[:space:]]*$' .env | cut -d= -f1)
|
|
37
|
+
if [ -n "$missing" ]; then
|
|
38
|
+
log_warn "These .env keys are empty — fill them in:"
|
|
39
|
+
echo "$missing" | sed 's/^/ - /'
|
|
40
|
+
fi
|
|
41
|
+
return 0
|
|
42
|
+
done
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_bootstrap_node_pm() {
|
|
46
|
+
if [ -f pnpm-lock.yaml ]; then echo pnpm
|
|
47
|
+
elif [ -f yarn.lock ]; then echo yarn
|
|
48
|
+
elif [ -f bun.lockb ] || [ -f bun.lock ]; then echo bun
|
|
49
|
+
else echo npm
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_bootstrap_install() {
|
|
54
|
+
local fw=$1
|
|
55
|
+
case "$fw" in
|
|
56
|
+
node|react|vue|angular|next)
|
|
57
|
+
local pm
|
|
58
|
+
pm=$(_bootstrap_node_pm)
|
|
59
|
+
log_info "Installing dependencies with $pm..."
|
|
60
|
+
case "$pm" in
|
|
61
|
+
yarn) yarn ;;
|
|
62
|
+
pnpm) pnpm install ;;
|
|
63
|
+
bun) bun install ;;
|
|
64
|
+
*) npm install ;;
|
|
65
|
+
esac
|
|
66
|
+
;;
|
|
67
|
+
flutter)
|
|
68
|
+
has_cmd flutter || { log_warn "flutter not found — skipping 'flutter pub get'."; return 0; }
|
|
69
|
+
log_info "Running flutter pub get..."
|
|
70
|
+
flutter pub get
|
|
71
|
+
;;
|
|
72
|
+
python)
|
|
73
|
+
if [ -f pyproject.toml ] && has_cmd poetry; then
|
|
74
|
+
log_info "Installing dependencies with poetry..."
|
|
75
|
+
poetry install
|
|
76
|
+
elif [ -f requirements.txt ]; then
|
|
77
|
+
has_cmd python3 || { log_warn "python3 not found — skipping install."; return 0; }
|
|
78
|
+
[ -d .venv ] || python3 -m venv .venv
|
|
79
|
+
log_info "Installing dependencies into .venv..."
|
|
80
|
+
.venv/bin/pip install -r requirements.txt
|
|
81
|
+
fi
|
|
82
|
+
;;
|
|
83
|
+
go)
|
|
84
|
+
has_cmd go || { log_warn "go not found — skipping 'go mod download'."; return 0; }
|
|
85
|
+
log_info "Running go mod download..."
|
|
86
|
+
go mod download
|
|
87
|
+
;;
|
|
88
|
+
rust)
|
|
89
|
+
has_cmd cargo || { log_warn "cargo not found — skipping 'cargo fetch'."; return 0; }
|
|
90
|
+
log_info "Running cargo fetch..."
|
|
91
|
+
cargo fetch
|
|
92
|
+
;;
|
|
93
|
+
swift)
|
|
94
|
+
has_cmd swift || { log_warn "swift not found — skipping 'swift package resolve'."; return 0; }
|
|
95
|
+
log_info "Running swift package resolve..."
|
|
96
|
+
swift package resolve
|
|
97
|
+
;;
|
|
98
|
+
docker)
|
|
99
|
+
log_debug "Docker project — nothing to install locally."
|
|
100
|
+
;;
|
|
101
|
+
esac
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_bootstrap_migrations() {
|
|
105
|
+
local fw=$1
|
|
106
|
+
if [ "$fw" = "node" ] || [ "$fw" = "react" ] || [ "$fw" = "vue" ] || [ "$fw" = "angular" ] || [ "$fw" = "next" ]; then
|
|
107
|
+
if _package_json_has_script migrate; then
|
|
108
|
+
local pm
|
|
109
|
+
pm=$(_bootstrap_node_pm)
|
|
110
|
+
confirm "Run the project's 'migrate' script (via $pm)?" || return 0
|
|
111
|
+
case "$pm" in
|
|
112
|
+
yarn) yarn migrate ;;
|
|
113
|
+
pnpm) pnpm run migrate ;;
|
|
114
|
+
bun) bun run migrate ;;
|
|
115
|
+
*) npm run migrate ;;
|
|
116
|
+
esac
|
|
117
|
+
return 0
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
if [ -f prisma/schema.prisma ]; then
|
|
121
|
+
confirm "Run 'npx prisma migrate dev'?" && npx prisma migrate dev
|
|
122
|
+
elif [ -f manage.py ]; then
|
|
123
|
+
has_cmd python3 && confirm "Run 'python3 manage.py migrate'?" && python3 manage.py migrate
|
|
124
|
+
fi
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_bootstrap_offer_dev_server() {
|
|
128
|
+
local fw=$1
|
|
129
|
+
local script=""
|
|
130
|
+
case "$fw" in
|
|
131
|
+
node) script=start ;;
|
|
132
|
+
react|vue|angular|next) script=dev ;;
|
|
133
|
+
*) return 0 ;;
|
|
134
|
+
esac
|
|
135
|
+
[ -f "$CONFIG_DIR/$fw/$script.sh" ] || return 0
|
|
136
|
+
confirm "Launch the dev server now ('xgem run $fw $script')?" && scaffold_run_script "$fw" "$script" "$CONFIG_DIR"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
cmd_bootstrap() {
|
|
140
|
+
log_info "Detecting project framework..."
|
|
141
|
+
local fw
|
|
142
|
+
fw=$(_detect_framework)
|
|
143
|
+
if [ -z "$fw" ]; then
|
|
144
|
+
log_warn "Could not auto-detect the framework from any known marker file."
|
|
145
|
+
echo "Pick one:"
|
|
146
|
+
PS3="Enter target selection number: "
|
|
147
|
+
select fw in "${ALL_FRAMEWORKS[@]}"; do
|
|
148
|
+
[ -n "$fw" ] && break
|
|
149
|
+
echo "Invalid selection."
|
|
150
|
+
done
|
|
151
|
+
else
|
|
152
|
+
log_success "Detected: $fw"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
_bootstrap_env_file
|
|
156
|
+
_bootstrap_install "$fw"
|
|
157
|
+
_bootstrap_migrations "$fw"
|
|
158
|
+
|
|
159
|
+
if [ ! -d "$CONFIG_DIR" ]; then
|
|
160
|
+
confirm "Scaffold xgem automation scripts (.xgem-automate) for $fw too?" && _xgem_bookkeeping "$fw"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
_bootstrap_offer_dev_server "$fw"
|
|
164
|
+
log_success "Bootstrap complete."
|
|
165
|
+
}
|
package/lib/ci.sh
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# xgem ci: run lint -> test -> build for every configured framework before
|
|
3
|
+
# you push, so a CI failure gets caught locally first.
|
|
4
|
+
# Depends on lib/logger.sh.
|
|
5
|
+
|
|
6
|
+
cmd_ci() {
|
|
7
|
+
[ -d "$CONFIG_DIR" ] || die "No $CONFIG_DIR found — run 'xgem init' or 'xgem add' first."
|
|
8
|
+
|
|
9
|
+
local -a steps=(lint test build)
|
|
10
|
+
local -a results=()
|
|
11
|
+
local overall_status=0
|
|
12
|
+
local fw_dir fw step
|
|
13
|
+
|
|
14
|
+
for fw_dir in "$CONFIG_DIR"/*/; do
|
|
15
|
+
[ -d "$fw_dir" ] || continue
|
|
16
|
+
fw=$(basename "$fw_dir")
|
|
17
|
+
for step in "${steps[@]}"; do
|
|
18
|
+
[ -f "$CONFIG_DIR/$fw/$step.sh" ] || continue
|
|
19
|
+
log_info "Running $fw $step..."
|
|
20
|
+
if bash "$CONFIG_DIR/$fw/$step.sh"; then
|
|
21
|
+
results+=("PASS $fw $step")
|
|
22
|
+
else
|
|
23
|
+
results+=("FAIL $fw $step")
|
|
24
|
+
overall_status=1
|
|
25
|
+
fi
|
|
26
|
+
done
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
if [ ${#results[@]} -eq 0 ]; then
|
|
30
|
+
log_warn "No lint/test/build scripts found under $CONFIG_DIR to run."
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
echo ""
|
|
35
|
+
echo "=== xgem ci summary ==="
|
|
36
|
+
printf '%s\n' "${results[@]}"
|
|
37
|
+
|
|
38
|
+
if [ "$overall_status" -eq 0 ]; then
|
|
39
|
+
log_success "All checks passed."
|
|
40
|
+
else
|
|
41
|
+
log_error "Some checks failed."
|
|
42
|
+
fi
|
|
43
|
+
return "$overall_status"
|
|
44
|
+
}
|
package/lib/create.sh
CHANGED
|
@@ -42,6 +42,7 @@ XGEM_CREATED_NEW_FOLDER=""
|
|
|
42
42
|
_xgem_bookkeeping() {
|
|
43
43
|
local fw=$1
|
|
44
44
|
mkdir -p "$CONFIG_DIR"
|
|
45
|
+
registry_add "$(pwd)"
|
|
45
46
|
scaffold_inject_templates "$fw" "$CONFIG_DIR"
|
|
46
47
|
log_success "Successfully appended standard scripts for: $CONFIG_DIR/$fw"
|
|
47
48
|
|
|
@@ -98,15 +99,6 @@ _enter_project_dir() {
|
|
|
98
99
|
mkdir -p "$project_dir" && cd "$project_dir" || die "Could not enter $project_dir"
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
_open_url() {
|
|
102
|
-
local url=$1
|
|
103
|
-
case "$(detect_os)" in
|
|
104
|
-
darwin) open "$url" 2>/dev/null ;;
|
|
105
|
-
linux) xdg-open "$url" 2>/dev/null ;;
|
|
106
|
-
*) log_debug "Don't know how to open a browser on this OS — visit $url manually." ;;
|
|
107
|
-
esac
|
|
108
|
-
}
|
|
109
|
-
|
|
110
102
|
# _launch_dev_server_and_open_browser <cmd...>
|
|
111
103
|
# Starts the dev server in the background, tails its log for the first
|
|
112
104
|
# http://localhost URL it prints — this works across Vite/CRA/Next/Angular
|