@geekmidas/cli 10.0.0-alpha.12 → 10.0.0-alpha.13
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/{HostingerProvider-BcyFRbqV.mjs → HostingerProvider-BY26bWwB.mjs} +20 -21
- package/dist/HostingerProvider-BY26bWwB.mjs.map +1 -0
- package/dist/{HostingerProvider-BOvsgATO.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
- package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
- package/dist/{LocalStateProvider-yjXZXZDM.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
- package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
- package/dist/{LocalStateProvider-Bq-0C0sg.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
- package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
- package/dist/{Route53Provider-C0xmer8U.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
- package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
- package/dist/{Route53Provider-CH9XH7bz.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
- package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
- package/dist/{SSMStateProvider-DOZifZfE.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
- package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
- package/dist/{SSMStateProvider-CXtNgPfy.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
- package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
- package/dist/{backup-provisioner-cE2PuCTb.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
- package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
- package/dist/{backup-provisioner-DXXg6FIL.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
- package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
- package/dist/{bundler-BMekgx7a.cjs → bundler-BeNDZdHQ.cjs} +9 -12
- package/dist/bundler-BeNDZdHQ.cjs.map +1 -0
- package/dist/{bundler-Bux2iF-v.mjs → bundler-BodTL4kf.mjs} +8 -10
- package/dist/bundler-BodTL4kf.mjs.map +1 -0
- package/dist/{config-RYR9j6EF.cjs → config-Q1rvKHvw.cjs} +74 -69
- package/dist/config-Q1rvKHvw.cjs.map +1 -0
- package/dist/{config-DTsVjKZD.mjs → config-pqGD3hF9.mjs} +26 -14
- package/dist/config-pqGD3hF9.mjs.map +1 -0
- package/dist/config.cjs +4 -5
- package/dist/config.d.cts +14 -17
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +14 -17
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -5
- package/dist/{credentials-jMJC63qs.mjs → credentials-BekkKtY_.mjs} +234 -79
- package/dist/credentials-BekkKtY_.mjs.map +1 -0
- package/dist/{credentials-DQRvPz2S.cjs → credentials-Q6F0uqJq.cjs} +384 -236
- package/dist/credentials-Q6F0uqJq.cjs.map +1 -0
- package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
- package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
- package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
- package/dist/deploy/sniffer-hooks.cjs +13 -7
- package/dist/deploy/sniffer-hooks.cjs.map +1 -1
- package/dist/deploy/sniffer-hooks.d.cts +1 -2
- package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
- package/dist/deploy/sniffer-hooks.d.mts +1 -2
- package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
- package/dist/deploy/sniffer-hooks.mjs +9 -2
- package/dist/deploy/sniffer-hooks.mjs.map +1 -1
- package/dist/deploy/sniffer-loader.cjs +16 -7
- package/dist/deploy/sniffer-loader.cjs.map +1 -1
- package/dist/deploy/sniffer-loader.d.cts +1 -1
- package/dist/deploy/sniffer-loader.d.mts +1 -1
- package/dist/deploy/sniffer-loader.mjs +13 -2
- package/dist/deploy/sniffer-loader.mjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.cjs +11 -11
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
- package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +2 -2
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/deploy/sniffer-worker.cjs +15 -6
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.d.cts +1 -3
- package/dist/deploy/sniffer-worker.d.cts.map +1 -1
- package/dist/deploy/sniffer-worker.d.mts +1 -3
- package/dist/deploy/sniffer-worker.d.mts.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +15 -4
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/{discover-DmW9Bscc.cjs → discover-BERGFg8v.cjs} +68 -70
- package/dist/discover-BERGFg8v.cjs.map +1 -0
- package/dist/{discover-BYHQwQqu.mjs → discover-CK-n3w6b.mjs} +22 -20
- package/dist/discover-CK-n3w6b.mjs.map +1 -0
- package/dist/{emit-CUD1BWls.cjs → emit-BdoPFjZf.cjs} +53 -36
- package/dist/emit-BdoPFjZf.cjs.map +1 -0
- package/dist/{emit-CIlvnDvV.mjs → emit-Bzq7JsMP.mjs} +24 -6
- package/dist/emit-Bzq7JsMP.mjs.map +1 -0
- package/dist/{fullstack-secrets-B6KBHf-g.mjs → fullstack-secrets-BET8gqwK.mjs} +9 -15
- package/dist/fullstack-secrets-BET8gqwK.mjs.map +1 -0
- package/dist/{fullstack-secrets-DL8v0y4D.cjs → fullstack-secrets-DXsWO-5m.cjs} +19 -26
- package/dist/fullstack-secrets-DXsWO-5m.cjs.map +1 -0
- package/dist/{generator-VE2JrFlY.mjs → generator-LfZU7NlU.mjs} +8 -14
- package/dist/generator-LfZU7NlU.mjs.map +1 -0
- package/dist/{generator-CNzBw7g5.cjs → generator-Wdfp0jCS.cjs} +38 -45
- package/dist/generator-Wdfp0jCS.cjs.map +1 -0
- package/dist/{github-BThvbf2W.cjs → github-BfflNPVe.cjs} +36 -30
- package/dist/{github-BThvbf2W.cjs.map → github-BfflNPVe.cjs.map} +1 -1
- package/dist/{github-DpMZurEK.mjs → github-CRwnxKmD.mjs} +27 -20
- package/dist/github-CRwnxKmD.mjs.map +1 -0
- package/dist/{index-BzJ7QJ9c.d.mts → index-Cd-qeOam.d.mts} +3 -8
- package/dist/index-Cd-qeOam.d.mts.map +1 -0
- package/dist/{index-CfMjtdVC.d.cts → index-D-iAVHx-.d.cts} +3 -8
- package/dist/index-D-iAVHx-.d.cts.map +1 -0
- package/dist/index.cjs +2894 -1582
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2765 -1470
- package/dist/index.mjs.map +1 -1
- package/dist/{keystore-TxeYM7an.mjs → keystore-B4PRlbgE.mjs} +5 -7
- package/dist/keystore-B4PRlbgE.mjs.map +1 -0
- package/dist/{keystore-C9rint2E.cjs → keystore-DgGRj2Yy.cjs} +23 -26
- package/dist/keystore-DgGRj2Yy.cjs.map +1 -0
- package/dist/{openapi-DWLTsYLL.cjs → openapi-Dcbme-Us.cjs} +134 -171
- package/dist/openapi-Dcbme-Us.cjs.map +1 -0
- package/dist/openapi-react-query.cjs +156 -2
- package/dist/openapi-react-query.cjs.map +1 -0
- package/dist/openapi-react-query.d.cts +1 -3
- package/dist/openapi-react-query.d.cts.map +1 -1
- package/dist/openapi-react-query.d.mts +1 -3
- package/dist/openapi-react-query.d.mts.map +1 -1
- package/dist/openapi-react-query.mjs +156 -2
- package/dist/openapi-react-query.mjs.map +1 -0
- package/dist/{openapi-Bs3-5q_r.mjs → openapi-vy4JzhUv.mjs} +76 -106
- package/dist/openapi-vy4JzhUv.mjs.map +1 -0
- package/dist/openapi.cjs +3 -6
- package/dist/openapi.d.cts +8 -11
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +8 -11
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +2 -6
- package/dist/reconcile/public.cjs +4 -4
- package/dist/reconcile/public.d.cts +8 -26
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +8 -26
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{reconcile-Bhw5fmKu.cjs → reconcile-Dd2iyILf.cjs} +4 -7
- package/dist/reconcile-Dd2iyILf.cjs.map +1 -0
- package/dist/{reconcile-BI0tWkwz.mjs → reconcile-DhQ00DpU.mjs} +4 -7
- package/dist/reconcile-DhQ00DpU.mjs.map +1 -0
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
- package/dist/{storage-CSNplaJn.cjs → storage-C-30BD1e.cjs} +59 -69
- package/dist/storage-C-30BD1e.cjs.map +1 -0
- package/dist/{storage-B020InPW.mjs → storage-P_b3w7uj.mjs} +22 -13
- package/dist/storage-P_b3w7uj.mjs.map +1 -0
- package/dist/{sync-CzHXiR9c.mjs → sync-B3xxXtJT.mjs} +18 -6
- package/dist/sync-B3xxXtJT.mjs.map +1 -0
- package/dist/{sync-0ILCb-1S.cjs → sync-D7uTIIEi.cjs} +43 -25
- package/dist/sync-D7uTIIEi.cjs.map +1 -0
- package/dist/types-BGo5TaNE.d.mts +6164 -0
- package/dist/types-BGo5TaNE.d.mts.map +1 -0
- package/dist/types-C5ZNpUad.d.cts +6165 -0
- package/dist/types-C5ZNpUad.d.cts.map +1 -0
- package/dist/workspace/index.cjs +3 -3
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -3
- package/dist/{workspace-CtnZnWsa.mjs → workspace-CgwmXEtc.mjs} +712 -806
- package/dist/workspace-CgwmXEtc.mjs.map +1 -0
- package/dist/{workspace-DPV7FtAv.cjs → workspace-mFpI_ky_.cjs} +881 -976
- package/dist/workspace-mFpI_ky_.cjs.map +1 -0
- package/package.json +14 -14
- package/dist/CachedStateProvider-BEBl2wQT.cjs +0 -60
- package/dist/CachedStateProvider-BEBl2wQT.cjs.map +0 -1
- package/dist/CachedStateProvider-C-8wtlto.mjs +0 -3
- package/dist/CachedStateProvider-Co4n5Wvs.mjs +0 -54
- package/dist/CachedStateProvider-Co4n5Wvs.mjs.map +0 -1
- package/dist/CachedStateProvider-DqhGpzsm.cjs +0 -3
- package/dist/HostingerProvider-BOvsgATO.cjs.map +0 -1
- package/dist/HostingerProvider-BcyFRbqV.mjs.map +0 -1
- package/dist/LocalStateProvider-Bq-0C0sg.mjs.map +0 -1
- package/dist/LocalStateProvider-yjXZXZDM.cjs.map +0 -1
- package/dist/Route53Provider-C0xmer8U.mjs.map +0 -1
- package/dist/Route53Provider-CH9XH7bz.cjs.map +0 -1
- package/dist/SSMStateProvider-CXtNgPfy.cjs.map +0 -1
- package/dist/SSMStateProvider-DOZifZfE.mjs.map +0 -1
- package/dist/backup-provisioner-DXXg6FIL.mjs.map +0 -1
- package/dist/backup-provisioner-cE2PuCTb.cjs.map +0 -1
- package/dist/bundler-BMekgx7a.cjs.map +0 -1
- package/dist/bundler-Bux2iF-v.mjs.map +0 -1
- package/dist/chunk-Duj1WY3L.mjs +0 -7
- package/dist/config-DTsVjKZD.mjs.map +0 -1
- package/dist/config-RYR9j6EF.cjs.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-DQRvPz2S.cjs.map +0 -1
- package/dist/credentials-jMJC63qs.mjs.map +0 -1
- package/dist/discover-BYHQwQqu.mjs.map +0 -1
- package/dist/discover-DmW9Bscc.cjs.map +0 -1
- package/dist/dokploy-api-5cK2InBm.cjs +0 -3
- package/dist/dokploy-api-D2Ny4Jrc.mjs +0 -3
- package/dist/dokploy-api-pdaBryoY.mjs +0 -706
- package/dist/dokploy-api-pdaBryoY.mjs.map +0 -1
- package/dist/dokploy-api-zqKe9lHH.cjs +0 -718
- package/dist/dokploy-api-zqKe9lHH.cjs.map +0 -1
- package/dist/emit-CIlvnDvV.mjs.map +0 -1
- package/dist/emit-CUD1BWls.cjs.map +0 -1
- package/dist/encryption-D2pL3tHH.cjs +0 -54
- package/dist/encryption-D2pL3tHH.cjs.map +0 -1
- package/dist/encryption-YDsXXi6w.mjs +0 -3
- package/dist/encryption-_4zwjOAR.mjs +0 -42
- package/dist/encryption-_4zwjOAR.mjs.map +0 -1
- package/dist/encryption-sQ2Oxx0d.cjs +0 -4
- package/dist/fullstack-secrets-B6KBHf-g.mjs.map +0 -1
- package/dist/fullstack-secrets-DL8v0y4D.cjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/github-DpMZurEK.mjs.map +0 -1
- package/dist/index-BzJ7QJ9c.d.mts.map +0 -1
- package/dist/index-CfMjtdVC.d.cts.map +0 -1
- package/dist/keystore-C9rint2E.cjs.map +0 -1
- package/dist/keystore-TxeYM7an.mjs.map +0 -1
- package/dist/openapi-Bs3-5q_r.mjs.map +0 -1
- package/dist/openapi-DWLTsYLL.cjs.map +0 -1
- package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
- package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
- package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
- package/dist/reconcile-BI0tWkwz.mjs.map +0 -1
- package/dist/reconcile-Bhw5fmKu.cjs.map +0 -1
- package/dist/setup-BmLoNrDX.mjs +0 -12
- package/dist/setup-BrR1_xGy.cjs +0 -12
- package/dist/setup-BsNR2LBG.cjs +0 -467
- package/dist/setup-BsNR2LBG.cjs.map +0 -1
- package/dist/setup-D5-JMknk.mjs +0 -437
- package/dist/setup-D5-JMknk.mjs.map +0 -1
- package/dist/storage-B020InPW.mjs.map +0 -1
- package/dist/storage-CSNplaJn.cjs.map +0 -1
- package/dist/storage-DGBzMLZa.mjs +0 -4
- package/dist/storage-DlVol_oj.cjs +0 -8
- package/dist/sync-0ILCb-1S.cjs.map +0 -1
- package/dist/sync-CzHXiR9c.mjs.map +0 -1
- package/dist/sync-DYENfOt4.cjs +0 -4
- package/dist/sync-HAau6h_R.mjs +0 -3
- package/dist/types-DVIx8I1N.d.mts +0 -1950
- package/dist/types-DVIx8I1N.d.mts.map +0 -1
- package/dist/types-PMP_qXRY.d.cts +0 -1950
- package/dist/types-PMP_qXRY.d.cts.map +0 -1
- package/dist/workspace-Cji6lE8E.cjs +0 -10
- package/dist/workspace-CkJAtRIX.mjs +0 -9
- package/dist/workspace-CtnZnWsa.mjs.map +0 -1
- package/dist/workspace-DPV7FtAv.cjs.map +0 -1
|
@@ -1,21 +1,28 @@
|
|
|
1
|
-
const
|
|
2
|
-
require(
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const node_child_process = require_chunk.__toESM(require("node:child_process"));
|
|
8
|
-
const __aws_sdk_client_iam = require_chunk.__toESM(require("@aws-sdk/client-iam"));
|
|
9
|
-
|
|
1
|
+
const require_config = require("./config-Q1rvKHvw.cjs");
|
|
2
|
+
const require_workspace = require("./workspace-mFpI_ky_.cjs");
|
|
3
|
+
const require_keystore = require("./keystore-DgGRj2Yy.cjs");
|
|
4
|
+
let node_fs = require("node:fs");
|
|
5
|
+
let node_child_process = require("node:child_process");
|
|
6
|
+
let _aws_sdk_client_iam = require("@aws-sdk/client-iam");
|
|
10
7
|
//#region src/deploy/github.ts
|
|
8
|
+
/**
|
|
9
|
+
* `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.
|
|
10
|
+
*
|
|
11
|
+
* A stage usually lives in its own AWS account — staging in one, production in
|
|
12
|
+
* another — so this runs once per stage, with that account's profile:
|
|
13
|
+
*
|
|
14
|
+
* gkm deploy:github --stage staging --profile acme-dev
|
|
15
|
+
* gkm deploy:github --stage prod --profile acme-prod
|
|
16
|
+
*
|
|
17
|
+
* In the stage's account it makes sure GitHub's OIDC provider exists, and a
|
|
18
|
+
* role that only this repository's `<stage>` environment can assume. On
|
|
19
|
+
* GitHub it creates that environment and gives it what the generated deploy
|
|
20
|
+
* workflow reads: `AWS_ROLE_ARN`, and the stage's secrets key as
|
|
21
|
+
* `GKM_SECRETS_KEY`. Re-running it converges rather than duplicating.
|
|
22
|
+
*/
|
|
11
23
|
const logger = console;
|
|
12
24
|
const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
|
|
13
25
|
const AUDIENCE = "sts.amazonaws.com";
|
|
14
|
-
/**
|
|
15
|
-
* What SST needs to create a stack is most of AWS, so this is the default —
|
|
16
|
-
* said out loud in the output, and replaceable with `--policy-arn`.
|
|
17
|
-
*/
|
|
18
|
-
const DEFAULT_POLICY_ARN = "arn:aws:iam::aws:policy/AdministratorAccess";
|
|
19
26
|
const defaultGh = (args, input) => (0, node_child_process.execFileSync)("gh", args, {
|
|
20
27
|
encoding: "utf-8",
|
|
21
28
|
...input === void 0 ? {} : {
|
|
@@ -53,36 +60,35 @@ function trustPolicy(providerArn, repo, stage) {
|
|
|
53
60
|
}
|
|
54
61
|
/** GitHub's OIDC provider in this account, created if it is not there. */
|
|
55
62
|
async function ensureOidcProvider(iam) {
|
|
56
|
-
const { OpenIDConnectProviderList = [] } = await iam.send(new
|
|
63
|
+
const { OpenIDConnectProviderList = [] } = await iam.send(new _aws_sdk_client_iam.ListOpenIDConnectProvidersCommand({}));
|
|
57
64
|
const existing = OpenIDConnectProviderList.find((p) => p.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`))?.Arn;
|
|
58
65
|
if (existing) return existing;
|
|
59
|
-
|
|
66
|
+
return (await iam.send(new _aws_sdk_client_iam.CreateOpenIDConnectProviderCommand({
|
|
60
67
|
Url: `https://${GITHUB_OIDC_HOST}`,
|
|
61
68
|
ClientIDList: [AUDIENCE]
|
|
62
|
-
}));
|
|
63
|
-
return created.OpenIDConnectProviderArn;
|
|
69
|
+
}))).OpenIDConnectProviderArn;
|
|
64
70
|
}
|
|
65
71
|
/** The deploy role, created or brought back to this trust and policy. */
|
|
66
72
|
async function ensureRole(iam, name, trust, policyArn) {
|
|
67
73
|
let arn;
|
|
68
74
|
try {
|
|
69
|
-
const { Role } = await iam.send(new
|
|
70
|
-
await iam.send(new
|
|
75
|
+
const { Role } = await iam.send(new _aws_sdk_client_iam.GetRoleCommand({ RoleName: name }));
|
|
76
|
+
await iam.send(new _aws_sdk_client_iam.UpdateAssumeRolePolicyCommand({
|
|
71
77
|
RoleName: name,
|
|
72
78
|
PolicyDocument: trust
|
|
73
79
|
}));
|
|
74
80
|
arn = Role.Arn;
|
|
75
81
|
} catch (error) {
|
|
76
82
|
if (error.name !== "NoSuchEntityException") throw error;
|
|
77
|
-
const { Role } = await iam.send(new
|
|
83
|
+
const { Role } = await iam.send(new _aws_sdk_client_iam.CreateRoleCommand({
|
|
78
84
|
RoleName: name,
|
|
79
85
|
AssumeRolePolicyDocument: trust,
|
|
80
86
|
Description: "Deploys from GitHub Actions (gkm deploy:github)",
|
|
81
|
-
MaxSessionDuration:
|
|
87
|
+
MaxSessionDuration: 7200
|
|
82
88
|
}));
|
|
83
89
|
arn = Role.Arn;
|
|
84
90
|
}
|
|
85
|
-
await iam.send(new
|
|
91
|
+
await iam.send(new _aws_sdk_client_iam.AttachRolePolicyCommand({
|
|
86
92
|
RoleName: name,
|
|
87
93
|
PolicyArn: policyArn
|
|
88
94
|
}));
|
|
@@ -111,7 +117,7 @@ async function iamFor(profile, endpoint) {
|
|
|
111
117
|
secretAccessKey: "test"
|
|
112
118
|
};
|
|
113
119
|
}
|
|
114
|
-
return new
|
|
120
|
+
return new _aws_sdk_client_iam.IAMClient(config);
|
|
115
121
|
}
|
|
116
122
|
async function deployGithubCommand(options, deps = {}) {
|
|
117
123
|
const gh = deps.gh ?? defaultGh;
|
|
@@ -126,7 +132,7 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
126
132
|
".nameWithOwner"
|
|
127
133
|
]);
|
|
128
134
|
const role = roleName(workspace.name, options.stage);
|
|
129
|
-
const policyArn = options.policyArn ??
|
|
135
|
+
const policyArn = options.policyArn ?? "arn:aws:iam::aws:policy/AdministratorAccess";
|
|
130
136
|
const keyPath = require_keystore.getKeyPath(options.stage, workspace.name);
|
|
131
137
|
const hasKey = (0, node_fs.existsSync)(keyPath);
|
|
132
138
|
logger.log(`\n🔐 GitHub → AWS for stage "${options.stage}"\n`);
|
|
@@ -141,11 +147,10 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
141
147
|
return { repo };
|
|
142
148
|
}
|
|
143
149
|
const iam = deps.iam ?? await iamFor(options.profile);
|
|
144
|
-
const
|
|
150
|
+
const roleArn = await ensureRole(iam, role, trustPolicy(await ensureOidcProvider(iam).catch((error) => {
|
|
145
151
|
if (/SSO session/i.test(String(error?.message)) && options.profile) throw new SsoSessionExpired(options.profile);
|
|
146
152
|
throw error;
|
|
147
|
-
});
|
|
148
|
-
const roleArn = await ensureRole(iam, role, trustPolicy(providerArn, repo, options.stage), policyArn);
|
|
153
|
+
}), repo, options.stage), policyArn);
|
|
149
154
|
logger.log(`\n ✓ AWS: ${roleArn}`);
|
|
150
155
|
gh([
|
|
151
156
|
"api",
|
|
@@ -185,13 +190,14 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
185
190
|
}
|
|
186
191
|
/** The profile's SSO login has lapsed; the fix is one command away. */
|
|
187
192
|
var SsoSessionExpired = class extends Error {
|
|
193
|
+
profile;
|
|
188
194
|
constructor(profile) {
|
|
189
195
|
super(`The SSO session for profile "${profile}" has expired or is invalid. Run: aws sso login --profile ${profile}`);
|
|
190
196
|
this.profile = profile;
|
|
191
197
|
this.name = "SsoSessionExpired";
|
|
192
198
|
}
|
|
193
199
|
};
|
|
194
|
-
|
|
195
200
|
//#endregion
|
|
196
201
|
exports.deployGithubCommand = deployGithubCommand;
|
|
197
|
-
|
|
202
|
+
|
|
203
|
+
//# sourceMappingURL=github-BfflNPVe.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-BThvbf2W.cjs","names":["defaultGh: Gh","project: string","stage: string","providerArn: string","repo: string","iam: IAMClient","ListOpenIDConnectProvidersCommand","CreateOpenIDConnectProviderCommand","name: string","trust: string","policyArn: string","arn: string","GetRoleCommand","UpdateAssumeRolePolicyCommand","CreateRoleCommand","AttachRolePolicyCommand","profile?: string","endpoint?: string","config: IAMClientConfig","IAMClient","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
|
+
{"version":3,"file":"github-BfflNPVe.cjs","names":["execFileSync","ListOpenIDConnectProvidersCommand","CreateOpenIDConnectProviderCommand","GetRoleCommand","UpdateAssumeRolePolicyCommand","CreateRoleCommand","AttachRolePolicyCommand","IAMClient","loadWorkspaceConfig","getKeyPath","existsSync","readFileSync"],"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,20 +1,28 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getKeyPath } from "./keystore-TxeYM7an.mjs";
|
|
1
|
+
import { o as loadWorkspaceConfig } from "./config-pqGD3hF9.mjs";
|
|
2
|
+
import { w as assertDeployedStage } from "./workspace-CgwmXEtc.mjs";
|
|
3
|
+
import { t as getKeyPath } from "./keystore-B4PRlbgE.mjs";
|
|
5
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
5
|
import { execFileSync } from "node:child_process";
|
|
7
6
|
import { AttachRolePolicyCommand, CreateOpenIDConnectProviderCommand, CreateRoleCommand, GetRoleCommand, IAMClient, ListOpenIDConnectProvidersCommand, UpdateAssumeRolePolicyCommand } from "@aws-sdk/client-iam";
|
|
8
|
-
|
|
9
7
|
//#region src/deploy/github.ts
|
|
8
|
+
/**
|
|
9
|
+
* `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.
|
|
10
|
+
*
|
|
11
|
+
* A stage usually lives in its own AWS account — staging in one, production in
|
|
12
|
+
* another — so this runs once per stage, with that account's profile:
|
|
13
|
+
*
|
|
14
|
+
* gkm deploy:github --stage staging --profile acme-dev
|
|
15
|
+
* gkm deploy:github --stage prod --profile acme-prod
|
|
16
|
+
*
|
|
17
|
+
* In the stage's account it makes sure GitHub's OIDC provider exists, and a
|
|
18
|
+
* role that only this repository's `<stage>` environment can assume. On
|
|
19
|
+
* GitHub it creates that environment and gives it what the generated deploy
|
|
20
|
+
* workflow reads: `AWS_ROLE_ARN`, and the stage's secrets key as
|
|
21
|
+
* `GKM_SECRETS_KEY`. Re-running it converges rather than duplicating.
|
|
22
|
+
*/
|
|
10
23
|
const logger = console;
|
|
11
24
|
const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
|
|
12
25
|
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
26
|
const defaultGh = (args, input) => execFileSync("gh", args, {
|
|
19
27
|
encoding: "utf-8",
|
|
20
28
|
...input === void 0 ? {} : {
|
|
@@ -55,11 +63,10 @@ async function ensureOidcProvider(iam) {
|
|
|
55
63
|
const { OpenIDConnectProviderList = [] } = await iam.send(new ListOpenIDConnectProvidersCommand({}));
|
|
56
64
|
const existing = OpenIDConnectProviderList.find((p) => p.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`))?.Arn;
|
|
57
65
|
if (existing) return existing;
|
|
58
|
-
|
|
66
|
+
return (await iam.send(new CreateOpenIDConnectProviderCommand({
|
|
59
67
|
Url: `https://${GITHUB_OIDC_HOST}`,
|
|
60
68
|
ClientIDList: [AUDIENCE]
|
|
61
|
-
}));
|
|
62
|
-
return created.OpenIDConnectProviderArn;
|
|
69
|
+
}))).OpenIDConnectProviderArn;
|
|
63
70
|
}
|
|
64
71
|
/** The deploy role, created or brought back to this trust and policy. */
|
|
65
72
|
async function ensureRole(iam, name, trust, policyArn) {
|
|
@@ -77,7 +84,7 @@ async function ensureRole(iam, name, trust, policyArn) {
|
|
|
77
84
|
RoleName: name,
|
|
78
85
|
AssumeRolePolicyDocument: trust,
|
|
79
86
|
Description: "Deploys from GitHub Actions (gkm deploy:github)",
|
|
80
|
-
MaxSessionDuration:
|
|
87
|
+
MaxSessionDuration: 7200
|
|
81
88
|
}));
|
|
82
89
|
arn = Role.Arn;
|
|
83
90
|
}
|
|
@@ -125,7 +132,7 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
125
132
|
".nameWithOwner"
|
|
126
133
|
]);
|
|
127
134
|
const role = roleName(workspace.name, options.stage);
|
|
128
|
-
const policyArn = options.policyArn ??
|
|
135
|
+
const policyArn = options.policyArn ?? "arn:aws:iam::aws:policy/AdministratorAccess";
|
|
129
136
|
const keyPath = getKeyPath(options.stage, workspace.name);
|
|
130
137
|
const hasKey = existsSync(keyPath);
|
|
131
138
|
logger.log(`\n🔐 GitHub → AWS for stage "${options.stage}"\n`);
|
|
@@ -140,11 +147,10 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
140
147
|
return { repo };
|
|
141
148
|
}
|
|
142
149
|
const iam = deps.iam ?? await iamFor(options.profile);
|
|
143
|
-
const
|
|
150
|
+
const roleArn = await ensureRole(iam, role, trustPolicy(await ensureOidcProvider(iam).catch((error) => {
|
|
144
151
|
if (/SSO session/i.test(String(error?.message)) && options.profile) throw new SsoSessionExpired(options.profile);
|
|
145
152
|
throw error;
|
|
146
|
-
});
|
|
147
|
-
const roleArn = await ensureRole(iam, role, trustPolicy(providerArn, repo, options.stage), policyArn);
|
|
153
|
+
}), repo, options.stage), policyArn);
|
|
148
154
|
logger.log(`\n ✓ AWS: ${roleArn}`);
|
|
149
155
|
gh([
|
|
150
156
|
"api",
|
|
@@ -184,13 +190,14 @@ async function deployGithubCommand(options, deps = {}) {
|
|
|
184
190
|
}
|
|
185
191
|
/** The profile's SSO login has lapsed; the fix is one command away. */
|
|
186
192
|
var SsoSessionExpired = class extends Error {
|
|
193
|
+
profile;
|
|
187
194
|
constructor(profile) {
|
|
188
195
|
super(`The SSO session for profile "${profile}" has expired or is invalid. Run: aws sso login --profile ${profile}`);
|
|
189
196
|
this.profile = profile;
|
|
190
197
|
this.name = "SsoSessionExpired";
|
|
191
198
|
}
|
|
192
199
|
};
|
|
193
|
-
|
|
194
200
|
//#endregion
|
|
195
201
|
export { deployGithubCommand };
|
|
196
|
-
|
|
202
|
+
|
|
203
|
+
//# sourceMappingURL=github-CRwnxKmD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-CRwnxKmD.mjs","names":[],"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,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { C as WorkspaceInput, E as Framework, S as WorkspaceConfig, a as Routes, g as LoadedConfig, h as InferredWorkspaceConfig, l as AppsRecord, r as GkmConfig, y as NormalizedWorkspace } from "./types-BGo5TaNE.mjs";
|
|
3
2
|
//#region src/workspace/publicEnv.d.ts
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
4
|
* All public env-var prefixes the toolbox understands.
|
|
7
5
|
*
|
|
@@ -30,8 +28,6 @@ declare function getPublicEnvPrefix(framework?: Framework): string;
|
|
|
30
28
|
* Returns the un-prefixed name, or `null` if no prefix matched.
|
|
31
29
|
*/
|
|
32
30
|
declare function stripPublicPrefix(name: string): string | null;
|
|
33
|
-
//# sourceMappingURL=publicEnv.d.ts.map
|
|
34
|
-
|
|
35
31
|
//#endregion
|
|
36
32
|
//#region src/workspace/index.d.ts
|
|
37
33
|
/**
|
|
@@ -165,7 +161,6 @@ declare function getEndpointForStage(dokployConfig: {
|
|
|
165
161
|
endpoint?: string;
|
|
166
162
|
endpoints?: Record<string, string>;
|
|
167
163
|
} | undefined, stage: string): string | undefined;
|
|
168
|
-
//# sourceMappingURL=index.d.ts.map
|
|
169
164
|
//#endregion
|
|
170
|
-
export {
|
|
171
|
-
//# sourceMappingURL=index-
|
|
165
|
+
export { getAppBuildOrder as a, getEndpointForStage as c, workspaceConstructGlobs as d, wrapSingleAppAsWorkspace as f, stripPublicPrefix as h, defineWorkspace as i, normalizeWorkspace as l, getPublicEnvPrefix as m, appConstructGlobs as n, getAppGkmConfig as o, PUBLIC_ENV_PREFIXES as p, constructPatterns as r, getDependencyEnvVars as s, allConstructGlobs as t, processConfig as u };
|
|
166
|
+
//# sourceMappingURL=index-Cd-qeOam.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Cd-qeOam.d.mts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC4ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBA8BX,mBACf,QAAQ,iBACR,cACE;;;;;iBA8Ca,yBACf,QAAQ,WACR,cACE;;;;;iBA0Da,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBA6Ba,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAiB1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAkCa,iBAAiB,WAAW;;;;;;;;;;iBAmC5B,qBACf,WAAW,qBACX,iBACA,qBACE;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDa,oBACf;EACK;EAAmB,YAAY;eAEpC"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { C as WorkspaceInput, E as Framework, S as WorkspaceConfig, a as Routes, g as LoadedConfig, h as InferredWorkspaceConfig, l as AppsRecord, r as GkmConfig, y as NormalizedWorkspace } from "./types-C5ZNpUad.cjs";
|
|
3
2
|
//#region src/workspace/publicEnv.d.ts
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
4
|
* All public env-var prefixes the toolbox understands.
|
|
7
5
|
*
|
|
@@ -30,8 +28,6 @@ declare function getPublicEnvPrefix(framework?: Framework): string;
|
|
|
30
28
|
* Returns the un-prefixed name, or `null` if no prefix matched.
|
|
31
29
|
*/
|
|
32
30
|
declare function stripPublicPrefix(name: string): string | null;
|
|
33
|
-
//# sourceMappingURL=publicEnv.d.ts.map
|
|
34
|
-
|
|
35
31
|
//#endregion
|
|
36
32
|
//#region src/workspace/index.d.ts
|
|
37
33
|
/**
|
|
@@ -165,7 +161,6 @@ declare function getEndpointForStage(dokployConfig: {
|
|
|
165
161
|
endpoint?: string;
|
|
166
162
|
endpoints?: Record<string, string>;
|
|
167
163
|
} | undefined, stage: string): string | undefined;
|
|
168
|
-
//# sourceMappingURL=index.d.ts.map
|
|
169
164
|
//#endregion
|
|
170
|
-
export {
|
|
171
|
-
//# sourceMappingURL=index-
|
|
165
|
+
export { getAppBuildOrder as a, getEndpointForStage as c, workspaceConstructGlobs as d, wrapSingleAppAsWorkspace as f, stripPublicPrefix as h, defineWorkspace as i, normalizeWorkspace as l, getPublicEnvPrefix as m, appConstructGlobs as n, getAppGkmConfig as o, PUBLIC_ENV_PREFIXES as p, constructPatterns as r, getDependencyEnvVars as s, allConstructGlobs as t, processConfig as u };
|
|
166
|
+
//# sourceMappingURL=index-D-iAVHx-.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-D-iAVHx-.d.cts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC4ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBA8BX,mBACf,QAAQ,iBACR,cACE;;;;;iBA8Ca,yBACf,QAAQ,WACR,cACE;;;;;iBA0Da,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBA6Ba,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAiB1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAkCa,iBAAiB,WAAW;;;;;;;;;;iBAmC5B,qBACf,WAAW,qBACX,iBACA,qBACE;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDa,oBACf;EACK;EAAmB,YAAY;eAEpC"}
|