@anthusai/papyrus 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/infra/amplify-app-shell.js +17 -3
- package/infra/amplify-app-shell.ts +18 -3
- package/infra/site-config.js +6 -1
- package/infra/site-config.ts +7 -1
- package/package.json +1 -1
- package/routes.manifest.json +1 -1
|
@@ -43,11 +43,22 @@ The stack also creates the `<siteId>-papyrus-authoring` role. The CLI signs
|
|
|
43
43
|
* AppSync requests (SigV4) with credentials for that role (SSO, OIDC or any
|
|
44
44
|
* principal in the account that may assume it); no token is stored anywhere.
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
* until Amplify's GitHub App is
|
|
48
|
-
* (docs/site-hosting.md).
|
|
46
|
+
* Unless `repositoryAccessTokenSecretArn` is set, no repository and no access
|
|
47
|
+
* token are configured: the apps are manual-deploy until Amplify's GitHub App is
|
|
48
|
+
* connected once in the console (docs/site-hosting.md). When it is set, both apps
|
|
49
|
+
* are created against `repository` and read the GitHub token from that Secrets
|
|
50
|
+
* Manager secret through a CloudFormation dynamic reference, so the token never
|
|
51
|
+
* appears in site.json or the synthesized template. The Papyrus backend itself is created inside the CMS
|
|
49
52
|
* app by `ampx pipeline-deploy` from the production build.
|
|
50
53
|
*/
|
|
54
|
+
function repositoryConnectionProperties(config) {
|
|
55
|
+
if (config.repositoryAccessTokenSecretArn === undefined)
|
|
56
|
+
return {};
|
|
57
|
+
return {
|
|
58
|
+
repository: config.repository,
|
|
59
|
+
accessToken: `{{resolve:secretsmanager:${config.repositoryAccessTokenSecretArn}:SecretString}}`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
51
62
|
export class AmplifyAppShellStack extends Stack {
|
|
52
63
|
cmsAppId;
|
|
53
64
|
readerAppId;
|
|
@@ -114,7 +125,9 @@ export class AmplifyAppShellStack extends Stack {
|
|
|
114
125
|
resources: PROSPECTUS_PAPYRUS_SITE_ROUTES.map((route) => `${prospectusAccountsApiStageArn}/${route}`),
|
|
115
126
|
}));
|
|
116
127
|
}
|
|
128
|
+
const repositoryConnection = repositoryConnectionProperties(config);
|
|
117
129
|
const cmsApp = new amplify.CfnApp(this, "App", {
|
|
130
|
+
...repositoryConnection,
|
|
118
131
|
name: cmsAppName,
|
|
119
132
|
description: `Papyrus newsroom CMS for ${config.siteId} (WEB_COMPUTE)`,
|
|
120
133
|
platform: "WEB_COMPUTE",
|
|
@@ -332,6 +345,7 @@ export class AmplifyAppShellStack extends Stack {
|
|
|
332
345
|
resources: ["arn:aws:s3:::amplify-*/media/*"],
|
|
333
346
|
}));
|
|
334
347
|
const readerApp = new amplify.CfnApp(this, "ReaderApp", {
|
|
348
|
+
...repositoryConnectionProperties(config),
|
|
335
349
|
name: readerAppName,
|
|
336
350
|
description: `Papyrus static reader for ${config.siteId} (WEB)`,
|
|
337
351
|
platform: "WEB",
|
|
@@ -46,11 +46,22 @@ The stack also creates the `<siteId>-papyrus-authoring` role. The CLI signs
|
|
|
46
46
|
* AppSync requests (SigV4) with credentials for that role (SSO, OIDC or any
|
|
47
47
|
* principal in the account that may assume it); no token is stored anywhere.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
* until Amplify's GitHub App is
|
|
51
|
-
* (docs/site-hosting.md).
|
|
49
|
+
* Unless `repositoryAccessTokenSecretArn` is set, no repository and no access
|
|
50
|
+
* token are configured: the apps are manual-deploy until Amplify's GitHub App is
|
|
51
|
+
* connected once in the console (docs/site-hosting.md). When it is set, both apps
|
|
52
|
+
* are created against `repository` and read the GitHub token from that Secrets
|
|
53
|
+
* Manager secret through a CloudFormation dynamic reference, so the token never
|
|
54
|
+
* appears in site.json or the synthesized template. The Papyrus backend itself is created inside the CMS
|
|
52
55
|
* app by `ampx pipeline-deploy` from the production build.
|
|
53
56
|
*/
|
|
57
|
+
function repositoryConnectionProperties(config: AmplifyAppShellSiteConfig): { repository?: string; accessToken?: string } {
|
|
58
|
+
if (config.repositoryAccessTokenSecretArn === undefined) return {};
|
|
59
|
+
return {
|
|
60
|
+
repository: config.repository,
|
|
61
|
+
accessToken: `{{resolve:secretsmanager:${config.repositoryAccessTokenSecretArn}:SecretString}}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
export class AmplifyAppShellStack extends Stack {
|
|
55
66
|
public readonly cmsAppId?: string;
|
|
56
67
|
public readonly readerAppId?: string;
|
|
@@ -130,7 +141,10 @@ export class AmplifyAppShellStack extends Stack {
|
|
|
130
141
|
);
|
|
131
142
|
}
|
|
132
143
|
|
|
144
|
+
const repositoryConnection = repositoryConnectionProperties(config);
|
|
145
|
+
|
|
133
146
|
const cmsApp = new amplify.CfnApp(this, "App", {
|
|
147
|
+
...repositoryConnection,
|
|
134
148
|
name: cmsAppName,
|
|
135
149
|
description: `Papyrus newsroom CMS for ${config.siteId} (WEB_COMPUTE)`,
|
|
136
150
|
platform: "WEB_COMPUTE",
|
|
@@ -389,6 +403,7 @@ export class AmplifyAppShellStack extends Stack {
|
|
|
389
403
|
);
|
|
390
404
|
|
|
391
405
|
const readerApp = new amplify.CfnApp(this, "ReaderApp", {
|
|
406
|
+
...repositoryConnectionProperties(config),
|
|
392
407
|
name: readerAppName,
|
|
393
408
|
description: `Papyrus static reader for ${config.siteId} (WEB)`,
|
|
394
409
|
platform: "WEB",
|
package/infra/site-config.js
CHANGED
|
@@ -5,6 +5,7 @@ export function hasCmsApp(config) {
|
|
|
5
5
|
export const DEFAULT_CI_BRANCHES = ["main", "staging"];
|
|
6
6
|
const SITE_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
7
7
|
const REPOSITORY_PATTERN = /^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
8
|
+
const SECRETS_MANAGER_SECRET_ARN_PATTERN = /^arn:aws:secretsmanager:[a-z0-9-]+:\d{12}:secret:[A-Za-z0-9/_+=.@-]+$/;
|
|
8
9
|
const HOSTED_ZONE_ID_PATTERN = /^Z[A-Z0-9]+$/;
|
|
9
10
|
const HOST_NAME_PATTERN = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/;
|
|
10
11
|
const DOMAIN_PREFIX_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
@@ -297,9 +298,12 @@ function validateOauthRedirectUrls(config) {
|
|
|
297
298
|
}
|
|
298
299
|
export function parseSiteConfig(raw) {
|
|
299
300
|
const record = requireObject(raw, "site");
|
|
300
|
-
rejectUnknownKeys(record, ["siteId", "repository", "brand", "frontend", "hostedZoneId", "stackName", "cms", "reader", "papyrusVersion", "storagePreviewPrefix", "github"], "site");
|
|
301
|
+
rejectUnknownKeys(record, ["siteId", "repository", "repositoryAccessTokenSecretArn", "brand", "frontend", "hostedZoneId", "stackName", "cms", "reader", "papyrusVersion", "storagePreviewPrefix", "github"], "site");
|
|
301
302
|
const siteId = requireString(record.siteId, "siteId", SITE_ID_PATTERN, "kebab-case");
|
|
302
303
|
const repository = requireString(record.repository, "repository", REPOSITORY_PATTERN, "https://github.com/<org>/<repo>");
|
|
304
|
+
const repositoryAccessTokenSecretArn = record.repositoryAccessTokenSecretArn === undefined
|
|
305
|
+
? undefined
|
|
306
|
+
: requireString(record.repositoryAccessTokenSecretArn, "repositoryAccessTokenSecretArn", SECRETS_MANAGER_SECRET_ARN_PATTERN, "Secrets Manager secret ARN");
|
|
303
307
|
const brand = requireString(record.brand, "brand");
|
|
304
308
|
const frontend = requireString(record.frontend, "frontend");
|
|
305
309
|
if (frontend !== "pretext" && frontend !== "markus-static") {
|
|
@@ -382,6 +386,7 @@ export function parseSiteConfig(raw) {
|
|
|
382
386
|
const config = {
|
|
383
387
|
siteId,
|
|
384
388
|
repository,
|
|
389
|
+
repositoryAccessTokenSecretArn,
|
|
385
390
|
brand,
|
|
386
391
|
frontend,
|
|
387
392
|
hostedZoneId,
|
package/infra/site-config.ts
CHANGED
|
@@ -47,6 +47,7 @@ export type CmsConfig = {
|
|
|
47
47
|
export type AmplifyAppShellSiteConfig = {
|
|
48
48
|
siteId: string;
|
|
49
49
|
repository: string;
|
|
50
|
+
repositoryAccessTokenSecretArn?: string;
|
|
50
51
|
brand: string;
|
|
51
52
|
frontend: "pretext" | "markus-static";
|
|
52
53
|
hostedZoneId?: string;
|
|
@@ -85,6 +86,7 @@ export const DEFAULT_CI_BRANCHES = ["main", "staging"];
|
|
|
85
86
|
|
|
86
87
|
const SITE_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
87
88
|
const REPOSITORY_PATTERN = /^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
89
|
+
const SECRETS_MANAGER_SECRET_ARN_PATTERN = /^arn:aws:secretsmanager:[a-z0-9-]+:\d{12}:secret:[A-Za-z0-9/_+=.@-]+$/;
|
|
88
90
|
const HOSTED_ZONE_ID_PATTERN = /^Z[A-Z0-9]+$/;
|
|
89
91
|
const HOST_NAME_PATTERN = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/;
|
|
90
92
|
const DOMAIN_PREFIX_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
@@ -392,12 +394,15 @@ export function parseSiteConfig(raw: unknown): AmplifyAppShellSiteConfig {
|
|
|
392
394
|
const record = requireObject(raw, "site");
|
|
393
395
|
rejectUnknownKeys(
|
|
394
396
|
record,
|
|
395
|
-
["siteId", "repository", "brand", "frontend", "hostedZoneId", "stackName", "cms", "reader", "papyrusVersion", "storagePreviewPrefix", "github"],
|
|
397
|
+
["siteId", "repository", "repositoryAccessTokenSecretArn", "brand", "frontend", "hostedZoneId", "stackName", "cms", "reader", "papyrusVersion", "storagePreviewPrefix", "github"],
|
|
396
398
|
"site",
|
|
397
399
|
);
|
|
398
400
|
|
|
399
401
|
const siteId = requireString(record.siteId, "siteId", SITE_ID_PATTERN, "kebab-case");
|
|
400
402
|
const repository = requireString(record.repository, "repository", REPOSITORY_PATTERN, "https://github.com/<org>/<repo>");
|
|
403
|
+
const repositoryAccessTokenSecretArn = record.repositoryAccessTokenSecretArn === undefined
|
|
404
|
+
? undefined
|
|
405
|
+
: requireString(record.repositoryAccessTokenSecretArn, "repositoryAccessTokenSecretArn", SECRETS_MANAGER_SECRET_ARN_PATTERN, "Secrets Manager secret ARN");
|
|
401
406
|
const brand = requireString(record.brand, "brand");
|
|
402
407
|
const frontend = requireString(record.frontend, "frontend");
|
|
403
408
|
if (frontend !== "pretext" && frontend !== "markus-static") {
|
|
@@ -480,6 +485,7 @@ export function parseSiteConfig(raw: unknown): AmplifyAppShellSiteConfig {
|
|
|
480
485
|
const config: AmplifyAppShellSiteConfig = {
|
|
481
486
|
siteId,
|
|
482
487
|
repository,
|
|
488
|
+
repositoryAccessTokenSecretArn,
|
|
483
489
|
brand,
|
|
484
490
|
frontend,
|
|
485
491
|
hostedZoneId,
|
package/package.json
CHANGED
package/routes.manifest.json
CHANGED