@staticforge/aws 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +6 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/clients.d.ts +22 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +64 -0
- package/dist/clients.js.map +1 -0
- package/dist/deployer.d.ts +6 -0
- package/dist/deployer.d.ts.map +1 -0
- package/dist/deployer.js +379 -0
- package/dist/deployer.js.map +1 -0
- package/dist/iac.d.ts +26 -0
- package/dist/iac.d.ts.map +1 -0
- package/dist/iac.js +223 -0
- package/dist/iac.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/routing.d.ts +32 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +111 -0
- package/dist/routing.js.map +1 -0
- package/package.json +59 -3
- package/terraform/modules/site/cdn.tf +191 -0
- package/terraform/modules/site/ci.tf +117 -0
- package/terraform/modules/site/domain.tf +77 -0
- package/terraform/modules/site/logging.tf +82 -0
- package/terraform/modules/site/outputs.tf +69 -0
- package/terraform/modules/site/router.js +136 -0
- package/terraform/modules/site/router.tf +33 -0
- package/terraform/modules/site/storage.tf +107 -0
- package/terraform/modules/site/variables.tf +106 -0
- package/terraform/modules/site/versions.tf +11 -0
- package/terraform/state-bootstrap/main.tf +104 -0
- package/terraform/state-bootstrap/outputs.tf +11 -0
- package/terraform/state-bootstrap/variables.tf +21 -0
- package/terraform/state-bootstrap/versions.tf +10 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import '@aws-sdk/signature-v4a';
|
|
2
|
+
import { CloudFrontClient } from '@aws-sdk/client-cloudfront';
|
|
3
|
+
import { CloudFrontKeyValueStoreClient } from '@aws-sdk/client-cloudfront-keyvaluestore';
|
|
4
|
+
import { IAMClient } from '@aws-sdk/client-iam';
|
|
5
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
6
|
+
import { STSClient } from '@aws-sdk/client-sts';
|
|
7
|
+
import { SforgeError } from '@staticforge/core';
|
|
8
|
+
/** SDK clients, injectable for tests. Credentials come from the default chain. */
|
|
9
|
+
export interface AwsClients {
|
|
10
|
+
s3(region: string): S3Client;
|
|
11
|
+
sts(region: string): STSClient;
|
|
12
|
+
iam(): IAMClient;
|
|
13
|
+
cloudfront(): CloudFrontClient;
|
|
14
|
+
kvs(): CloudFrontKeyValueStoreClient;
|
|
15
|
+
}
|
|
16
|
+
export declare function defaultClients(): AwsClients;
|
|
17
|
+
/** Error name of an SDK error ("NoSuchKey", "AccessDenied", …). */
|
|
18
|
+
export declare function errorName(error: unknown): string;
|
|
19
|
+
export declare function httpStatus(error: unknown): number | undefined;
|
|
20
|
+
/** Wrap an SDK error: credential problems → SF_CLOUD_AUTH, the rest → `code`. */
|
|
21
|
+
export declare function awsError(error: unknown, what: string, code?: SforgeError['code']): SforgeError;
|
|
22
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAEA,OAAO,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAa,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE3D,kFAAkF;AAClF,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,GAAG,IAAI,SAAS,CAAC;IACjB,UAAU,IAAI,gBAAgB,CAAC;IAC/B,GAAG,IAAI,6BAA6B,CAAC;CACtC;AAED,wBAAgB,cAAc,IAAI,UAAU,CAa3C;AAYD,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7D;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,WAAW,CAAC,MAAM,CAA0B,GACjD,WAAW,CAiBb"}
|
package/dist/clients.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// KeyValueStore requests are signed with SigV4a; this registers the pure-JS
|
|
2
|
+
// signer, so the native CRT is not needed.
|
|
3
|
+
import '@aws-sdk/signature-v4a';
|
|
4
|
+
import { CloudFrontClient } from '@aws-sdk/client-cloudfront';
|
|
5
|
+
import { CloudFrontKeyValueStoreClient } from '@aws-sdk/client-cloudfront-keyvaluestore';
|
|
6
|
+
import { IAMClient } from '@aws-sdk/client-iam';
|
|
7
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
8
|
+
import { STSClient } from '@aws-sdk/client-sts';
|
|
9
|
+
import { ErrorCode, SforgeError } from '@staticforge/core';
|
|
10
|
+
export function defaultClients() {
|
|
11
|
+
const cache = new Map();
|
|
12
|
+
const once = (key, create) => {
|
|
13
|
+
if (!cache.has(key))
|
|
14
|
+
cache.set(key, create());
|
|
15
|
+
return cache.get(key);
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
s3: (region) => once(`s3:${region}`, () => new S3Client({ region })),
|
|
19
|
+
sts: (region) => once(`sts:${region}`, () => new STSClient({ region })),
|
|
20
|
+
iam: () => once('iam', () => new IAMClient({ region: 'us-east-1' })),
|
|
21
|
+
cloudfront: () => once('cloudfront', () => new CloudFrontClient({ region: 'us-east-1' })),
|
|
22
|
+
kvs: () => once('kvs', () => new CloudFrontKeyValueStoreClient({ region: 'us-east-1' })),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const AUTH_ERRORS = new Set([
|
|
26
|
+
'CredentialsProviderError',
|
|
27
|
+
'ExpiredToken',
|
|
28
|
+
'ExpiredTokenException',
|
|
29
|
+
'InvalidClientTokenId',
|
|
30
|
+
'UnrecognizedClientException',
|
|
31
|
+
'TokenRefreshRequired',
|
|
32
|
+
'SignatureDoesNotMatch',
|
|
33
|
+
]);
|
|
34
|
+
/** Error name of an SDK error ("NoSuchKey", "AccessDenied", …). */
|
|
35
|
+
export function errorName(error) {
|
|
36
|
+
if (error === null || typeof error !== 'object')
|
|
37
|
+
return '';
|
|
38
|
+
const e = error;
|
|
39
|
+
return e.Code ?? e.name ?? '';
|
|
40
|
+
}
|
|
41
|
+
export function httpStatus(error) {
|
|
42
|
+
return error?.$metadata?.httpStatusCode;
|
|
43
|
+
}
|
|
44
|
+
/** Wrap an SDK error: credential problems → SF_CLOUD_AUTH, the rest → `code`. */
|
|
45
|
+
export function awsError(error, what, code = ErrorCode.DeployFailed) {
|
|
46
|
+
if (error instanceof SforgeError)
|
|
47
|
+
return error;
|
|
48
|
+
const name = errorName(error);
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
if (AUTH_ERRORS.has(name) || /credential|sso session|token.*expired/i.test(message)) {
|
|
51
|
+
return new SforgeError(ErrorCode.CloudAuth, `${what}: ${message}`, {
|
|
52
|
+
cause: error,
|
|
53
|
+
hint: 'Sign in to AWS (e.g. `aws sso login`, or set AWS_PROFILE) and try again.',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (name === 'AccessDenied' || name === 'AccessDeniedException') {
|
|
57
|
+
return new SforgeError(ErrorCode.CloudAuth, `${what}: access denied (${message})`, {
|
|
58
|
+
cause: error,
|
|
59
|
+
hint: 'The AWS identity in use lacks a permission this operation needs.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return new SforgeError(code, `${what}: ${message}`, { cause: error, details: { error: name } });
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Deployer, type DeployerContext } from '@staticforge/provider-api';
|
|
2
|
+
import { type AwsClients } from './clients.js';
|
|
3
|
+
/** Outputs of terraform/modules/site the deployer needs. */
|
|
4
|
+
export declare const REQUIRED_OUTPUTS: string[];
|
|
5
|
+
export declare function createAwsDeployer(context: DeployerContext, clients?: AwsClients): Deployer;
|
|
6
|
+
//# sourceMappingURL=deployer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAgBA,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,eAAe,EAYrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,UAAU,EAAmD,MAAM,cAAc,CAAC;AAShG,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,UAAmE,CAAC;AAqEjG,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,UAA6B,GACrC,QAAQ,CAoZV"}
|
package/dist/deployer.js
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { createReadStream } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
|
|
4
|
+
import { DescribeKeyValueStoreCommand, UpdateKeysCommand, } from '@aws-sdk/client-cloudfront-keyvaluestore';
|
|
5
|
+
import { CopyObjectCommand, DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, } from '@aws-sdk/client-s3';
|
|
6
|
+
import { ErrorCode, SforgeError } from '@staticforge/core';
|
|
7
|
+
import { assertPreviewId, cacheControl, contentType, diffManifests, gitShortSha, mapLimit, newVersionId, publishedFiles, readManifest, } from '@staticforge/provider-api';
|
|
8
|
+
import { awsError, defaultClients, errorName, httpStatus } from './clients.js';
|
|
9
|
+
import { routeExceptions } from './routing.js';
|
|
10
|
+
/** Bookkeeping objects; the router never serves them (every URL is prefixed with v/<id>/). */
|
|
11
|
+
const VERSIONS_KEY = '_sforge/versions.json';
|
|
12
|
+
const ERROR_PAGE_KEY = '_sforge/errors/404.html';
|
|
13
|
+
const manifestKey = (id) => `_sforge/manifests/${id}.json`;
|
|
14
|
+
const versionPrefix = (id) => `v/${id}/`;
|
|
15
|
+
/** Outputs of terraform/modules/site the deployer needs. */
|
|
16
|
+
export const REQUIRED_OUTPUTS = ['bucket', 'bucket_region', 'kvs_arn', 'distribution_id', 'url'];
|
|
17
|
+
const UPLOAD_CONCURRENCY = 16;
|
|
18
|
+
/** UpdateKeys accepts at most 50 puts and deletes per call. */
|
|
19
|
+
const KVS_BATCH = 50;
|
|
20
|
+
const emptyDocument = () => ({
|
|
21
|
+
schemaVersion: 1,
|
|
22
|
+
active: null,
|
|
23
|
+
versions: [],
|
|
24
|
+
previews: [],
|
|
25
|
+
});
|
|
26
|
+
function readOutputs(context) {
|
|
27
|
+
const o = context.outputs;
|
|
28
|
+
const missing = REQUIRED_OUTPUTS.filter((name) => typeof o[name] !== 'string');
|
|
29
|
+
if (missing.length > 0) {
|
|
30
|
+
throw new SforgeError(ErrorCode.NotProvisioned, `Target "${context.targetName}" is missing infrastructure outputs: ${missing.join(', ')}`, { hint: `Run \`sforge provision ${context.targetName}\`.` });
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
bucket: o.bucket,
|
|
34
|
+
region: o.bucket_region,
|
|
35
|
+
kvsArn: o.kvs_arn,
|
|
36
|
+
distributionId: o.distribution_id,
|
|
37
|
+
url: o.url,
|
|
38
|
+
previewDomain: typeof o.preview_domain === 'string' ? o.preview_domain : null,
|
|
39
|
+
trailingSlash: o.trailing_slash === 'never' || o.trailing_slash === 'always'
|
|
40
|
+
? o.trailing_slash
|
|
41
|
+
: context.config.build.trailingSlash,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** S3 CopySource: bucket/key, URL-encoded per segment. */
|
|
45
|
+
const copySource = (bucket, key) => `${bucket}/${key.split('/').map(encodeURIComponent).join('/')}`;
|
|
46
|
+
export function createAwsDeployer(context, clients = defaultClients()) {
|
|
47
|
+
const target = context.target;
|
|
48
|
+
const { logger } = context;
|
|
49
|
+
let resolved;
|
|
50
|
+
const out = () => (resolved ??= readOutputs(context));
|
|
51
|
+
const s3 = () => clients.s3(out().region);
|
|
52
|
+
async function getJson(key) {
|
|
53
|
+
try {
|
|
54
|
+
const response = await s3().send(new GetObjectCommand({ Bucket: out().bucket, Key: key }));
|
|
55
|
+
const text = await response.Body.transformToString('utf8');
|
|
56
|
+
return { value: JSON.parse(text), etag: response.ETag };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (errorName(error) === 'NoSuchKey' || httpStatus(error) === 404)
|
|
60
|
+
return undefined;
|
|
61
|
+
throw awsError(error, `Could not read s3://${out().bucket}/${key}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function putJson(key, value, condition) {
|
|
65
|
+
try {
|
|
66
|
+
await s3().send(new PutObjectCommand({
|
|
67
|
+
Bucket: out().bucket,
|
|
68
|
+
Key: key,
|
|
69
|
+
Body: `${JSON.stringify(value, null, 2)}\n`,
|
|
70
|
+
ContentType: 'application/json',
|
|
71
|
+
CacheControl: 'no-store',
|
|
72
|
+
...(condition?.ifMatch && { IfMatch: condition.ifMatch }),
|
|
73
|
+
...(condition?.ifNoneMatch && { IfNoneMatch: condition.ifNoneMatch }),
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (httpStatus(error) === 412 ||
|
|
78
|
+
errorName(error) === 'PreconditionFailed' ||
|
|
79
|
+
httpStatus(error) === 409) {
|
|
80
|
+
throw new SforgeError(ErrorCode.DeployFailed, `Another deploy to "${context.targetName}" changed ${key} at the same time`, { hint: `Check \`sforge versions ${context.targetName}\`, then deploy again.` });
|
|
81
|
+
}
|
|
82
|
+
throw awsError(error, `Could not write s3://${out().bucket}/${key}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function loadDocument() {
|
|
86
|
+
const found = await getJson(VERSIONS_KEY);
|
|
87
|
+
return found === undefined
|
|
88
|
+
? { doc: emptyDocument(), etag: undefined }
|
|
89
|
+
: { doc: found.value, etag: found.etag };
|
|
90
|
+
}
|
|
91
|
+
const saveDocument = (doc, etag) => putJson(VERSIONS_KEY, doc, etag === undefined ? { ifNoneMatch: '*' } : { ifMatch: etag });
|
|
92
|
+
async function listKeys(prefix) {
|
|
93
|
+
const keys = [];
|
|
94
|
+
let token;
|
|
95
|
+
do {
|
|
96
|
+
const page = await s3().send(new ListObjectsV2Command({
|
|
97
|
+
Bucket: out().bucket,
|
|
98
|
+
Prefix: prefix,
|
|
99
|
+
ContinuationToken: token,
|
|
100
|
+
}));
|
|
101
|
+
for (const object of page.Contents ?? [])
|
|
102
|
+
if (object.Key)
|
|
103
|
+
keys.push(object.Key);
|
|
104
|
+
token = page.IsTruncated ? page.NextContinuationToken : undefined;
|
|
105
|
+
} while (token !== undefined);
|
|
106
|
+
return keys;
|
|
107
|
+
}
|
|
108
|
+
async function deleteKeys(keys) {
|
|
109
|
+
for (let i = 0; i < keys.length; i += 1000) {
|
|
110
|
+
const batch = keys.slice(i, i + 1000);
|
|
111
|
+
const result = await s3().send(new DeleteObjectsCommand({
|
|
112
|
+
Bucket: out().bucket,
|
|
113
|
+
Delete: { Objects: batch.map((Key) => ({ Key })), Quiet: true },
|
|
114
|
+
}));
|
|
115
|
+
if (result.Errors !== undefined && result.Errors.length > 0) {
|
|
116
|
+
throw new SforgeError(ErrorCode.DeployFailed, `Could not delete ${result.Errors.length} objects (${result.Errors[0]?.Key}: ${result.Errors[0]?.Message})`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return keys.length;
|
|
120
|
+
}
|
|
121
|
+
async function updateKvs(puts, deletes = []) {
|
|
122
|
+
const changes = [
|
|
123
|
+
...Object.entries(puts).map(([k, v]) => ({ put: [k, v] })),
|
|
124
|
+
...deletes.filter((k) => !(k in puts)).map((k) => ({ del: k })),
|
|
125
|
+
];
|
|
126
|
+
if (changes.length === 0)
|
|
127
|
+
return;
|
|
128
|
+
const kvs = clients.kvs();
|
|
129
|
+
let etag = (await kvs.send(new DescribeKeyValueStoreCommand({ KvsARN: out().kvsArn }))).ETag;
|
|
130
|
+
for (let i = 0; i < changes.length; i += KVS_BATCH) {
|
|
131
|
+
const batch = changes.slice(i, i + KVS_BATCH);
|
|
132
|
+
const response = await kvs.send(new UpdateKeysCommand({
|
|
133
|
+
KvsARN: out().kvsArn,
|
|
134
|
+
IfMatch: etag,
|
|
135
|
+
Puts: batch.flatMap((c) => ('put' in c ? [{ Key: c.put[0], Value: c.put[1] }] : [])),
|
|
136
|
+
Deletes: batch.flatMap((c) => ('del' in c ? [{ Key: c.del }] : [])),
|
|
137
|
+
}));
|
|
138
|
+
etag = response.ETag;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const routeKey = (id, key) => `r:${id}:${key}`;
|
|
142
|
+
/** Point CloudFront's 404 page at a version (error responses bypass the router). */
|
|
143
|
+
async function publishErrorPage(id, manifest) {
|
|
144
|
+
if (manifest !== undefined && manifest.files['404.html'] === undefined)
|
|
145
|
+
return;
|
|
146
|
+
await s3().send(new CopyObjectCommand({
|
|
147
|
+
Bucket: out().bucket,
|
|
148
|
+
Key: ERROR_PAGE_KEY,
|
|
149
|
+
CopySource: copySource(out().bucket, `${versionPrefix(id)}404.html`),
|
|
150
|
+
MetadataDirective: 'REPLACE',
|
|
151
|
+
ContentType: 'text/html; charset=utf-8',
|
|
152
|
+
CacheControl: 'public, max-age=0, must-revalidate',
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
async function removeVersion(record, extraKvsDeletes = []) {
|
|
156
|
+
const deleted = await deleteKeys(await listKeys(versionPrefix(record.id)));
|
|
157
|
+
await deleteKeys([manifestKey(record.id)]);
|
|
158
|
+
await updateKvs({}, [...record.routes.map((k) => routeKey(record.id, k)), ...extraKvsDeletes]);
|
|
159
|
+
return deleted;
|
|
160
|
+
}
|
|
161
|
+
const previewUrl = (id) => `https://${id}.${out().previewDomain}`;
|
|
162
|
+
return {
|
|
163
|
+
previewBaseUrl: (id) => target.previewDomain === undefined ? undefined : `https://${id}.${target.previewDomain}`,
|
|
164
|
+
async current() {
|
|
165
|
+
const { doc } = await loadDocument();
|
|
166
|
+
return { url: out().url, versionId: doc.active };
|
|
167
|
+
},
|
|
168
|
+
async versions() {
|
|
169
|
+
const { doc } = await loadDocument();
|
|
170
|
+
const toVersion = (r, preview) => ({
|
|
171
|
+
id: r.id,
|
|
172
|
+
createdAt: r.createdAt,
|
|
173
|
+
...(r.gitSha && { gitSha: r.gitSha }),
|
|
174
|
+
files: r.files,
|
|
175
|
+
bytes: r.bytes,
|
|
176
|
+
active: !preview && r.id === doc.active,
|
|
177
|
+
preview,
|
|
178
|
+
...(preview && out().previewDomain !== null && { url: previewUrl(r.id) }),
|
|
179
|
+
});
|
|
180
|
+
return [
|
|
181
|
+
...[...doc.versions].reverse().map((r) => toVersion(r, false)),
|
|
182
|
+
...doc.previews.map((r) => toVersion(r, true)),
|
|
183
|
+
];
|
|
184
|
+
},
|
|
185
|
+
async deploy(options) {
|
|
186
|
+
const o = out();
|
|
187
|
+
const manifest = readManifest(options.buildDir);
|
|
188
|
+
const preview = options.preview;
|
|
189
|
+
if (preview !== undefined) {
|
|
190
|
+
assertPreviewId(preview);
|
|
191
|
+
if (o.previewDomain === null) {
|
|
192
|
+
throw new SforgeError(ErrorCode.Unsupported, `Target "${context.targetName}" has no previewDomain, so it cannot serve PR previews`, {
|
|
193
|
+
hint: 'On AWS, previews are served at <id>.<previewDomain> with a wildcard certificate: ' +
|
|
194
|
+
`set targets.${context.targetName}.domain and previewDomain, then run \`sforge provision ${context.targetName}\`.`,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const { doc, etag } = await loadDocument();
|
|
199
|
+
const gitSha = options.gitSha ?? gitShortSha(context.rootDir, context.env);
|
|
200
|
+
const id = preview ?? newVersionId(options.now ?? new Date(), gitSha);
|
|
201
|
+
if (preview === undefined && doc.versions.some((v) => v.id === id)) {
|
|
202
|
+
throw new SforgeError(ErrorCode.DeployFailed, `Version ${id} already exists; deploy again in a second`);
|
|
203
|
+
}
|
|
204
|
+
const existingPreview = preview === undefined ? undefined : doc.previews.find((p) => p.id === preview);
|
|
205
|
+
const previousId = preview === undefined ? (doc.active ?? undefined) : existingPreview?.id;
|
|
206
|
+
const previous = previousId === undefined
|
|
207
|
+
? undefined
|
|
208
|
+
: (await getJson(manifestKey(previousId)))?.value;
|
|
209
|
+
const diff = diffManifests(manifest, previous, preview !== undefined);
|
|
210
|
+
const files = publishedFiles(manifest);
|
|
211
|
+
const routes = routeExceptions(files.map(([path]) => path), o.trailingSlash, id);
|
|
212
|
+
for (const url of routes.skipped)
|
|
213
|
+
logger.warn(`URL too long for the CloudFront router, not served as locally: ${url}`);
|
|
214
|
+
const count = (change) => diff.files.filter((f) => f.change === change).length;
|
|
215
|
+
const bytes = diff.files
|
|
216
|
+
.filter((f) => f.change === 'upload')
|
|
217
|
+
.reduce((sum, f) => sum + f.entry.size, 0);
|
|
218
|
+
const url = preview === undefined ? o.url : previewUrl(preview);
|
|
219
|
+
const result = {
|
|
220
|
+
target: context.targetName,
|
|
221
|
+
provider: 'aws',
|
|
222
|
+
versionId: id,
|
|
223
|
+
url,
|
|
224
|
+
preview: preview !== undefined,
|
|
225
|
+
uploaded: count('upload'),
|
|
226
|
+
copied: count('copy'),
|
|
227
|
+
skipped: count('unchanged'),
|
|
228
|
+
deleted: diff.removed.length,
|
|
229
|
+
bytes,
|
|
230
|
+
pruned: [],
|
|
231
|
+
invalidated: false,
|
|
232
|
+
dryRun: options.dryRun === true,
|
|
233
|
+
...(previousId !== undefined && { previousVersionId: previousId }),
|
|
234
|
+
};
|
|
235
|
+
if (options.dryRun)
|
|
236
|
+
return result;
|
|
237
|
+
const prefix = versionPrefix(id);
|
|
238
|
+
logger.info(`Uploading ${result.uploaded} files to s3://${o.bucket}/${prefix}` +
|
|
239
|
+
(result.copied > 0 ? `, copying ${result.copied} unchanged` : ''));
|
|
240
|
+
try {
|
|
241
|
+
await mapLimit(diff.files, UPLOAD_CONCURRENCY, async (file) => {
|
|
242
|
+
if (file.change === 'unchanged')
|
|
243
|
+
return;
|
|
244
|
+
const key = `${prefix}${file.path}`;
|
|
245
|
+
if (file.change === 'copy') {
|
|
246
|
+
await s3().send(new CopyObjectCommand({
|
|
247
|
+
Bucket: o.bucket,
|
|
248
|
+
Key: key,
|
|
249
|
+
CopySource: copySource(o.bucket, `${versionPrefix(previousId)}${file.path}`),
|
|
250
|
+
}));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
await s3().send(new PutObjectCommand({
|
|
254
|
+
Bucket: o.bucket,
|
|
255
|
+
Key: key,
|
|
256
|
+
Body: createReadStream(join(options.buildDir, file.path)),
|
|
257
|
+
ContentLength: file.entry.size,
|
|
258
|
+
ContentType: contentType(file.path),
|
|
259
|
+
CacheControl: cacheControl(file.entry.cache),
|
|
260
|
+
ChecksumSHA256: Buffer.from(file.entry.sha256, 'hex').toString('base64'),
|
|
261
|
+
Metadata: { sha256: file.entry.sha256 },
|
|
262
|
+
}));
|
|
263
|
+
logger.debug(`uploaded ${file.path}`);
|
|
264
|
+
});
|
|
265
|
+
if (diff.removed.length > 0)
|
|
266
|
+
await deleteKeys(diff.removed.map((path) => `${prefix}${path}`));
|
|
267
|
+
await putJson(manifestKey(id), manifest);
|
|
268
|
+
const routeKeys = Object.keys(routes.entries);
|
|
269
|
+
await updateKvs(Object.fromEntries(Object.entries(routes.entries).map(([k, v]) => [routeKey(id, k), v])), (existingPreview?.routes ?? [])
|
|
270
|
+
.filter((k) => !(k in routes.entries))
|
|
271
|
+
.map((k) => routeKey(id, k)));
|
|
272
|
+
// Smoke check: the new version is complete in S3 before it goes live.
|
|
273
|
+
const probe = manifest.files['index.html'] !== undefined ? 'index.html' : files[0]?.[0];
|
|
274
|
+
if (probe !== undefined) {
|
|
275
|
+
await s3().send(new HeadObjectCommand({ Bucket: o.bucket, Key: `${prefix}${probe}` }));
|
|
276
|
+
}
|
|
277
|
+
const record = {
|
|
278
|
+
id,
|
|
279
|
+
createdAt: (options.now ?? new Date()).toISOString(),
|
|
280
|
+
...(gitSha && { gitSha }),
|
|
281
|
+
files: files.length,
|
|
282
|
+
bytes: files.reduce((sum, [, entry]) => sum + entry.size, 0),
|
|
283
|
+
routes: routeKeys,
|
|
284
|
+
};
|
|
285
|
+
if (preview === undefined) {
|
|
286
|
+
await publishErrorPage(id, manifest);
|
|
287
|
+
await updateKvs({ active: id });
|
|
288
|
+
logger.info(`Version ${id} is live at ${o.url}`);
|
|
289
|
+
doc.active = id;
|
|
290
|
+
doc.versions.push(record);
|
|
291
|
+
const excess = doc.versions.length - target.retainVersions;
|
|
292
|
+
if (excess > 0) {
|
|
293
|
+
const old = doc.versions.filter((v) => v.id !== id).slice(0, excess);
|
|
294
|
+
for (const version of old) {
|
|
295
|
+
logger.info(`Removing old version ${version.id}`);
|
|
296
|
+
await removeVersion(version);
|
|
297
|
+
result.pruned.push(version.id);
|
|
298
|
+
}
|
|
299
|
+
doc.versions = doc.versions.filter((v) => !result.pruned.includes(v.id));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
await updateKvs({ [`host:${preview}`]: id });
|
|
304
|
+
logger.info(`Preview ${preview} is live at ${url}`);
|
|
305
|
+
doc.previews = [...doc.previews.filter((p) => p.id !== preview), record];
|
|
306
|
+
}
|
|
307
|
+
await saveDocument(doc, etag);
|
|
308
|
+
if (options.invalidate) {
|
|
309
|
+
await clients.cloudfront().send(new CreateInvalidationCommand({
|
|
310
|
+
DistributionId: o.distributionId,
|
|
311
|
+
InvalidationBatch: {
|
|
312
|
+
CallerReference: `sforge-${id}-${Date.now()}`,
|
|
313
|
+
Paths: { Quantity: 1, Items: ['/*'] },
|
|
314
|
+
},
|
|
315
|
+
}));
|
|
316
|
+
result.invalidated = true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
throw awsError(error, `Deploy to "${context.targetName}" failed`);
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
},
|
|
324
|
+
async rollback(to) {
|
|
325
|
+
const { doc, etag } = await loadDocument();
|
|
326
|
+
if (doc.active === null) {
|
|
327
|
+
throw new SforgeError(ErrorCode.VersionNotFound, `Nothing has been deployed to "${context.targetName}"`);
|
|
328
|
+
}
|
|
329
|
+
const index = doc.versions.findIndex((v) => v.id === doc.active);
|
|
330
|
+
const version = to === undefined ? doc.versions[index - 1] : doc.versions.find((v) => v.id === to);
|
|
331
|
+
if (version === undefined) {
|
|
332
|
+
const known = doc.versions.map((v) => v.id);
|
|
333
|
+
throw new SforgeError(ErrorCode.VersionNotFound, to === undefined
|
|
334
|
+
? `There is no version before ${doc.active} to roll back to`
|
|
335
|
+
: `Version ${to} is not retained for "${context.targetName}"`, {
|
|
336
|
+
details: { versions: known },
|
|
337
|
+
hint: `List versions with \`sforge versions ${context.targetName}\`.`,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
const previous = doc.active;
|
|
341
|
+
try {
|
|
342
|
+
const manifest = (await getJson(manifestKey(version.id)))?.value;
|
|
343
|
+
await publishErrorPage(version.id, manifest);
|
|
344
|
+
await updateKvs({ active: version.id });
|
|
345
|
+
doc.active = version.id;
|
|
346
|
+
await saveDocument(doc, etag);
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
throw awsError(error, `Rollback of "${context.targetName}" failed`);
|
|
350
|
+
}
|
|
351
|
+
logger.info(`"${context.targetName}" now serves ${version.id}`);
|
|
352
|
+
return {
|
|
353
|
+
target: context.targetName,
|
|
354
|
+
versionId: version.id,
|
|
355
|
+
previousVersionId: previous,
|
|
356
|
+
url: out().url,
|
|
357
|
+
};
|
|
358
|
+
},
|
|
359
|
+
async destroyPreview(previewId) {
|
|
360
|
+
assertPreviewId(previewId);
|
|
361
|
+
const { doc, etag } = await loadDocument();
|
|
362
|
+
const record = doc.previews.find((p) => p.id === previewId);
|
|
363
|
+
try {
|
|
364
|
+
const deleted = record
|
|
365
|
+
? await removeVersion(record, [`host:${previewId}`])
|
|
366
|
+
: await deleteKeys(await listKeys(versionPrefix(previewId)));
|
|
367
|
+
if (record !== undefined) {
|
|
368
|
+
doc.previews = doc.previews.filter((p) => p.id !== previewId);
|
|
369
|
+
await saveDocument(doc, etag);
|
|
370
|
+
}
|
|
371
|
+
return { target: context.targetName, previewId, deleted, existed: record !== undefined };
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
throw awsError(error, `Removing preview ${previewId} failed`);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=deployer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployer.js","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"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"}
|
package/dist/iac.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type AwsTargetConfig } from '@staticforge/core';
|
|
2
|
+
import { type IacProfile } from '@staticforge/iac';
|
|
3
|
+
import { type AwsClients } from './clients.js';
|
|
4
|
+
export declare const SITE_MODULE_DIR: string;
|
|
5
|
+
export declare const STATE_BOOTSTRAP_DIR: string;
|
|
6
|
+
export interface StateLocation {
|
|
7
|
+
bucket: string;
|
|
8
|
+
region: string;
|
|
9
|
+
key: string;
|
|
10
|
+
}
|
|
11
|
+
/** `sforge-state-<accountId>-<region>` unless configured, key `<site>/<target>.tfstate`. */
|
|
12
|
+
export declare function stateLocation(target: AwsTargetConfig, accountId: string, project: string, targetName: string): StateLocation;
|
|
13
|
+
export interface OidcProviderChoice {
|
|
14
|
+
create: boolean;
|
|
15
|
+
arn?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The account's GitHub OIDC provider is shared: reuse an existing one, unless
|
|
19
|
+
* this target created it (tagged `sforge:owner = <site>-<target>`), in which
|
|
20
|
+
* case it stays managed here.
|
|
21
|
+
*/
|
|
22
|
+
export declare function chooseOidcProvider(clients: AwsClients, owner: string): Promise<OidcProviderChoice>;
|
|
23
|
+
/** Instructions for DNS records the user must create (no Route 53 hosted zone). */
|
|
24
|
+
export declare function describeValidation(outputs: Record<string, unknown>): string | undefined;
|
|
25
|
+
export declare function createAwsIacProfile(clients?: AwsClients): IacProfile;
|
|
26
|
+
//# sourceMappingURL=iac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iac.d.ts","sourceRoot":"","sources":["../src/iac.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAA0B,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAEL,KAAK,UAAU,EAKhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,UAAU,EAAmD,MAAM,cAAc,CAAC;AAMhG,eAAO,MAAM,eAAe,QAA+B,CAAC;AAC5D,eAAO,MAAM,mBAAmB,QAAkC,CAAC;AAKnE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,aAAa,CAOf;AAgDD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC,CAgB7B;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CASvF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,UAA6B,GAAG,UAAU,CA2ItF"}
|