@continuous-excellence/ze-great-dashboard-aws 0.1.23 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/cli.js +22 -5
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -5
- package/package.json +1 -1
- package/template.yml +9 -1
package/README.md
CHANGED
|
@@ -14,8 +14,8 @@ opinion about your process. Every panel is a live read of a system that already
|
|
|
14
14
|
Design doc: `ze-great-idea-pit/tool-ideas/trust-dashboard.md`. How this repo came to be shaped the
|
|
15
15
|
way it is, including the quirks that look like bugs: `docs/initialization-log.md`.
|
|
16
16
|
|
|
17
|
-
**Status:
|
|
18
|
-
|
|
17
|
+
**Status: MVP in active use.** GitHub Actions `pipeline-status` and source-agnostic `http-value`
|
|
18
|
+
panels work end to end. Azure DevOps remains to be built.
|
|
19
19
|
|
|
20
20
|
## Quickstart
|
|
21
21
|
|
|
@@ -116,12 +116,14 @@ Server environment variables are documented in `.env.example`. The one that matt
|
|
|
116
116
|
## Deploying
|
|
117
117
|
|
|
118
118
|
Push to `main`. CI checks, versions with [Tagger](https://github.com/robertfmurdock/tagger), publishes
|
|
119
|
-
the client
|
|
119
|
+
the immutable client assets, then deploys the exact npm tarball to the repository-owned consumer
|
|
120
|
+
reference before publishing that same tarball.
|
|
120
121
|
|
|
121
122
|
Infrastructure is a CloudFormation stack under `infra/`. On `main`, CI deploys the stack before it
|
|
122
|
-
publishes assets and updates the Lambda.
|
|
123
|
+
publishes assets and updates the Lambda. The public client origin is
|
|
124
|
+
`https://public-assets.zegreatrob.com`. Other branches receive no AWS credentials. CloudFormation
|
|
123
125
|
keeps the infrastructure state in AWS; `infra/README.md` documents the one-time GitHub OIDC role
|
|
124
|
-
|
|
126
|
+
bootstraps, including the consumer reference.
|
|
125
127
|
|
|
126
128
|
For a consumer-managed deployment with the published AWS package, see [`docs/aws-setup.md`](docs/aws-setup.md).
|
|
127
129
|
|
package/dist/cli.js
CHANGED
|
@@ -921,12 +921,9 @@ async function packageLambda(options) {
|
|
|
921
921
|
);
|
|
922
922
|
return packagedRelease;
|
|
923
923
|
}
|
|
924
|
-
async function
|
|
925
|
-
const artifactDir = resolve2(options.artifactDir);
|
|
924
|
+
async function publishClientAssets(options) {
|
|
926
925
|
const assetsDir = resolve2(options.assetsDir);
|
|
927
|
-
await readFile2(join2(artifactDir, "lambda.zip"));
|
|
928
926
|
await readFile2(join2(assetsDir, "index.html"));
|
|
929
|
-
if (options.dryRun) return;
|
|
930
927
|
const assetPath = `${options.assetsBaseUrl.replace(/\/+$/, "")}/dashboard/${options.version}`;
|
|
931
928
|
await run("aws", [
|
|
932
929
|
"s3",
|
|
@@ -946,6 +943,15 @@ async function deployLambda(options) {
|
|
|
946
943
|
"--cache-control",
|
|
947
944
|
"public, max-age=60"
|
|
948
945
|
]);
|
|
946
|
+
return assetPath;
|
|
947
|
+
}
|
|
948
|
+
async function deployLambda(options) {
|
|
949
|
+
const artifactDir = resolve2(options.artifactDir);
|
|
950
|
+
const assetsDir = resolve2(options.assetsDir);
|
|
951
|
+
await readFile2(join2(artifactDir, "lambda.zip"));
|
|
952
|
+
await readFile2(join2(assetsDir, "index.html"));
|
|
953
|
+
if (options.dryRun) return;
|
|
954
|
+
const assetPath = await publishClientAssets(options);
|
|
949
955
|
await run("aws", [
|
|
950
956
|
"lambda",
|
|
951
957
|
"update-function-code",
|
|
@@ -1180,6 +1186,15 @@ try {
|
|
|
1180
1186
|
dryRun: args.includes("--dry-run")
|
|
1181
1187
|
});
|
|
1182
1188
|
console.log(JSON.stringify({ deployed: true, version }));
|
|
1189
|
+
} else if (args[0] === "publish-assets") {
|
|
1190
|
+
const version = requiredOption("--version", packageVersion);
|
|
1191
|
+
const assetPath = await publishClientAssets({
|
|
1192
|
+
assetsDir: option("--assets-dir", bundledAssets) ?? bundledAssets,
|
|
1193
|
+
assetsBucket: requiredOption("--assets-bucket"),
|
|
1194
|
+
assetsBaseUrl: requiredOption("--assets-base-url"),
|
|
1195
|
+
version
|
|
1196
|
+
});
|
|
1197
|
+
console.log(JSON.stringify({ published: true, version, assetPath }));
|
|
1183
1198
|
} else if (args[0] === "doctor") {
|
|
1184
1199
|
const parametersPath = option("--parameters", "aws-dashboard-parameters.json") ?? "aws-dashboard-parameters.json";
|
|
1185
1200
|
const region = option("--region", process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? "us-east-1") ?? "us-east-1";
|
|
@@ -1237,7 +1252,9 @@ try {
|
|
|
1237
1252
|
`);
|
|
1238
1253
|
console.log(JSON.stringify({ output }));
|
|
1239
1254
|
} else if (args[0] !== "package")
|
|
1240
|
-
throw new Error(
|
|
1255
|
+
throw new Error(
|
|
1256
|
+
"Usage: ze-great-dashboard-aws package|parameters|publish-assets|deploy|doctor [options]"
|
|
1257
|
+
);
|
|
1241
1258
|
else {
|
|
1242
1259
|
const boardConfig = option("--board-config");
|
|
1243
1260
|
const version = option("--version", process.env.DASHBOARD_VERSION ?? packageVersion);
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,14 @@ export type DeployLambdaOptions = {
|
|
|
27
27
|
version: string;
|
|
28
28
|
dryRun?: boolean;
|
|
29
29
|
};
|
|
30
|
+
export type PublishClientAssetsOptions = {
|
|
31
|
+
assetsDir: string;
|
|
32
|
+
assetsBucket: string;
|
|
33
|
+
assetsBaseUrl: string;
|
|
34
|
+
version: string;
|
|
35
|
+
};
|
|
36
|
+
/** Publishes the immutable client half of a provider-managed release. */
|
|
37
|
+
export declare function publishClientAssets(options: PublishClientAssetsOptions): Promise<string>;
|
|
30
38
|
/** Performs the AWS-specific half of a release using explicit deployment outputs. */
|
|
31
39
|
export declare function deployLambda(options: DeployLambdaOptions): Promise<void>;
|
|
32
40
|
export declare function cloudFormationTemplate(): Promise<string>;
|
package/dist/index.js
CHANGED
|
@@ -908,12 +908,9 @@ async function packageLambda(options) {
|
|
|
908
908
|
);
|
|
909
909
|
return packagedRelease;
|
|
910
910
|
}
|
|
911
|
-
async function
|
|
912
|
-
const artifactDir = resolve2(options.artifactDir);
|
|
911
|
+
async function publishClientAssets(options) {
|
|
913
912
|
const assetsDir = resolve2(options.assetsDir);
|
|
914
|
-
await readFile2(join2(artifactDir, "lambda.zip"));
|
|
915
913
|
await readFile2(join2(assetsDir, "index.html"));
|
|
916
|
-
if (options.dryRun) return;
|
|
917
914
|
const assetPath = `${options.assetsBaseUrl.replace(/\/+$/, "")}/dashboard/${options.version}`;
|
|
918
915
|
await run("aws", [
|
|
919
916
|
"s3",
|
|
@@ -933,6 +930,15 @@ async function deployLambda(options) {
|
|
|
933
930
|
"--cache-control",
|
|
934
931
|
"public, max-age=60"
|
|
935
932
|
]);
|
|
933
|
+
return assetPath;
|
|
934
|
+
}
|
|
935
|
+
async function deployLambda(options) {
|
|
936
|
+
const artifactDir = resolve2(options.artifactDir);
|
|
937
|
+
const assetsDir = resolve2(options.assetsDir);
|
|
938
|
+
await readFile2(join2(artifactDir, "lambda.zip"));
|
|
939
|
+
await readFile2(join2(assetsDir, "index.html"));
|
|
940
|
+
if (options.dryRun) return;
|
|
941
|
+
const assetPath = await publishClientAssets(options);
|
|
936
942
|
await run("aws", [
|
|
937
943
|
"lambda",
|
|
938
944
|
"update-function-code",
|
|
@@ -960,5 +966,6 @@ async function cloudFormationTemplate() {
|
|
|
960
966
|
export {
|
|
961
967
|
cloudFormationTemplate,
|
|
962
968
|
deployLambda,
|
|
963
|
-
packageLambda
|
|
969
|
+
packageLambda,
|
|
970
|
+
publishClientAssets
|
|
964
971
|
};
|
package/package.json
CHANGED
package/template.yml
CHANGED
|
@@ -25,6 +25,9 @@ Resources:
|
|
|
25
25
|
ServerRole:
|
|
26
26
|
Type: AWS::IAM::Role
|
|
27
27
|
Properties:
|
|
28
|
+
# A stable, Name-derived role name lets consumer bootstrap policies scope CloudFormation
|
|
29
|
+
# execution to this stack's runtime role rather than every role in the account.
|
|
30
|
+
RoleName: !Sub '${Name}-server'
|
|
28
31
|
AssumeRolePolicyDocument:
|
|
29
32
|
Version: '2012-10-17'
|
|
30
33
|
Statement: [{ Effect: Allow, Principal: { Service: lambda.amazonaws.com }, Action: sts:AssumeRole }]
|
|
@@ -36,7 +39,12 @@ Resources:
|
|
|
36
39
|
Statement:
|
|
37
40
|
- Effect: Allow
|
|
38
41
|
Action: [secretsmanager:DescribeSecret, secretsmanager:GetSecretValue]
|
|
39
|
-
|
|
42
|
+
# IAM requires every statement to have a resource. When no secret is configured,
|
|
43
|
+
# keep this read permission pointed at a nonexistent ARN rather than widening it.
|
|
44
|
+
Resource: !If
|
|
45
|
+
- HasSecretReference
|
|
46
|
+
- !Ref SecretReference
|
|
47
|
+
- !Sub 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:ze-great-dashboard-no-secret-configured'
|
|
40
48
|
ServerLogGroup:
|
|
41
49
|
Type: AWS::Logs::LogGroup
|
|
42
50
|
Properties: { RetentionInDays: !Ref LogRetentionInDays, LogGroupName: !Sub '/aws/lambda/${Name}' }
|