@geekmidas/cli 10.0.0-alpha.10 → 10.0.0-alpha.11
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/dist/{CachedStateProvider-CqPdW7CB.cjs → CachedStateProvider-BEBl2wQT.cjs} +1 -1
- package/dist/{CachedStateProvider-CqPdW7CB.cjs.map → CachedStateProvider-BEBl2wQT.cjs.map} +1 -1
- package/dist/CachedStateProvider-C-8wtlto.mjs +3 -0
- package/dist/{CachedStateProvider-DTniehMP.mjs → CachedStateProvider-Co4n5Wvs.mjs} +1 -1
- package/dist/{CachedStateProvider-DTniehMP.mjs.map → CachedStateProvider-Co4n5Wvs.mjs.map} +1 -1
- package/dist/{CachedStateProvider-BLo7zv7S.cjs → CachedStateProvider-DqhGpzsm.cjs} +1 -1
- package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BOvsgATO.cjs} +1 -1
- package/dist/{HostingerProvider-h3EbEp-Z.cjs.map → HostingerProvider-BOvsgATO.cjs.map} +1 -1
- package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-BcyFRbqV.mjs} +1 -1
- package/dist/{HostingerProvider-Cft7lEYr.mjs.map → HostingerProvider-BcyFRbqV.mjs.map} +1 -1
- package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-Bq-0C0sg.mjs} +1 -1
- package/dist/{LocalStateProvider-Bn6tS-oL.mjs.map → LocalStateProvider-Bq-0C0sg.mjs.map} +1 -1
- package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-yjXZXZDM.cjs} +1 -1
- package/dist/{LocalStateProvider-Db9SEjyH.cjs.map → LocalStateProvider-yjXZXZDM.cjs.map} +1 -1
- package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-C0xmer8U.mjs} +1 -1
- package/dist/{Route53Provider-RdpUDJQk.mjs.map → Route53Provider-C0xmer8U.mjs.map} +1 -1
- package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-CH9XH7bz.cjs} +1 -1
- package/dist/{Route53Provider-di2fMM5N.cjs.map → Route53Provider-CH9XH7bz.cjs.map} +1 -1
- package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-CXtNgPfy.cjs} +1 -1
- package/dist/{SSMStateProvider-DyX8s9HI.cjs.map → SSMStateProvider-CXtNgPfy.cjs.map} +1 -1
- package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-DOZifZfE.mjs} +1 -1
- package/dist/{SSMStateProvider-BRt2py-A.mjs.map → SSMStateProvider-DOZifZfE.mjs.map} +1 -1
- package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DXXg6FIL.mjs} +1 -1
- package/dist/{backup-provisioner-Bgj5Vi_L.mjs.map → backup-provisioner-DXXg6FIL.mjs.map} +1 -1
- package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-cE2PuCTb.cjs} +1 -1
- package/dist/{backup-provisioner-BrsHwYG0.cjs.map → backup-provisioner-cE2PuCTb.cjs.map} +1 -1
- package/dist/{bundler-BY1OmV1e.cjs → bundler-CaTGtiaO.cjs} +3 -3
- package/dist/{bundler-BY1OmV1e.cjs.map → bundler-CaTGtiaO.cjs.map} +1 -1
- package/dist/{bundler-Be8Zg4Wd.mjs → bundler-S3ek7ea-.mjs} +3 -3
- package/dist/{bundler-Be8Zg4Wd.mjs.map → bundler-S3ek7ea-.mjs.map} +1 -1
- package/dist/{config-DVVph9yz.mjs → config-B0L2tvvC.mjs} +2 -2
- package/dist/{config-DVVph9yz.mjs.map → config-B0L2tvvC.mjs.map} +1 -1
- package/dist/{config-BZ1F0WuA.cjs → config-HhDpJmLO.cjs} +2 -2
- package/dist/{config-BZ1F0WuA.cjs.map → config-HhDpJmLO.cjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +2 -2
- package/dist/{credentials-Xamqe_NJ.cjs → credentials-B2Pyh3bJ.cjs} +5 -5
- package/dist/{credentials-Xamqe_NJ.cjs.map → credentials-B2Pyh3bJ.cjs.map} +1 -1
- package/dist/{credentials-dP8vRVRv.mjs → credentials-CZrys9C5.mjs} +5 -5
- package/dist/{credentials-dP8vRVRv.mjs.map → credentials-CZrys9C5.mjs.map} +1 -1
- package/dist/dokploy-api-5cK2InBm.cjs +3 -0
- package/dist/dokploy-api-D2Ny4Jrc.mjs +3 -0
- package/dist/{dokploy-api-aTFPz7_4.mjs → dokploy-api-pdaBryoY.mjs} +1 -1
- package/dist/{dokploy-api-aTFPz7_4.mjs.map → dokploy-api-pdaBryoY.mjs.map} +1 -1
- package/dist/{dokploy-api-BsVH0y_s.cjs → dokploy-api-zqKe9lHH.cjs} +1 -1
- package/dist/{dokploy-api-BsVH0y_s.cjs.map → dokploy-api-zqKe9lHH.cjs.map} +1 -1
- package/dist/{emit-CiZS_5Ub.mjs → emit-CIlvnDvV.mjs} +1 -1
- package/dist/{emit-CiZS_5Ub.mjs.map → emit-CIlvnDvV.mjs.map} +1 -1
- package/dist/{emit-CbcRolsa.cjs → emit-CUD1BWls.cjs} +1 -1
- package/dist/{emit-CbcRolsa.cjs.map → emit-CUD1BWls.cjs.map} +1 -1
- package/dist/{encryption-C6jaU0hE.cjs → encryption-D2pL3tHH.cjs} +1 -1
- package/dist/{encryption-C6jaU0hE.cjs.map → encryption-D2pL3tHH.cjs.map} +1 -1
- package/dist/encryption-YDsXXi6w.mjs +3 -0
- package/dist/{encryption-D-abyhZx.mjs → encryption-_4zwjOAR.mjs} +1 -1
- package/dist/{encryption-D-abyhZx.mjs.map → encryption-_4zwjOAR.mjs.map} +1 -1
- package/dist/{encryption-CHzzeR8a.cjs → encryption-sQ2Oxx0d.cjs} +1 -1
- package/dist/{fullstack-secrets-C-GGohke.cjs → fullstack-secrets-D6MyHhQP.cjs} +1 -1
- package/dist/{fullstack-secrets-C-GGohke.cjs.map → fullstack-secrets-D6MyHhQP.cjs.map} +1 -1
- package/dist/{fullstack-secrets-D1o9-G5l.mjs → fullstack-secrets-METaRLS1.mjs} +1 -1
- package/dist/{fullstack-secrets-D1o9-G5l.mjs.map → fullstack-secrets-METaRLS1.mjs.map} +1 -1
- package/dist/github-BrvaPkFf.cjs +197 -0
- package/dist/github-BrvaPkFf.cjs.map +1 -0
- package/dist/github-CrpsXSfV.mjs +196 -0
- package/dist/github-CrpsXSfV.mjs.map +1 -0
- package/dist/{index-C6e-ULLx.d.mts → index-Ayxg_DQY.d.mts} +2 -2
- package/dist/{index-C6e-ULLx.d.mts.map → index-Ayxg_DQY.d.mts.map} +1 -1
- package/dist/index.cjs +109 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +108 -62
- package/dist/index.mjs.map +1 -1
- package/dist/keystore-C9rint2E.cjs +101 -0
- package/dist/keystore-C9rint2E.cjs.map +1 -0
- package/dist/keystore-TxeYM7an.mjs +83 -0
- package/dist/keystore-TxeYM7an.mjs.map +1 -0
- package/dist/{openapi-SjsgARie.cjs → openapi-DaKlTKxz.cjs} +2 -2
- package/dist/{openapi-SjsgARie.cjs.map → openapi-DaKlTKxz.cjs.map} +1 -1
- package/dist/{openapi-react-query-CmJ1xDbn.cjs → openapi-react-query-BKH334Ug.cjs} +1 -1
- package/dist/{openapi-react-query-CmJ1xDbn.cjs.map → openapi-react-query-BKH334Ug.cjs.map} +1 -1
- package/dist/{openapi-react-query-Byltvm_7.mjs → openapi-react-query-DoR5CmzQ.mjs} +1 -1
- package/dist/{openapi-react-query-Byltvm_7.mjs.map → openapi-react-query-DoR5CmzQ.mjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/{openapi-Xx0A7Wg0.mjs → openapi-y1d7Kalt.mjs} +2 -2
- package/dist/{openapi-Xx0A7Wg0.mjs.map → openapi-y1d7Kalt.mjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +3 -3
- package/dist/reconcile/public.cjs +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/reconcile/public.mjs +1 -1
- package/dist/{reconcile-CFs8C_1a.mjs → reconcile-C13ERt1U.mjs} +2 -2
- package/dist/{reconcile-CFs8C_1a.mjs.map → reconcile-C13ERt1U.mjs.map} +1 -1
- package/dist/{reconcile-D0pimNiy.cjs → reconcile-CYMhFSYy.cjs} +2 -2
- package/dist/{reconcile-D0pimNiy.cjs.map → reconcile-CYMhFSYy.cjs.map} +1 -1
- package/dist/setup-BWgMs4gg.mjs +12 -0
- package/dist/{setup-hC6hI86f.cjs → setup-DOv92pIu.cjs} +6 -6
- package/dist/{setup-hC6hI86f.cjs.map → setup-DOv92pIu.cjs.map} +1 -1
- package/dist/{setup-C8KOx8_8.mjs → setup-DQo_h_yK.mjs} +6 -6
- package/dist/{setup-C8KOx8_8.mjs.map → setup-DQo_h_yK.mjs.map} +1 -1
- package/dist/setup-lCx_DcUo.cjs +12 -0
- package/dist/{storage-Bi24WfoW.mjs → storage-B020InPW.mjs} +4 -79
- package/dist/storage-B020InPW.mjs.map +1 -0
- package/dist/{storage-BJmzYxt8.cjs → storage-CSNplaJn.cjs} +4 -85
- package/dist/storage-CSNplaJn.cjs.map +1 -0
- package/dist/{storage-CYlGwWTj.mjs → storage-DGBzMLZa.mjs} +2 -1
- package/dist/{storage-BM9hGpgv.cjs → storage-DlVol_oj.cjs} +2 -1
- package/dist/{sync-SizaChmC.cjs → sync-0ILCb-1S.cjs} +2 -2
- package/dist/{sync-SizaChmC.cjs.map → sync-0ILCb-1S.cjs.map} +1 -1
- package/dist/{sync-CmEuNZsB.mjs → sync-CzHXiR9c.mjs} +2 -2
- package/dist/{sync-CmEuNZsB.mjs.map → sync-CzHXiR9c.mjs.map} +1 -1
- package/dist/sync-DYENfOt4.cjs +4 -0
- package/dist/{sync-hOqAWHR6.mjs → sync-HAau6h_R.mjs} +1 -1
- package/dist/{types-6pkp2RRj.d.mts → types-CL7jPFM2.d.mts} +1 -1
- package/dist/{types-6pkp2RRj.d.mts.map → types-CL7jPFM2.d.mts.map} +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-C6VJQVtG.cjs → workspace-C-a3G_U0.cjs} +30 -4
- package/dist/workspace-C-a3G_U0.cjs.map +1 -0
- package/dist/workspace-DQxxs7Jk.cjs +10 -0
- package/dist/{workspace-zoqRbihZ.mjs → workspace-DaEX7FEg.mjs} +25 -5
- package/dist/workspace-DaEX7FEg.mjs.map +1 -0
- package/dist/workspace-DbI580qS.mjs +9 -0
- package/package.json +11 -11
- package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
- package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
- package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
- package/dist/encryption-CQUncu7v.mjs +0 -3
- package/dist/setup-BA8ciTPU.mjs +0 -11
- package/dist/setup-BsZvZP6f.cjs +0 -11
- package/dist/storage-BJmzYxt8.cjs.map +0 -1
- package/dist/storage-Bi24WfoW.mjs.map +0 -1
- package/dist/sync-D306yOWu.cjs +0 -4
- package/dist/workspace-BzrG_2SI.mjs +0 -8
- package/dist/workspace-C6VJQVtG.cjs.map +0 -1
- package/dist/workspace-XXtNhqJl.cjs +0 -9
- package/dist/workspace-zoqRbihZ.mjs.map +0 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import "./discover-CAlFgYec.mjs";
|
|
2
|
+
import { loadWorkspaceConfig } from "./config-B0L2tvvC.mjs";
|
|
3
|
+
import { assertDeployedStage } from "./workspace-DaEX7FEg.mjs";
|
|
4
|
+
import { getKeyPath } from "./keystore-TxeYM7an.mjs";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { AttachRolePolicyCommand, CreateOpenIDConnectProviderCommand, CreateRoleCommand, GetRoleCommand, IAMClient, ListOpenIDConnectProvidersCommand, UpdateAssumeRolePolicyCommand } from "@aws-sdk/client-iam";
|
|
8
|
+
|
|
9
|
+
//#region src/deploy/github.ts
|
|
10
|
+
const logger = console;
|
|
11
|
+
const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
|
|
12
|
+
const AUDIENCE = "sts.amazonaws.com";
|
|
13
|
+
/**
|
|
14
|
+
* What SST needs to create a stack is most of AWS, so this is the default —
|
|
15
|
+
* said out loud in the output, and replaceable with `--policy-arn`.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_POLICY_ARN = "arn:aws:iam::aws:policy/AdministratorAccess";
|
|
18
|
+
const defaultGh = (args, input) => execFileSync("gh", args, {
|
|
19
|
+
encoding: "utf-8",
|
|
20
|
+
...input === void 0 ? {} : {
|
|
21
|
+
input,
|
|
22
|
+
stdio: [
|
|
23
|
+
"pipe",
|
|
24
|
+
"pipe",
|
|
25
|
+
"pipe"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}).trim();
|
|
29
|
+
/** The role a stage deploys as: `<project>-github-<stage>`, within IAM's 64. */
|
|
30
|
+
function roleName(project, stage) {
|
|
31
|
+
return `${project}-github-${stage}`.toLowerCase().replace(/[^a-z0-9+=,.@_-]/g, "-").slice(0, 64);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Who may assume the role: a workflow job running in this repository's
|
|
35
|
+
* `<stage>` environment, and nothing else — not another branch's job, not
|
|
36
|
+
* another environment's. That is what keeps a staging deploy from using the
|
|
37
|
+
* production role.
|
|
38
|
+
*/
|
|
39
|
+
function trustPolicy(providerArn, repo, stage) {
|
|
40
|
+
return JSON.stringify({
|
|
41
|
+
Version: "2012-10-17",
|
|
42
|
+
Statement: [{
|
|
43
|
+
Effect: "Allow",
|
|
44
|
+
Principal: { Federated: providerArn },
|
|
45
|
+
Action: "sts:AssumeRoleWithWebIdentity",
|
|
46
|
+
Condition: { StringEquals: {
|
|
47
|
+
[`${GITHUB_OIDC_HOST}:aud`]: AUDIENCE,
|
|
48
|
+
[`${GITHUB_OIDC_HOST}:sub`]: `repo:${repo}:environment:${stage}`
|
|
49
|
+
} }
|
|
50
|
+
}]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** GitHub's OIDC provider in this account, created if it is not there. */
|
|
54
|
+
async function ensureOidcProvider(iam) {
|
|
55
|
+
const { OpenIDConnectProviderList = [] } = await iam.send(new ListOpenIDConnectProvidersCommand({}));
|
|
56
|
+
const existing = OpenIDConnectProviderList.find((p) => p.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`))?.Arn;
|
|
57
|
+
if (existing) return existing;
|
|
58
|
+
const created = await iam.send(new CreateOpenIDConnectProviderCommand({
|
|
59
|
+
Url: `https://${GITHUB_OIDC_HOST}`,
|
|
60
|
+
ClientIDList: [AUDIENCE]
|
|
61
|
+
}));
|
|
62
|
+
return created.OpenIDConnectProviderArn;
|
|
63
|
+
}
|
|
64
|
+
/** The deploy role, created or brought back to this trust and policy. */
|
|
65
|
+
async function ensureRole(iam, name, trust, policyArn) {
|
|
66
|
+
let arn;
|
|
67
|
+
try {
|
|
68
|
+
const { Role } = await iam.send(new GetRoleCommand({ RoleName: name }));
|
|
69
|
+
await iam.send(new UpdateAssumeRolePolicyCommand({
|
|
70
|
+
RoleName: name,
|
|
71
|
+
PolicyDocument: trust
|
|
72
|
+
}));
|
|
73
|
+
arn = Role.Arn;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error.name !== "NoSuchEntityException") throw error;
|
|
76
|
+
const { Role } = await iam.send(new CreateRoleCommand({
|
|
77
|
+
RoleName: name,
|
|
78
|
+
AssumeRolePolicyDocument: trust,
|
|
79
|
+
Description: "Deploys from GitHub Actions (gkm deploy:github)",
|
|
80
|
+
MaxSessionDuration: 3600 * 2
|
|
81
|
+
}));
|
|
82
|
+
arn = Role.Arn;
|
|
83
|
+
}
|
|
84
|
+
await iam.send(new AttachRolePolicyCommand({
|
|
85
|
+
RoleName: name,
|
|
86
|
+
PolicyArn: policyArn
|
|
87
|
+
}));
|
|
88
|
+
return arn;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* An IAM client for the stage's account.
|
|
92
|
+
*
|
|
93
|
+
* `fromIni` for a named profile, deliberately: it resolves exactly that
|
|
94
|
+
* profile — keys, assume-role, `credential_process` or SSO, whichever
|
|
95
|
+
* ~/.aws/config says — and never falls back to AWS_* in the environment. The
|
|
96
|
+
* provider chain checks the environment first, so exported staging keys would
|
|
97
|
+
* quietly win over `--profile prod` and the production role would land in the
|
|
98
|
+
* staging account.
|
|
99
|
+
*/
|
|
100
|
+
async function iamFor(profile, endpoint) {
|
|
101
|
+
const config = { region: "us-east-1" };
|
|
102
|
+
if (profile) {
|
|
103
|
+
const { fromIni } = await import("@aws-sdk/credential-providers");
|
|
104
|
+
config.credentials = fromIni({ profile });
|
|
105
|
+
}
|
|
106
|
+
if (endpoint) {
|
|
107
|
+
config.endpoint = endpoint;
|
|
108
|
+
config.credentials = {
|
|
109
|
+
accessKeyId: "test",
|
|
110
|
+
secretAccessKey: "test"
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return new IAMClient(config);
|
|
114
|
+
}
|
|
115
|
+
async function deployGithubCommand(options, deps = {}) {
|
|
116
|
+
const gh = deps.gh ?? defaultGh;
|
|
117
|
+
const { workspace } = await loadWorkspaceConfig(deps.cwd);
|
|
118
|
+
assertDeployedStage(workspace.stages, options.stage);
|
|
119
|
+
const repo = options.repo ?? gh([
|
|
120
|
+
"repo",
|
|
121
|
+
"view",
|
|
122
|
+
"--json",
|
|
123
|
+
"nameWithOwner",
|
|
124
|
+
"-q",
|
|
125
|
+
".nameWithOwner"
|
|
126
|
+
]);
|
|
127
|
+
const role = roleName(workspace.name, options.stage);
|
|
128
|
+
const policyArn = options.policyArn ?? DEFAULT_POLICY_ARN;
|
|
129
|
+
const keyPath = getKeyPath(options.stage, workspace.name);
|
|
130
|
+
const hasKey = existsSync(keyPath);
|
|
131
|
+
logger.log(`\n🔐 GitHub → AWS for stage "${options.stage}"\n`);
|
|
132
|
+
logger.log(` Repository: ${repo}`);
|
|
133
|
+
logger.log(` AWS profile: ${options.profile ?? "(default credentials)"}`);
|
|
134
|
+
logger.log(` Role: ${role}`);
|
|
135
|
+
logger.log(` Policy: ${policyArn}${options.policyArn ? "" : " (default; --policy-arn to narrow)"}`);
|
|
136
|
+
logger.log(` Trusted by: repo:${repo}:environment:${options.stage} only`);
|
|
137
|
+
logger.log(` Secrets key: ${hasKey ? keyPath : `none at ${keyPath} — run gkm secrets:init --stage ${options.stage} first`}`);
|
|
138
|
+
if (options.dryRun) {
|
|
139
|
+
logger.log("\n --dry-run: nothing changed.\n");
|
|
140
|
+
return { repo };
|
|
141
|
+
}
|
|
142
|
+
const iam = deps.iam ?? await iamFor(options.profile);
|
|
143
|
+
const providerArn = await ensureOidcProvider(iam).catch((error) => {
|
|
144
|
+
if (/SSO session/i.test(String(error?.message)) && options.profile) throw new SsoSessionExpired(options.profile);
|
|
145
|
+
throw error;
|
|
146
|
+
});
|
|
147
|
+
const roleArn = await ensureRole(iam, role, trustPolicy(providerArn, repo, options.stage), policyArn);
|
|
148
|
+
logger.log(`\n ✓ AWS: ${roleArn}`);
|
|
149
|
+
gh([
|
|
150
|
+
"api",
|
|
151
|
+
"--method",
|
|
152
|
+
"PUT",
|
|
153
|
+
`repos/${repo}/environments/${options.stage}`
|
|
154
|
+
]);
|
|
155
|
+
gh([
|
|
156
|
+
"variable",
|
|
157
|
+
"set",
|
|
158
|
+
"AWS_ROLE_ARN",
|
|
159
|
+
"--env",
|
|
160
|
+
options.stage,
|
|
161
|
+
"--repo",
|
|
162
|
+
repo,
|
|
163
|
+
"--body",
|
|
164
|
+
roleArn
|
|
165
|
+
]);
|
|
166
|
+
logger.log(` ✓ GitHub: environment "${options.stage}", AWS_ROLE_ARN`);
|
|
167
|
+
if (hasKey) {
|
|
168
|
+
gh([
|
|
169
|
+
"secret",
|
|
170
|
+
"set",
|
|
171
|
+
"GKM_SECRETS_KEY",
|
|
172
|
+
"--env",
|
|
173
|
+
options.stage,
|
|
174
|
+
"--repo",
|
|
175
|
+
repo
|
|
176
|
+
], readFileSync(keyPath, "utf-8").trim());
|
|
177
|
+
logger.log(" ✓ GitHub: GKM_SECRETS_KEY");
|
|
178
|
+
} else logger.log(` ⚠ No secrets key for "${options.stage}"; run gkm secrets:init --stage ${options.stage}, then this again.`);
|
|
179
|
+
logger.log(`\n Protect it: add required reviewers to the "${options.stage}" environment in the repository settings.\n`);
|
|
180
|
+
return {
|
|
181
|
+
roleArn,
|
|
182
|
+
repo
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** The profile's SSO login has lapsed; the fix is one command away. */
|
|
186
|
+
var SsoSessionExpired = class extends Error {
|
|
187
|
+
constructor(profile) {
|
|
188
|
+
super(`The SSO session for profile "${profile}" has expired or is invalid. Run: aws sso login --profile ${profile}`);
|
|
189
|
+
this.profile = profile;
|
|
190
|
+
this.name = "SsoSessionExpired";
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
//#endregion
|
|
195
|
+
export { deployGithubCommand };
|
|
196
|
+
//# sourceMappingURL=github-CrpsXSfV.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-CrpsXSfV.mjs","names":["defaultGh: Gh","project: string","stage: string","providerArn: string","repo: string","iam: IAMClient","name: string","trust: string","policyArn: string","arn: string","profile?: string","endpoint?: string","config: IAMClientConfig","options: DeployGithubOptions","deps: { iam?: IAMClient; gh?: Gh; cwd?: string }","profile: string"],"sources":["../src/deploy/github.ts"],"sourcesContent":["/**\n * `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.\n *\n * A stage usually lives in its own AWS account — staging in one, production in\n * another — so this runs once per stage, with that account's profile:\n *\n * gkm deploy:github --stage staging --profile acme-dev\n * gkm deploy:github --stage prod --profile acme-prod\n *\n * In the stage's account it makes sure GitHub's OIDC provider exists, and a\n * role that only this repository's `<stage>` environment can assume. On\n * GitHub it creates that environment and gives it what the generated deploy\n * workflow reads: `AWS_ROLE_ARN`, and the stage's secrets key as\n * `GKM_SECRETS_KEY`. Re-running it converges rather than duplicating.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport {\n\tAttachRolePolicyCommand,\n\tCreateOpenIDConnectProviderCommand,\n\tCreateRoleCommand,\n\tGetRoleCommand,\n\tIAMClient,\n\ttype IAMClientConfig,\n\tListOpenIDConnectProvidersCommand,\n\tUpdateAssumeRolePolicyCommand,\n} from '@aws-sdk/client-iam';\nimport { loadWorkspaceConfig } from '../config.js';\nimport { getKeyPath } from '../secrets/keystore.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\n\nconst logger = console;\n\nconst GITHUB_OIDC_HOST = 'token.actions.githubusercontent.com';\nconst AUDIENCE = 'sts.amazonaws.com';\n\n/**\n * What SST needs to create a stack is most of AWS, so this is the default —\n * said out loud in the output, and replaceable with `--policy-arn`.\n */\nexport const DEFAULT_POLICY_ARN = 'arn:aws:iam::aws:policy/AdministratorAccess';\n\nexport interface DeployGithubOptions {\n\tstage: string;\n\t/** The AWS profile for the stage's account. */\n\tprofile?: string;\n\t/** `owner/name`; defaults to the repository `gh` sees here. */\n\trepo?: string;\n\t/** The policy the deploy role gets. */\n\tpolicyArn?: string;\n\tdryRun?: boolean;\n}\n\n/** Runs `gh` with the given arguments and optional stdin, returning stdout. */\nexport type Gh = (args: string[], input?: string) => string;\n\nconst defaultGh: Gh = (args, input) =>\n\texecFileSync('gh', args, {\n\t\tencoding: 'utf-8',\n\t\t...(input === undefined\n\t\t\t? {}\n\t\t\t: { input, stdio: ['pipe', 'pipe', 'pipe'] as const }),\n\t}).trim();\n\n/** The role a stage deploys as: `<project>-github-<stage>`, within IAM's 64. */\nexport function roleName(project: string, stage: string): string {\n\treturn `${project}-github-${stage}`\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9+=,.@_-]/g, '-')\n\t\t.slice(0, 64);\n}\n\n/**\n * Who may assume the role: a workflow job running in this repository's\n * `<stage>` environment, and nothing else — not another branch's job, not\n * another environment's. That is what keeps a staging deploy from using the\n * production role.\n */\nexport function trustPolicy(\n\tproviderArn: string,\n\trepo: string,\n\tstage: string,\n): string {\n\treturn JSON.stringify({\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tEffect: 'Allow',\n\t\t\t\tPrincipal: { Federated: providerArn },\n\t\t\t\tAction: 'sts:AssumeRoleWithWebIdentity',\n\t\t\t\tCondition: {\n\t\t\t\t\tStringEquals: {\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:aud`]: AUDIENCE,\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:sub`]: `repo:${repo}:environment:${stage}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t});\n}\n\n/** GitHub's OIDC provider in this account, created if it is not there. */\nexport async function ensureOidcProvider(iam: IAMClient): Promise<string> {\n\tconst { OpenIDConnectProviderList = [] } = await iam.send(\n\t\tnew ListOpenIDConnectProvidersCommand({}),\n\t);\n\tconst existing = OpenIDConnectProviderList.find((p) =>\n\t\tp.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`),\n\t)?.Arn;\n\tif (existing) return existing;\n\n\tconst created = await iam.send(\n\t\tnew CreateOpenIDConnectProviderCommand({\n\t\t\tUrl: `https://${GITHUB_OIDC_HOST}`,\n\t\t\tClientIDList: [AUDIENCE],\n\t\t}),\n\t);\n\treturn created.OpenIDConnectProviderArn!;\n}\n\n/** The deploy role, created or brought back to this trust and policy. */\nexport async function ensureRole(\n\tiam: IAMClient,\n\tname: string,\n\ttrust: string,\n\tpolicyArn: string,\n): Promise<string> {\n\tlet arn: string;\n\ttry {\n\t\tconst { Role } = await iam.send(new GetRoleCommand({ RoleName: name }));\n\t\tawait iam.send(\n\t\t\tnew UpdateAssumeRolePolicyCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tPolicyDocument: trust,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t} catch (error) {\n\t\tif ((error as { name?: string }).name !== 'NoSuchEntityException') {\n\t\t\tthrow error;\n\t\t}\n\t\tconst { Role } = await iam.send(\n\t\t\tnew CreateRoleCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tAssumeRolePolicyDocument: trust,\n\t\t\t\tDescription: 'Deploys from GitHub Actions (gkm deploy:github)',\n\t\t\t\t// SST deploys can run long; the default hour is tight.\n\t\t\t\tMaxSessionDuration: 3600 * 2,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t}\n\n\t// Attaching an attached policy is a no-op, so this converges too.\n\tawait iam.send(\n\t\tnew AttachRolePolicyCommand({ RoleName: name, PolicyArn: policyArn }),\n\t);\n\treturn arn;\n}\n\n/**\n * An IAM client for the stage's account.\n *\n * `fromIni` for a named profile, deliberately: it resolves exactly that\n * profile — keys, assume-role, `credential_process` or SSO, whichever\n * ~/.aws/config says — and never falls back to AWS_* in the environment. The\n * provider chain checks the environment first, so exported staging keys would\n * quietly win over `--profile prod` and the production role would land in the\n * staging account.\n */\nexport async function iamFor(\n\tprofile?: string,\n\tendpoint?: string,\n): Promise<IAMClient> {\n\tconst config: IAMClientConfig = { region: 'us-east-1' };\n\tif (profile) {\n\t\tconst { fromIni } = await import('@aws-sdk/credential-providers');\n\t\tconfig.credentials = fromIni({ profile });\n\t}\n\tif (endpoint) {\n\t\tconfig.endpoint = endpoint;\n\t\tconfig.credentials = { accessKeyId: 'test', secretAccessKey: 'test' };\n\t}\n\treturn new IAMClient(config);\n}\n\nexport async function deployGithubCommand(\n\toptions: DeployGithubOptions,\n\tdeps: { iam?: IAMClient; gh?: Gh; cwd?: string } = {},\n): Promise<{ roleArn?: string; repo: string }> {\n\tconst gh = deps.gh ?? defaultGh;\n\tconst { workspace } = await loadWorkspaceConfig(deps.cwd);\n\tassertDeployedStage(workspace.stages, options.stage);\n\n\tconst repo =\n\t\toptions.repo ??\n\t\tgh(['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner']);\n\tconst role = roleName(workspace.name, options.stage);\n\tconst policyArn = options.policyArn ?? DEFAULT_POLICY_ARN;\n\tconst keyPath = getKeyPath(options.stage, workspace.name);\n\tconst hasKey = existsSync(keyPath);\n\n\tlogger.log(`\\n🔐 GitHub → AWS for stage \"${options.stage}\"\\n`);\n\tlogger.log(` Repository: ${repo}`);\n\tlogger.log(` AWS profile: ${options.profile ?? '(default credentials)'}`);\n\tlogger.log(` Role: ${role}`);\n\tlogger.log(\n\t\t` Policy: ${policyArn}${options.policyArn ? '' : ' (default; --policy-arn to narrow)'}`,\n\t);\n\tlogger.log(` Trusted by: repo:${repo}:environment:${options.stage} only`);\n\tlogger.log(\n\t\t` Secrets key: ${hasKey ? keyPath : `none at ${keyPath} — run gkm secrets:init --stage ${options.stage} first`}`,\n\t);\n\n\tif (options.dryRun) {\n\t\tlogger.log('\\n --dry-run: nothing changed.\\n');\n\t\treturn { repo };\n\t}\n\n\tconst iam = deps.iam ?? (await iamFor(options.profile));\n\tconst providerArn = await ensureOidcProvider(iam).catch((error) => {\n\t\t// The first AWS call is where an expired SSO login surfaces; the SDK's\n\t\t// message does not say which profile, and this command knows.\n\t\tif (/SSO session/i.test(String(error?.message)) && options.profile) {\n\t\t\tthrow new SsoSessionExpired(options.profile);\n\t\t}\n\t\tthrow error;\n\t});\n\tconst roleArn = await ensureRole(\n\t\tiam,\n\t\trole,\n\t\ttrustPolicy(providerArn, repo, options.stage),\n\t\tpolicyArn,\n\t);\n\tlogger.log(`\\n ✓ AWS: ${roleArn}`);\n\n\t// The environment the generated deploy workflow runs the stage in.\n\tgh(['api', '--method', 'PUT', `repos/${repo}/environments/${options.stage}`]);\n\tgh([\n\t\t'variable',\n\t\t'set',\n\t\t'AWS_ROLE_ARN',\n\t\t'--env',\n\t\toptions.stage,\n\t\t'--repo',\n\t\trepo,\n\t\t'--body',\n\t\troleArn,\n\t]);\n\tlogger.log(` ✓ GitHub: environment \"${options.stage}\", AWS_ROLE_ARN`);\n\n\tif (hasKey) {\n\t\t// Through stdin, so the key is never an argument a process list shows.\n\t\tgh(\n\t\t\t[\n\t\t\t\t'secret',\n\t\t\t\t'set',\n\t\t\t\t'GKM_SECRETS_KEY',\n\t\t\t\t'--env',\n\t\t\t\toptions.stage,\n\t\t\t\t'--repo',\n\t\t\t\trepo,\n\t\t\t],\n\t\t\treadFileSync(keyPath, 'utf-8').trim(),\n\t\t);\n\t\tlogger.log(' ✓ GitHub: GKM_SECRETS_KEY');\n\t} else {\n\t\tlogger.log(\n\t\t\t` ⚠ No secrets key for \"${options.stage}\"; run gkm secrets:init --stage ${options.stage}, then this again.`,\n\t\t);\n\t}\n\n\tlogger.log(\n\t\t`\\n Protect it: add required reviewers to the \"${options.stage}\" environment in the repository settings.\\n`,\n\t);\n\treturn { roleArn, repo };\n}\n\n/** The profile's SSO login has lapsed; the fix is one command away. */\nexport class SsoSessionExpired extends Error {\n\tconstructor(readonly profile: string) {\n\t\tsuper(\n\t\t\t`The SSO session for profile \"${profile}\" has expired or is invalid. Run: aws sso login --profile ${profile}`,\n\t\t);\n\t\tthis.name = 'SsoSessionExpired';\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppsRecord, Framework, GkmConfig, InferredWorkspaceConfig, LoadedConfig, NormalizedWorkspace, Routes, WorkspaceConfig, WorkspaceInput } from "./types-
|
|
1
|
+
import { AppsRecord, Framework, GkmConfig, InferredWorkspaceConfig, LoadedConfig, NormalizedWorkspace, Routes, WorkspaceConfig, WorkspaceInput } from "./types-CL7jPFM2.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/workspace/publicEnv.d.ts
|
|
4
4
|
|
|
@@ -172,4 +172,4 @@ declare function getEndpointForStage(dokployConfig: {
|
|
|
172
172
|
//# sourceMappingURL=index.d.ts.map
|
|
173
173
|
//#endregion
|
|
174
174
|
export { PUBLIC_ENV_PREFIXES, allConstructGlobs, appConstructGlobs, constructPatterns, defineWorkspace, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getEndpointForStage, getPublicEnvPrefix, normalizeWorkspace, processConfig, stripPublicPrefix, workspaceConstructGlobs, wrapSingleAppAsWorkspace };
|
|
175
|
-
//# sourceMappingURL=index-
|
|
175
|
+
//# sourceMappingURL=index-Ayxg_DQY.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-Ayxg_DQY.d.mts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"sourcesContent":[],"mappings":";;;;;;AASA;AAoBA;AAoBA;;;cAxCa;AC2Hb;;;;;;;AAE0B;AA8B1B;;;;AAGsB;AA+CtB;AAAwC,iBDzLxB,kBAAA,CCyLwB,SAAA,CAAA,EDzLO,SCyLP,CAAA,EAAA,MAAA;;;AAGlB;AAsEtB;AAA6B,iBD9Ob,iBAAA,CC8Oa,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;;;;;;;;AA3J7B;;;;;;;AAE0B;AA8B1B;;;;AAGsB;AA+CtB;;;;AAGsB;AAsEtB;;;;;AAGe;AA6Bf;AAmBA;AAwBA;AAaA;AAiBA;;;;AAGY;AAmCZ;AAmCA;;;;AAIS;AAgDO,iBAjYA,eAmYqB,CAAA,oBAnYe,UAmYT,CAAA,CAAA,MAAA,EAlYlC,cAkYkC,CAlYnB,KAkYmB,CAAA,CAAA,EAjYxC,uBAiYwC,CAjYhB,KAiYgB,CAAA;;;;iBAnW3B,kBAAA,SACP,+BAEN;;;;;iBA+Ca,wBAAA,SACP,yBAEN;;;;;iBAsEa,aAAA,SACP,YAAY,+BAElB;;;;;;;iBA6Ba,uBAAA,YACJ;;;;;;;;;;;;iBAkBI,iBAAA,YACJ;;;;;;;iBAuBI,iBAAA,YAA6B;;iBAa7B,iBAAA,SAA0B;;;;;iBAiB1B,eAAA,YACJ,uCAET;;;;;iBAmCa,gBAAA,YAA4B;;;;;;;;;;iBAmC5B,oBAAA,YACJ,2DAGT;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDa,mBAAA;;cAEqB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
3
3
|
const require_discover = require('./discover-DTmFeloL.cjs');
|
|
4
|
-
const require_config = require('./config-
|
|
5
|
-
const require_workspace = require('./workspace-
|
|
4
|
+
const require_config = require('./config-HhDpJmLO.cjs');
|
|
5
|
+
const require_workspace = require('./workspace-C-a3G_U0.cjs');
|
|
6
6
|
const require_credentials = require('./credentials-BapzjyV5.cjs');
|
|
7
|
-
const require_credentials$1 = require('./credentials-
|
|
7
|
+
const require_credentials$1 = require('./credentials-B2Pyh3bJ.cjs');
|
|
8
8
|
const require_generator = require('./generator-CNzBw7g5.cjs');
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
require('./
|
|
18
|
-
|
|
9
|
+
const require_keystore = require('./keystore-C9rint2E.cjs');
|
|
10
|
+
const require_storage = require('./storage-CSNplaJn.cjs');
|
|
11
|
+
const require_openapi = require('./openapi-DaKlTKxz.cjs');
|
|
12
|
+
const require_emit = require('./emit-CUD1BWls.cjs');
|
|
13
|
+
const require_dokploy_api = require('./dokploy-api-zqKe9lHH.cjs');
|
|
14
|
+
const require_encryption = require('./encryption-D2pL3tHH.cjs');
|
|
15
|
+
const require_CachedStateProvider = require('./CachedStateProvider-BEBl2wQT.cjs');
|
|
16
|
+
const require_fullstack_secrets = require('./fullstack-secrets-D6MyHhQP.cjs');
|
|
17
|
+
const require_openapi_react_query = require('./openapi-react-query-BKH334Ug.cjs');
|
|
18
|
+
require('./sync-0ILCb-1S.cjs');
|
|
19
|
+
const require_setup = require('./setup-DOv92pIu.cjs');
|
|
19
20
|
const node_fs = require_chunk.__toESM(require("node:fs"));
|
|
20
21
|
const node_path = require_chunk.__toESM(require("node:path"));
|
|
21
22
|
const __geekmidas_manifest = require_chunk.__toESM(require("@geekmidas/manifest"));
|
|
@@ -43,7 +44,7 @@ const prompts = require_chunk.__toESM(require("prompts"));
|
|
|
43
44
|
|
|
44
45
|
//#region package.json
|
|
45
46
|
var name = "@geekmidas/cli";
|
|
46
|
-
var version = "10.0.0-alpha.
|
|
47
|
+
var version = "10.0.0-alpha.11";
|
|
47
48
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
48
49
|
var private$1 = false;
|
|
49
50
|
var type = "module";
|
|
@@ -188,7 +189,7 @@ const logger$11 = console;
|
|
|
188
189
|
* Validate Dokploy token by making a test API call
|
|
189
190
|
*/
|
|
190
191
|
async function validateDokployToken(endpoint, token) {
|
|
191
|
-
const { DokployApi: DokployApi$1 } = await Promise.resolve().then(() => require("./dokploy-api-
|
|
192
|
+
const { DokployApi: DokployApi$1 } = await Promise.resolve().then(() => require("./dokploy-api-5cK2InBm.cjs"));
|
|
192
193
|
const api = new DokployApi$1({
|
|
193
194
|
baseUrl: endpoint,
|
|
194
195
|
token
|
|
@@ -2639,7 +2640,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
|
|
|
2639
2640
|
let masterKey;
|
|
2640
2641
|
if (context.production?.bundle && !skipBundle) {
|
|
2641
2642
|
logger$7.log(`\n📦 Bundling production server...`);
|
|
2642
|
-
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-
|
|
2643
|
+
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-CaTGtiaO.cjs"));
|
|
2643
2644
|
const allConstructs = [
|
|
2644
2645
|
...endpoints.map((e) => e.construct),
|
|
2645
2646
|
...functions.map((f) => f.construct),
|
|
@@ -3592,11 +3593,11 @@ async function createDnsProvider(options) {
|
|
|
3592
3593
|
if (isDnsProvider(config.provider)) return config.provider;
|
|
3593
3594
|
const provider = config.provider;
|
|
3594
3595
|
if (provider === "hostinger") {
|
|
3595
|
-
const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-
|
|
3596
|
+
const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-BOvsgATO.cjs"));
|
|
3596
3597
|
return new HostingerProvider();
|
|
3597
3598
|
}
|
|
3598
3599
|
if (provider === "route53") {
|
|
3599
|
-
const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-
|
|
3600
|
+
const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-CH9XH7bz.cjs"));
|
|
3600
3601
|
const route53Config = config;
|
|
3601
3602
|
return new Route53Provider({
|
|
3602
3603
|
region: route53Config.region,
|
|
@@ -5923,20 +5924,20 @@ function isStateProvider(value) {
|
|
|
5923
5924
|
async function createStateProvider(options) {
|
|
5924
5925
|
const { config, workspaceRoot, workspaceName } = options;
|
|
5925
5926
|
if (!config) {
|
|
5926
|
-
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-
|
|
5927
|
+
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-yjXZXZDM.cjs"));
|
|
5927
5928
|
return new LocalStateProvider(workspaceRoot);
|
|
5928
5929
|
}
|
|
5929
5930
|
if (isStateProvider(config.provider)) return config.provider;
|
|
5930
5931
|
const provider = config.provider;
|
|
5931
5932
|
if (provider === "local") {
|
|
5932
|
-
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-
|
|
5933
|
+
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-yjXZXZDM.cjs"));
|
|
5933
5934
|
return new LocalStateProvider(workspaceRoot);
|
|
5934
5935
|
}
|
|
5935
5936
|
if (provider === "ssm") {
|
|
5936
5937
|
if (!workspaceName) throw new Error("Workspace name is required for SSM state provider. Set \"name\" in gkm.config.ts.");
|
|
5937
|
-
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-
|
|
5938
|
-
const { SSMStateProvider } = await Promise.resolve().then(() => require("./SSMStateProvider-
|
|
5939
|
-
const { CachedStateProvider: CachedStateProvider$1 } = await Promise.resolve().then(() => require("./CachedStateProvider-
|
|
5938
|
+
const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-yjXZXZDM.cjs"));
|
|
5939
|
+
const { SSMStateProvider } = await Promise.resolve().then(() => require("./SSMStateProvider-CXtNgPfy.cjs"));
|
|
5940
|
+
const { CachedStateProvider: CachedStateProvider$1 } = await Promise.resolve().then(() => require("./CachedStateProvider-DqhGpzsm.cjs"));
|
|
5940
5941
|
const ssmConfig = config;
|
|
5941
5942
|
const local = new LocalStateProvider(workspaceRoot);
|
|
5942
5943
|
const ssm = SSMStateProvider.create({
|
|
@@ -6812,7 +6813,7 @@ async function workspaceDeployCommand(configured, options) {
|
|
|
6812
6813
|
const backupCluster = Object.values(declaredClusters)[0];
|
|
6813
6814
|
if (workspace.deploy?.backups && backupCluster) {
|
|
6814
6815
|
logger$3.log("\n💾 Provisioning backup destination...");
|
|
6815
|
-
const { provisionBackupDestination } = await Promise.resolve().then(() => require("./backup-provisioner-
|
|
6816
|
+
const { provisionBackupDestination } = await Promise.resolve().then(() => require("./backup-provisioner-cE2PuCTb.cjs"));
|
|
6816
6817
|
const backupState = await provisionBackupDestination({
|
|
6817
6818
|
api,
|
|
6818
6819
|
projectId: project.projectId,
|
|
@@ -8026,26 +8027,26 @@ const CLI_VERSION = `~${pkg.version}`;
|
|
|
8026
8027
|
* Run: pnpm --filter @geekmidas/cli sync-versions
|
|
8027
8028
|
*/
|
|
8028
8029
|
const GEEKMIDAS_VERSIONS = {
|
|
8029
|
-
"@geekmidas/audit": "~10.0.0-alpha.
|
|
8030
|
-
"@geekmidas/auth": "~10.0.0-alpha.
|
|
8031
|
-
"@geekmidas/cache": "~10.0.0-alpha.
|
|
8032
|
-
"@geekmidas/client": "~10.0.0-alpha.
|
|
8033
|
-
"@geekmidas/cloud": "~10.0.0-alpha.
|
|
8034
|
-
"@geekmidas/constructs": "~10.0.0-alpha.
|
|
8035
|
-
"@geekmidas/db": "~10.0.0-alpha.
|
|
8036
|
-
"@geekmidas/emailkit": "~10.0.0-alpha.
|
|
8037
|
-
"@geekmidas/envkit": "~10.0.0-alpha.
|
|
8038
|
-
"@geekmidas/errors": "~10.0.0-alpha.
|
|
8039
|
-
"@geekmidas/events": "~10.0.0-alpha.
|
|
8040
|
-
"@geekmidas/logger": "~10.0.0-alpha.
|
|
8041
|
-
"@geekmidas/manifest": "~10.0.0-alpha.
|
|
8042
|
-
"@geekmidas/rate-limit": "~10.0.0-alpha.
|
|
8043
|
-
"@geekmidas/schema": "~10.0.0-alpha.
|
|
8044
|
-
"@geekmidas/services": "~10.0.0-alpha.
|
|
8045
|
-
"@geekmidas/storage": "~10.0.0-alpha.
|
|
8046
|
-
"@geekmidas/studio": "~10.0.0-alpha.
|
|
8047
|
-
"@geekmidas/telescope": "~10.0.0-alpha.
|
|
8048
|
-
"@geekmidas/testkit": "~10.0.0-alpha.
|
|
8030
|
+
"@geekmidas/audit": "~10.0.0-alpha.11",
|
|
8031
|
+
"@geekmidas/auth": "~10.0.0-alpha.11",
|
|
8032
|
+
"@geekmidas/cache": "~10.0.0-alpha.11",
|
|
8033
|
+
"@geekmidas/client": "~10.0.0-alpha.11",
|
|
8034
|
+
"@geekmidas/cloud": "~10.0.0-alpha.11",
|
|
8035
|
+
"@geekmidas/constructs": "~10.0.0-alpha.11",
|
|
8036
|
+
"@geekmidas/db": "~10.0.0-alpha.11",
|
|
8037
|
+
"@geekmidas/emailkit": "~10.0.0-alpha.11",
|
|
8038
|
+
"@geekmidas/envkit": "~10.0.0-alpha.11",
|
|
8039
|
+
"@geekmidas/errors": "~10.0.0-alpha.11",
|
|
8040
|
+
"@geekmidas/events": "~10.0.0-alpha.11",
|
|
8041
|
+
"@geekmidas/logger": "~10.0.0-alpha.11",
|
|
8042
|
+
"@geekmidas/manifest": "~10.0.0-alpha.11",
|
|
8043
|
+
"@geekmidas/rate-limit": "~10.0.0-alpha.11",
|
|
8044
|
+
"@geekmidas/schema": "~10.0.0-alpha.11",
|
|
8045
|
+
"@geekmidas/services": "~10.0.0-alpha.11",
|
|
8046
|
+
"@geekmidas/storage": "~10.0.0-alpha.11",
|
|
8047
|
+
"@geekmidas/studio": "~10.0.0-alpha.11",
|
|
8048
|
+
"@geekmidas/telescope": "~10.0.0-alpha.11",
|
|
8049
|
+
"@geekmidas/testkit": "~10.0.0-alpha.11",
|
|
8049
8050
|
"@geekmidas/cli": CLI_VERSION
|
|
8050
8051
|
};
|
|
8051
8052
|
|
|
@@ -9842,7 +9843,7 @@ function deployPackage(options) {
|
|
|
9842
9843
|
}
|
|
9843
9844
|
function generateDeployFiles(options) {
|
|
9844
9845
|
if (options.deployTarget !== "sst") return [];
|
|
9845
|
-
if (!options.region) throw new
|
|
9846
|
+
if (!options.region) throw new SstNeedsRegion();
|
|
9846
9847
|
const db = databaseFor();
|
|
9847
9848
|
const mail = emailFor();
|
|
9848
9849
|
const hasDatabase = options.template === "fullstack" || options.services.db;
|
|
@@ -9910,6 +9911,16 @@ ${inputs.join("\n")}
|
|
|
9910
9911
|
`
|
|
9911
9912
|
}];
|
|
9912
9913
|
}
|
|
9914
|
+
/**
|
|
9915
|
+
* An SST scaffold asked for without a region. `init` always resolves one —
|
|
9916
|
+
* asked, `--region`, or eu-west-1 under `--yes` — so this is a caller's bug.
|
|
9917
|
+
*/
|
|
9918
|
+
var SstNeedsRegion = class extends Error {
|
|
9919
|
+
constructor() {
|
|
9920
|
+
super("An SST deploy needs a region: pass --region, e.g. eu-west-1.");
|
|
9921
|
+
this.name = "SstNeedsRegion";
|
|
9922
|
+
}
|
|
9923
|
+
};
|
|
9913
9924
|
|
|
9914
9925
|
//#endregion
|
|
9915
9926
|
//#region src/init/generators/monorepo.ts
|
|
@@ -14091,8 +14102,8 @@ const AWS_REGION = /^[a-z]{2}(-gov)?-[a-z]+-\d$/;
|
|
|
14091
14102
|
async function initCommand(projectName, options = {}) {
|
|
14092
14103
|
const cwd = process.cwd();
|
|
14093
14104
|
const detectedPkgManager = detectPackageManager(cwd);
|
|
14094
|
-
if (options.deploy && !deployTargetChoices.some((choice) => choice.value === options.deploy)) throw new
|
|
14095
|
-
if (options.region && !AWS_REGION.test(options.region)) throw new
|
|
14105
|
+
if (options.deploy && !deployTargetChoices.some((choice) => choice.value === options.deploy)) throw new UnknownDeployTarget(options.deploy, deployTargetChoices.map((c) => c.value));
|
|
14106
|
+
if (options.region && !AWS_REGION.test(options.region)) throw new NotAnAwsRegion(options.region);
|
|
14096
14107
|
if (options.stages || options.localStage || options.protectedStage) {
|
|
14097
14108
|
const deployed = stageList(options.stages ?? "");
|
|
14098
14109
|
const problems = [
|
|
@@ -14103,7 +14114,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
14103
14114
|
}) : [],
|
|
14104
14115
|
...options.protectedStage && !deployed.includes(options.protectedStage) ? [`--protected-stage "${options.protectedStage}" is not in --stages`] : []
|
|
14105
14116
|
];
|
|
14106
|
-
if (problems.length) throw new
|
|
14117
|
+
if (problems.length) throw new require_workspace.InvalidStages([...new Set(problems)]);
|
|
14107
14118
|
}
|
|
14108
14119
|
let deployedSoFar = [];
|
|
14109
14120
|
prompts.default.override({});
|
|
@@ -14382,7 +14393,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
14382
14393
|
}
|
|
14383
14394
|
devSecrets.custom = customSecrets;
|
|
14384
14395
|
await require_storage.writeStageSecrets(devSecrets, targetDir);
|
|
14385
|
-
const keyPath =
|
|
14396
|
+
const keyPath = require_keystore.getKeyPath(local, name$1);
|
|
14386
14397
|
console.log(` Secrets: .gkm/secrets/${local}.json (encrypted)`);
|
|
14387
14398
|
console.log(` Key: ${keyPath}\n`);
|
|
14388
14399
|
if (!options.skipInstall) {
|
|
@@ -14511,9 +14522,26 @@ function resolveStages(options, answers) {
|
|
|
14511
14522
|
...kept ? { protected: [kept] } : {}
|
|
14512
14523
|
};
|
|
14513
14524
|
const problems = require_workspace.stageProblems(stages);
|
|
14514
|
-
if (problems.length) throw new
|
|
14525
|
+
if (problems.length) throw new require_workspace.InvalidStages(problems);
|
|
14515
14526
|
return stages;
|
|
14516
14527
|
}
|
|
14528
|
+
/** `--deploy` naming a target init has no scaffold for. */
|
|
14529
|
+
var UnknownDeployTarget = class extends Error {
|
|
14530
|
+
constructor(target, known) {
|
|
14531
|
+
super(`Unknown deploy target "${target}". Use ${known.join(", ")}.`);
|
|
14532
|
+
this.target = target;
|
|
14533
|
+
this.known = known;
|
|
14534
|
+
this.name = "UnknownDeployTarget";
|
|
14535
|
+
}
|
|
14536
|
+
};
|
|
14537
|
+
/** `--region` that is not shaped like one, e.g. `europe` for `eu-west-1`. */
|
|
14538
|
+
var NotAnAwsRegion = class extends Error {
|
|
14539
|
+
constructor(region) {
|
|
14540
|
+
super(`"${region}" is not an AWS region. Use one like eu-west-1.`);
|
|
14541
|
+
this.region = region;
|
|
14542
|
+
this.name = "NotAnAwsRegion";
|
|
14543
|
+
}
|
|
14544
|
+
};
|
|
14517
14545
|
|
|
14518
14546
|
//#endregion
|
|
14519
14547
|
//#region src/secrets/index.ts
|
|
@@ -14726,11 +14754,11 @@ function maskUrl(url) {
|
|
|
14726
14754
|
async function testCommand(options = {}) {
|
|
14727
14755
|
const cwd = process.cwd();
|
|
14728
14756
|
const stage = options.stage ?? await require_config.loadWorkspaceConfig(cwd).then((loaded) => loaded.workspace.stages.local).catch(() => void 0);
|
|
14729
|
-
if (!stage) throw new
|
|
14757
|
+
if (!stage) throw new NoStageToTest();
|
|
14730
14758
|
console.log(`\n🧪 Running tests with ${stage} environment...\n`);
|
|
14731
14759
|
const autoSetup = options.autoSetup || Boolean(process.env.GKM_AUTO_SETUP);
|
|
14732
14760
|
if (autoSetup) {
|
|
14733
|
-
const { ensureStageSecrets } = await Promise.resolve().then(() => require("./setup-
|
|
14761
|
+
const { ensureStageSecrets } = await Promise.resolve().then(() => require("./setup-lCx_DcUo.cjs"));
|
|
14734
14762
|
const generated = await ensureStageSecrets(stage, cwd);
|
|
14735
14763
|
if (generated) console.log(` 🔐 Generated fresh ${stage} secrets (auto-setup)`);
|
|
14736
14764
|
}
|
|
@@ -14817,6 +14845,13 @@ function rewriteDatabaseUrlForTests(env) {
|
|
|
14817
14845
|
}
|
|
14818
14846
|
return result;
|
|
14819
14847
|
}
|
|
14848
|
+
/** `gkm test` outside a project that declares stages, with none named. */
|
|
14849
|
+
var NoStageToTest = class extends Error {
|
|
14850
|
+
constructor() {
|
|
14851
|
+
super("No stage to test with: add `stages` to gkm.config.ts, or pass --stage.");
|
|
14852
|
+
this.name = "NoStageToTest";
|
|
14853
|
+
}
|
|
14854
|
+
};
|
|
14820
14855
|
|
|
14821
14856
|
//#endregion
|
|
14822
14857
|
//#region src/upgrade/version.ts
|
|
@@ -15359,13 +15394,13 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
|
|
|
15359
15394
|
const globalOptions = program.opts();
|
|
15360
15395
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
15361
15396
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await Promise.resolve().then(() => require("./config.cjs"));
|
|
15362
|
-
const { pushSecrets } = await Promise.resolve().then(() => require("./sync-
|
|
15363
|
-
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-
|
|
15364
|
-
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-
|
|
15397
|
+
const { pushSecrets } = await Promise.resolve().then(() => require("./sync-DYENfOt4.cjs"));
|
|
15398
|
+
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-CYMhFSYy.cjs"));
|
|
15399
|
+
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-DlVol_oj.cjs"));
|
|
15365
15400
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
15366
15401
|
const secrets = await readStageSecrets$1(options.stage, workspace.root);
|
|
15367
15402
|
if (secrets) {
|
|
15368
|
-
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-
|
|
15403
|
+
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-DQxxs7Jk.cjs"));
|
|
15369
15404
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers$1(workspace, options.stage));
|
|
15370
15405
|
if (result) {
|
|
15371
15406
|
await writeStageSecrets$1(result.secrets, workspace.root);
|
|
@@ -15385,16 +15420,16 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
|
|
|
15385
15420
|
const globalOptions = program.opts();
|
|
15386
15421
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
15387
15422
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await Promise.resolve().then(() => require("./config.cjs"));
|
|
15388
|
-
const { pullSecrets } = await Promise.resolve().then(() => require("./sync-
|
|
15389
|
-
const { writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-
|
|
15390
|
-
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-
|
|
15423
|
+
const { pullSecrets } = await Promise.resolve().then(() => require("./sync-DYENfOt4.cjs"));
|
|
15424
|
+
const { writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-DlVol_oj.cjs"));
|
|
15425
|
+
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-CYMhFSYy.cjs"));
|
|
15391
15426
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
15392
15427
|
let secrets = await pullSecrets(options.stage, workspace);
|
|
15393
15428
|
if (!secrets) {
|
|
15394
15429
|
console.error(`No remote secrets found for stage "${options.stage}".`);
|
|
15395
15430
|
process.exit(1);
|
|
15396
15431
|
}
|
|
15397
|
-
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-
|
|
15432
|
+
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-DQxxs7Jk.cjs"));
|
|
15398
15433
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers$1(workspace, options.stage));
|
|
15399
15434
|
if (result) {
|
|
15400
15435
|
secrets = result.secrets;
|
|
@@ -15413,8 +15448,8 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
15413
15448
|
const globalOptions = program.opts();
|
|
15414
15449
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
15415
15450
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await Promise.resolve().then(() => require("./config.cjs"));
|
|
15416
|
-
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-
|
|
15417
|
-
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-
|
|
15451
|
+
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-CYMhFSYy.cjs"));
|
|
15452
|
+
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-DlVol_oj.cjs"));
|
|
15418
15453
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
15419
15454
|
const stage = options.stage ?? workspace.stages.local;
|
|
15420
15455
|
const secrets = await readStageSecrets$1(stage, workspace.root);
|
|
@@ -15422,7 +15457,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
15422
15457
|
console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
|
|
15423
15458
|
process.exit(1);
|
|
15424
15459
|
}
|
|
15425
|
-
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-
|
|
15460
|
+
const { derivedContainers: derivedContainers$1 } = await Promise.resolve().then(() => require("./workspace-DQxxs7Jk.cjs"));
|
|
15426
15461
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers$1(workspace, stage));
|
|
15427
15462
|
if (!result) {
|
|
15428
15463
|
console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
|
|
@@ -15477,6 +15512,17 @@ program.command("deploy:init").description("Initialize Dokploy deployment (creat
|
|
|
15477
15512
|
process.exit(1);
|
|
15478
15513
|
}
|
|
15479
15514
|
});
|
|
15515
|
+
program.command("deploy:github").description("Let GitHub Actions deploy a stage: OIDC role in the stage's AWS account, and the GitHub environment the deploy workflow uses").requiredOption("--stage <stage>", "A deployed stage from gkm.config.ts").option("--profile <profile>", "AWS profile for the stage's account").option("--repo <owner/name>", "GitHub repository (default: this one)").option("--policy-arn <arn>", "Policy for the deploy role (default: AdministratorAccess)").option("--dry-run", "Show the plan without changing AWS or GitHub").action(async (options) => {
|
|
15516
|
+
try {
|
|
15517
|
+
const globalOptions = program.opts();
|
|
15518
|
+
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
15519
|
+
const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-BrvaPkFf.cjs"));
|
|
15520
|
+
await deployGithubCommand(options);
|
|
15521
|
+
} catch (error) {
|
|
15522
|
+
console.error(formatError(error));
|
|
15523
|
+
process.exit(1);
|
|
15524
|
+
}
|
|
15525
|
+
});
|
|
15480
15526
|
program.command("deploy:list").description("List Dokploy resources (projects, registries)").option("--endpoint <url>", "Dokploy server URL (uses stored credentials if logged in)").option("--projects", "List projects").option("--registries", "List registries").action(async (options) => {
|
|
15481
15527
|
try {
|
|
15482
15528
|
const globalOptions = program.opts();
|