@daemux/store-automator 0.5.3 → 0.7.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/bin/cli.mjs +3 -1
- package/package.json +1 -1
- package/plugins/store-automator/.claude-plugin/plugin.json +1 -1
- package/plugins/store-automator/agents/devops.md +8 -8
- package/src/ci-config.mjs +35 -0
- package/src/codemagic-api.mjs +4 -2
- package/src/codemagic-setup.mjs +39 -13
- package/src/github-setup.mjs +2 -11
- package/src/install.mjs +46 -2
- package/src/mcp-setup.mjs +27 -1
- package/src/prompt.mjs +10 -1
- package/src/utils.mjs +9 -0
- package/templates/ci.config.yaml.template +1 -0
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "App Store & Google Play automation for Flutter apps",
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.7.0"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "store-automator",
|
|
13
13
|
"source": "./plugins/store-automator",
|
|
14
14
|
"description": "3 agents for app store publishing: reviewer, meta-creator, media-designer",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.7.0",
|
|
16
16
|
"keywords": ["flutter", "app-store", "google-play", "fastlane", "codemagic"]
|
|
17
17
|
}
|
|
18
18
|
]
|
package/bin/cli.mjs
CHANGED
|
@@ -29,6 +29,7 @@ function flagValue(arg, prefix) {
|
|
|
29
29
|
|
|
30
30
|
const tokenFlags = {
|
|
31
31
|
'--codemagic-token=': 'codemagicToken',
|
|
32
|
+
'--codemagic-team-id=': 'codemagicTeamId',
|
|
32
33
|
'--stitch-key=': 'stitchApiKey',
|
|
33
34
|
'--cloudflare-token=': 'cloudflareToken',
|
|
34
35
|
'--cloudflare-account-id=': 'cloudflareAccountId',
|
|
@@ -87,6 +88,7 @@ Options:
|
|
|
87
88
|
|
|
88
89
|
MCP Token Flags (skip interactive prompts):
|
|
89
90
|
--codemagic-token=TOKEN Codemagic API token
|
|
91
|
+
--codemagic-team-id=ID Codemagic Team ID (from Teams page)
|
|
90
92
|
--stitch-key=KEY Stitch MCP API key
|
|
91
93
|
--cloudflare-token=TOKEN Cloudflare API token
|
|
92
94
|
--cloudflare-account-id=ID Cloudflare account ID
|
|
@@ -113,7 +115,7 @@ Examples:
|
|
|
113
115
|
npx @daemux/store-automator --github-setup Configure GitHub Actions
|
|
114
116
|
|
|
115
117
|
Non-interactive install (CI/CD):
|
|
116
|
-
npx @daemux/store-automator --codemagic-token=TOKEN --stitch-key=KEY
|
|
118
|
+
npx @daemux/store-automator --codemagic-token=TOKEN --codemagic-team-id=ID --stitch-key=KEY
|
|
117
119
|
npx @daemux/store-automator --cloudflare-token=TOKEN --cloudflare-account-id=ID`);
|
|
118
120
|
process.exit(0);
|
|
119
121
|
break; // eslint: no-fallthrough
|
package/package.json
CHANGED
|
@@ -44,7 +44,7 @@ The Codemagic pipeline runs two parallel workflows on push to `main`:
|
|
|
44
44
|
|
|
45
45
|
### Token Configuration
|
|
46
46
|
|
|
47
|
-
The Codemagic API token
|
|
47
|
+
The Codemagic API token and Team ID are auto-configured via the codemagic MCP server in `.mcp.json` (set during install). You do not need to resolve the token manually -- all MCP tool calls authenticate automatically. The `CODEMAGIC_TEAM_ID` env var enables default team resolution for team-scoped tools (`list_builds`, `get_team`, `list_team_members`, `create_variable_group`, `setup_asc_credentials`, `setup_code_signing`). If the codemagic MCP server is missing from `.mcp.json`, instruct the user to re-run `npx @daemux/store-automator` or add `--codemagic-token=TOKEN --codemagic-team-id=ID` to configure it.
|
|
48
48
|
|
|
49
49
|
### Triggering Builds
|
|
50
50
|
|
|
@@ -76,20 +76,20 @@ Build states: `queued` -> `preparing` -> `building` -> `testing` -> `publishing`
|
|
|
76
76
|
| `start_build` | Start a new build |
|
|
77
77
|
| `get_build` | Get details of a specific build |
|
|
78
78
|
| `cancel_build` | Cancel a running build |
|
|
79
|
-
| `list_builds` | List builds for a team (V3 API) |
|
|
79
|
+
| `list_builds` | List builds for a team (V3 API, uses default team if omitted) |
|
|
80
80
|
| `get_artifact_url` | Get the download URL for a build artifact |
|
|
81
81
|
| `create_public_artifact_url` | Create a time-limited public URL for an artifact |
|
|
82
82
|
| `list_caches` | List build caches for an application |
|
|
83
83
|
| `delete_caches` | Delete build caches for an application |
|
|
84
|
-
| `setup_asc_credentials` | Create variable group with
|
|
85
|
-
| `setup_code_signing` | Create variable group with iOS
|
|
84
|
+
| `setup_asc_credentials` | Create variable group with ASC credentials (uses default team if omitted) |
|
|
85
|
+
| `setup_code_signing` | Create variable group with iOS signing (uses default team if omitted) |
|
|
86
86
|
| `get_user` | Get the current authenticated user info |
|
|
87
87
|
| `list_teams` | List all teams the user belongs to |
|
|
88
|
-
| `get_team` | Get details of a specific team |
|
|
89
|
-
| `list_team_members` | List members of a
|
|
88
|
+
| `get_team` | Get details of a specific team (uses default team if omitted) |
|
|
89
|
+
| `list_team_members` | List members of a team (uses default team if omitted) |
|
|
90
90
|
| `list_variable_groups` | List variable groups for a team or application |
|
|
91
91
|
| `get_variable_group` | Get details of a specific variable group |
|
|
92
|
-
| `create_variable_group` | Create a new variable group |
|
|
92
|
+
| `create_variable_group` | Create a new variable group (uses default team if omitted) |
|
|
93
93
|
| `update_variable_group` | Update a variable group name or security setting |
|
|
94
94
|
| `delete_variable_group` | Delete a variable group |
|
|
95
95
|
| `list_variables` | List variables in a variable group |
|
|
@@ -366,7 +366,7 @@ Analyze Firestore usage patterns and optimize queries, indexes, and security rul
|
|
|
366
366
|
|
|
367
367
|
| File | Purpose |
|
|
368
368
|
|------|---------|
|
|
369
|
-
| `ci.config.yaml` | Single source of truth for all CI/CD config |
|
|
369
|
+
| `ci.config.yaml` | Single source of truth for all CI/CD config (includes team_id, app_id) |
|
|
370
370
|
| `codemagic.yaml` | Generated from template -- do not edit directly |
|
|
371
371
|
| `templates/codemagic.template.yaml` | Codemagic workflow template |
|
|
372
372
|
| `scripts/generate.sh` | Generates codemagic.yaml from ci.config.yaml |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const CI_CONFIG_FILE = 'ci.config.yaml';
|
|
5
|
+
const FIELD_PATTERNS = {
|
|
6
|
+
app_id: /^(\s*app_id:\s*)"[^"]*"/m,
|
|
7
|
+
team_id: /^(\s*team_id:\s*)"[^"]*"/m,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function writeCiField(projectDir, field, value) {
|
|
11
|
+
const configPath = join(projectDir, CI_CONFIG_FILE);
|
|
12
|
+
if (!existsSync(configPath)) return false;
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const pattern = FIELD_PATTERNS[field];
|
|
16
|
+
const content = readFileSync(configPath, 'utf8');
|
|
17
|
+
if (!pattern.test(content)) return false;
|
|
18
|
+
|
|
19
|
+
const updated = content.replace(pattern, `$1"${value}"`);
|
|
20
|
+
if (updated === content) return false;
|
|
21
|
+
|
|
22
|
+
writeFileSync(configPath, updated, 'utf8');
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function writeCiAppId(projectDir, appId) {
|
|
30
|
+
return writeCiField(projectDir, 'app_id', appId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function writeCiTeamId(projectDir, teamId) {
|
|
34
|
+
return writeCiField(projectDir, 'team_id', teamId);
|
|
35
|
+
}
|
package/src/codemagic-api.mjs
CHANGED
|
@@ -50,8 +50,10 @@ export async function findAppByRepo(token, repoUrl) {
|
|
|
50
50
|
}) || null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export async function addApp(token, repoUrl) {
|
|
54
|
-
|
|
53
|
+
export async function addApp(token, repoUrl, teamId) {
|
|
54
|
+
const body = { repositoryUrl: repoUrl };
|
|
55
|
+
if (teamId) body.teamId = teamId;
|
|
56
|
+
return cmFetch(token, 'POST', '/apps', body);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export async function startBuild(token, appId, workflowId, branch) {
|
package/src/codemagic-setup.mjs
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { findAppByRepo, addApp, startBuild, getBuildStatus, normalizeRepoUrl } from './codemagic-api.mjs';
|
|
2
|
-
import { exec } from './utils.mjs';
|
|
2
|
+
import { exec, resolveToken } from './utils.mjs';
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { writeCiAppId, writeCiTeamId } from './ci-config.mjs';
|
|
7
|
+
import { updateMcpAppId, updateMcpTeamId } from './mcp-setup.mjs';
|
|
4
8
|
|
|
5
9
|
const POLL_INTERVAL_MS = 30_000;
|
|
6
10
|
const POLL_TIMEOUT_MS = 15 * 60 * 1000;
|
|
7
11
|
const TERMINAL_STATUSES = new Set(['finished', 'failed', 'canceled']);
|
|
8
12
|
|
|
9
|
-
function resolveToken(tokenArg) {
|
|
10
|
-
const token = process.env.CM_API_TOKEN || tokenArg;
|
|
11
|
-
if (!token) {
|
|
12
|
-
console.error('Codemagic API token required. Set CM_API_TOKEN or pass --token=...');
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
return token;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
13
|
function resolveRepoUrl() {
|
|
19
14
|
const url = exec('git remote get-url origin');
|
|
20
15
|
if (!url) {
|
|
@@ -101,6 +96,24 @@ async function pollBuildStatus(token, buildId) {
|
|
|
101
96
|
return 'timeout';
|
|
102
97
|
}
|
|
103
98
|
|
|
99
|
+
function resolveCliTeamId() {
|
|
100
|
+
const prefix = '--codemagic-team-id=';
|
|
101
|
+
for (const arg of process.argv) {
|
|
102
|
+
if (arg.startsWith(prefix)) return arg.slice(prefix.length);
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function readCiTeamId() {
|
|
108
|
+
try {
|
|
109
|
+
const content = readFileSync(join(process.cwd(), 'ci.config.yaml'), 'utf8');
|
|
110
|
+
const match = content.match(/^\s*team_id:\s*"([^"]+)"/m);
|
|
111
|
+
return match ? match[1] : undefined;
|
|
112
|
+
} catch {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
104
117
|
export async function runCodemagicSetup(options) {
|
|
105
118
|
const {
|
|
106
119
|
tokenArg = '',
|
|
@@ -112,8 +125,10 @@ export async function runCodemagicSetup(options) {
|
|
|
112
125
|
|
|
113
126
|
const token = resolveToken(tokenArg);
|
|
114
127
|
const repoUrl = resolveRepoUrl();
|
|
128
|
+
const teamId = resolveCliTeamId() || readCiTeamId();
|
|
115
129
|
|
|
116
130
|
console.log(`Repository: ${repoUrl}`);
|
|
131
|
+
if (teamId) console.log(`Team ID: ${teamId}`);
|
|
117
132
|
console.log('Checking Codemagic for existing app...');
|
|
118
133
|
|
|
119
134
|
let app = await findAppByRepo(token, repoUrl);
|
|
@@ -122,7 +137,7 @@ export async function runCodemagicSetup(options) {
|
|
|
122
137
|
console.log(`App already registered: ${app.appName || app._id}`);
|
|
123
138
|
} else {
|
|
124
139
|
console.log('App not found. Adding to Codemagic...');
|
|
125
|
-
app = await addApp(token, repoUrl);
|
|
140
|
+
app = await addApp(token, repoUrl, teamId);
|
|
126
141
|
console.log(`App added: ${app.appName || app._id}`);
|
|
127
142
|
|
|
128
143
|
console.log('Setting up GitHub webhook...');
|
|
@@ -130,12 +145,23 @@ export async function runCodemagicSetup(options) {
|
|
|
130
145
|
}
|
|
131
146
|
|
|
132
147
|
const appId = app._id;
|
|
148
|
+
const appIdWritten = writeCiAppId(process.cwd(), appId);
|
|
149
|
+
updateMcpAppId(process.cwd(), appId);
|
|
150
|
+
|
|
151
|
+
if (teamId) {
|
|
152
|
+
writeCiTeamId(process.cwd(), teamId);
|
|
153
|
+
updateMcpTeamId(process.cwd(), teamId);
|
|
154
|
+
}
|
|
133
155
|
|
|
134
156
|
if (!trigger) {
|
|
135
157
|
console.log('\nSetup complete. Use --trigger to start a build.\n');
|
|
158
|
+
if (appIdWritten) {
|
|
159
|
+
console.log('codemagic.app_id written to ci.config.yaml.');
|
|
160
|
+
} else {
|
|
161
|
+
console.log('Fill codemagic.app_id in ci.config.yaml manually.');
|
|
162
|
+
}
|
|
136
163
|
console.log('To enable GitHub Actions auto-trigger:');
|
|
137
|
-
console.log('
|
|
138
|
-
console.log(' 2. Run: npx @daemux/store-automator --github-setup');
|
|
164
|
+
console.log(' Run: npx @daemux/store-automator --github-setup');
|
|
139
165
|
return { appId, buildId: null, status: null };
|
|
140
166
|
}
|
|
141
167
|
|
package/src/github-setup.mjs
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import { exec } from './utils.mjs';
|
|
1
|
+
import { exec, resolveToken } from './utils.mjs';
|
|
2
2
|
import { execFileSync } from 'child_process';
|
|
3
3
|
|
|
4
|
-
function resolveToken(tokenArg) {
|
|
5
|
-
const token = process.env.CM_API_TOKEN || tokenArg;
|
|
6
|
-
if (!token) {
|
|
7
|
-
console.error('Codemagic API token required. Set CM_API_TOKEN or pass --token=...');
|
|
8
|
-
process.exit(1);
|
|
9
|
-
}
|
|
10
|
-
return token;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
4
|
function checkGhCli() {
|
|
14
5
|
const ghPath = exec('which gh');
|
|
15
6
|
if (!ghPath) {
|
|
@@ -47,6 +38,6 @@ export async function runGitHubSetup(options) {
|
|
|
47
38
|
setGitHubSecret('CM_API_TOKEN', token);
|
|
48
39
|
|
|
49
40
|
console.log('\nGitHub Actions setup complete.');
|
|
50
|
-
console.log('Next:
|
|
41
|
+
console.log('Next: Verify codemagic.app_id in ci.config.yaml (auto-configured during install).');
|
|
51
42
|
console.log('GitHub Actions will trigger configured Codemagic workflows on push to main.');
|
|
52
43
|
}
|
package/src/install.mjs
CHANGED
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
} from './utils.mjs';
|
|
10
10
|
import { injectEnvVars, injectStatusLine } from './settings.mjs';
|
|
11
11
|
import { promptForTokens } from './prompt.mjs';
|
|
12
|
-
import { getMcpServers, writeMcpJson } from './mcp-setup.mjs';
|
|
12
|
+
import { getMcpServers, writeMcpJson, updateMcpAppId, updateMcpTeamId } from './mcp-setup.mjs';
|
|
13
13
|
import { installClaudeMd, installCiTemplates, installFirebaseTemplates } from './templates.mjs';
|
|
14
|
+
import { findAppByRepo, addApp, normalizeRepoUrl } from './codemagic-api.mjs';
|
|
15
|
+
import { writeCiAppId, writeCiTeamId } from './ci-config.mjs';
|
|
14
16
|
|
|
15
17
|
function checkClaudeCli() {
|
|
16
18
|
const result = exec('command -v claude') || exec('which claude');
|
|
@@ -110,6 +112,46 @@ function setupGitHubActions(codemagicToken) {
|
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
|
|
115
|
+
async function setupCodemagicApp(projectDir, codemagicToken, codemagicTeamId) {
|
|
116
|
+
if (!codemagicToken) return;
|
|
117
|
+
|
|
118
|
+
let repoUrl;
|
|
119
|
+
try {
|
|
120
|
+
const raw = execSync('git remote get-url origin', {
|
|
121
|
+
encoding: 'utf8',
|
|
122
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
123
|
+
}).trim();
|
|
124
|
+
if (!raw) return;
|
|
125
|
+
repoUrl = normalizeRepoUrl(raw);
|
|
126
|
+
} catch {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
let app = await findAppByRepo(codemagicToken, repoUrl);
|
|
132
|
+
if (!app) {
|
|
133
|
+
app = await addApp(codemagicToken, repoUrl, codemagicTeamId);
|
|
134
|
+
console.log(`Codemagic app created: ${app.appName || app._id}`);
|
|
135
|
+
} else {
|
|
136
|
+
console.log(`Codemagic app found: ${app.appName || app._id}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const written = writeCiAppId(projectDir, app._id);
|
|
140
|
+
if (written) {
|
|
141
|
+
console.log(`Codemagic app_id written to ci.config.yaml`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
updateMcpAppId(projectDir, app._id);
|
|
145
|
+
|
|
146
|
+
if (codemagicTeamId) {
|
|
147
|
+
writeCiTeamId(projectDir, codemagicTeamId);
|
|
148
|
+
updateMcpTeamId(projectDir, codemagicTeamId);
|
|
149
|
+
}
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.log(`Codemagic auto-setup skipped: ${err.message || err}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
113
155
|
export async function runInstall(scope, isPostinstall = false, cliTokens = {}) {
|
|
114
156
|
checkClaudeCli();
|
|
115
157
|
|
|
@@ -141,6 +183,8 @@ export async function runInstall(scope, isPostinstall = false, cliTokens = {}) {
|
|
|
141
183
|
installCiTemplates(projectDir, packageDir);
|
|
142
184
|
installFirebaseTemplates(projectDir, packageDir);
|
|
143
185
|
|
|
186
|
+
await setupCodemagicApp(projectDir, tokens.codemagicToken, tokens.codemagicTeamId);
|
|
187
|
+
|
|
144
188
|
const scopeLabel = scope === 'user' ? 'global' : 'project';
|
|
145
189
|
console.log(`Configuring ${scopeLabel} settings...`);
|
|
146
190
|
const settingsPath = join(baseDir, 'settings.json');
|
|
@@ -157,7 +201,7 @@ export async function runInstall(scope, isPostinstall = false, cliTokens = {}) {
|
|
|
157
201
|
printSummary(scope, oldVersion, newVersion);
|
|
158
202
|
console.log('');
|
|
159
203
|
console.log('Next steps:');
|
|
160
|
-
console.log(' 1. Fill ci.config.yaml (
|
|
204
|
+
console.log(' 1. Fill ci.config.yaml (codemagic.app_id is auto-configured if token was provided)');
|
|
161
205
|
console.log(' 2. Add creds/AuthKey.p8 and creds/play-service-account.json');
|
|
162
206
|
console.log(' 3. Start Claude Code');
|
|
163
207
|
if (!ghConfigured) {
|
package/src/mcp-setup.mjs
CHANGED
|
@@ -33,10 +33,13 @@ export function getMcpServers(tokens) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (tokens.codemagicToken) {
|
|
36
|
+
const codemagicEnv = { CODEMAGIC_API_TOKEN: tokens.codemagicToken };
|
|
37
|
+
if (tokens.codemagicTeamId) codemagicEnv.CODEMAGIC_TEAM_ID = tokens.codemagicTeamId;
|
|
38
|
+
if (tokens.codemagicAppId) codemagicEnv.CODEMAGIC_APP_ID = tokens.codemagicAppId;
|
|
36
39
|
servers.codemagic = {
|
|
37
40
|
command: 'npx',
|
|
38
41
|
args: ['-y', '@daemux/codemagic-mcp@latest'],
|
|
39
|
-
env:
|
|
42
|
+
env: codemagicEnv,
|
|
40
43
|
};
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -75,6 +78,29 @@ export function writeMcpJson(projectDir, servers) {
|
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
|
|
81
|
+
function updateMcpEnvVar(projectDir, envKey, value) {
|
|
82
|
+
const mcpPath = join(projectDir, '.mcp.json');
|
|
83
|
+
if (!existsSync(mcpPath)) return false;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const data = readJson(mcpPath);
|
|
87
|
+
if (!data.mcpServers?.codemagic?.env) return false;
|
|
88
|
+
data.mcpServers.codemagic.env[envKey] = value;
|
|
89
|
+
writeJson(mcpPath, data);
|
|
90
|
+
return true;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function updateMcpAppId(projectDir, appId) {
|
|
97
|
+
return updateMcpEnvVar(projectDir, 'CODEMAGIC_APP_ID', appId);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function updateMcpTeamId(projectDir, teamId) {
|
|
101
|
+
return updateMcpEnvVar(projectDir, 'CODEMAGIC_TEAM_ID', teamId);
|
|
102
|
+
}
|
|
103
|
+
|
|
78
104
|
export function removeMcpServers(projectDir) {
|
|
79
105
|
const mcpPath = join(projectDir, '.mcp.json');
|
|
80
106
|
if (!existsSync(mcpPath)) return;
|
package/src/prompt.mjs
CHANGED
|
@@ -17,7 +17,8 @@ function allTokensProvided(cliTokens) {
|
|
|
17
17
|
cliTokens.stitchApiKey !== undefined &&
|
|
18
18
|
cliTokens.cloudflareToken !== undefined &&
|
|
19
19
|
cliTokens.cloudflareAccountId !== undefined &&
|
|
20
|
-
cliTokens.codemagicToken !== undefined
|
|
20
|
+
cliTokens.codemagicToken !== undefined &&
|
|
21
|
+
cliTokens.codemagicTeamId !== undefined
|
|
21
22
|
);
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -27,6 +28,7 @@ export async function promptForTokens(cliTokens = {}) {
|
|
|
27
28
|
cloudflareToken: cliTokens.cloudflareToken ?? '',
|
|
28
29
|
cloudflareAccountId: cliTokens.cloudflareAccountId ?? '',
|
|
29
30
|
codemagicToken: cliTokens.codemagicToken ?? '',
|
|
31
|
+
codemagicTeamId: cliTokens.codemagicTeamId ?? '',
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
if (allTokensProvided(cliTokens)) {
|
|
@@ -79,6 +81,13 @@ export async function promptForTokens(cliTokens = {}) {
|
|
|
79
81
|
);
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
if (result.codemagicToken && cliTokens.codemagicTeamId === undefined) {
|
|
85
|
+
result.codemagicTeamId = await ask(
|
|
86
|
+
rl,
|
|
87
|
+
'Codemagic Team ID (optional, from Teams page): '
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
82
91
|
return result;
|
|
83
92
|
} finally {
|
|
84
93
|
rl.close();
|
package/src/utils.mjs
CHANGED
|
@@ -44,3 +44,12 @@ export function readJson(filePath) {
|
|
|
44
44
|
export function writeJson(filePath, data) {
|
|
45
45
|
writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
export function resolveToken(tokenArg) {
|
|
49
|
+
const token = process.env.CM_API_TOKEN || tokenArg;
|
|
50
|
+
if (!token) {
|
|
51
|
+
console.error('Codemagic API token required. Set CM_API_TOKEN or pass --token=...');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
return token;
|
|
55
|
+
}
|
|
@@ -59,6 +59,7 @@ web:
|
|
|
59
59
|
# Find app_id in your Codemagic dashboard URL: codemagic.io/app/{app_id}
|
|
60
60
|
# API token is stored in .mcp.json (codemagic MCP server, set during install)
|
|
61
61
|
codemagic:
|
|
62
|
+
team_id: "" # Team ID from Codemagic Teams page
|
|
62
63
|
app_id: ""
|
|
63
64
|
workflows:
|
|
64
65
|
- ios-release
|