/
index.ts
143 lines (131 loc) · 4.25 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import {
BuilderContext,
BuilderOutput,
createBuilder,
targetFromTargetString,
} from '@angular-devkit/architect';
import * as glob from 'glob';
import { getAccessKeyId, getSecretAccessKey } from './config';
import { CloudFront } from './cloudfront';
import { Schema } from './schema';
import { Uploader } from './uploader';
const getFiles = (filesPath: string) => {
return glob.sync(`**`, {
ignore: ['.git'],
cwd: filesPath,
nodir: true,
// Directory and file names may contain `.` at the beginning,
// e.g. `.well-known/apple-app-site-association`.
dot: true,
});
};
export default createBuilder(
async (
builderConfig: Schema,
context: BuilderContext
): Promise<BuilderOutput> => {
context.reportStatus('Executing deployment');
if (!context.target) {
throw new Error('Cannot deploy the application without a target');
}
const buildTarget = {
name:
builderConfig.buildTarget ||
`${context.target.project}:build:production`,
};
let targetString = `${context.target.project}:deploy`;
// Providing `region`, `bucket` and `subFolder` through configuration is actually deprecated.
// By default `ng add` command doesn't generate any additional configuration inside
// the builder configuration thus `context.target.configuration` defaults to an empty string.
if (context.target.configuration) {
targetString += `:${context.target.configuration}`;
}
const {
bucket,
region,
subFolder,
globFileUploadParamsList,
} = await context.getTargetOptions(targetFromTargetString(targetString));
const deployConfig = {
bucket,
region,
subFolder,
globFileUploadParamsList,
} as Pick<
Schema,
'bucket' | 'region' | 'subFolder' | 'globFileUploadParamsList'
>;
let buildResult: BuilderOutput;
if (builderConfig.noBuild) {
context.logger.info(`📦 Skipping build`);
const { outputPath } = await context.getTargetOptions(
targetFromTargetString(buildTarget.name)
);
buildResult = {
outputPath,
success: true,
};
} else {
const overrides = {
// this is an example how to override the workspace set of options
...(builderConfig.baseHref && { baseHref: builderConfig.baseHref }),
};
const build = await context.scheduleTarget(
targetFromTargetString(buildTarget.name),
{
...overrides,
}
);
buildResult = await build.result;
context.logger.info(`✔ Build Completed`);
}
if (buildResult.success) {
const { outputPath } = await context.getTargetOptions(
targetFromTargetString(buildTarget.name)
);
const files = getFiles(`${outputPath}`);
if (files.length === 0) {
throw new Error(
'Target did not produce any files, or the path is incorrect.'
);
}
if (getAccessKeyId() || getSecretAccessKey()) {
context.logger.info('Start uploading files...');
const uploader = new Uploader(context, deployConfig);
const success = await uploader.upload(files, `${outputPath}`);
if (success) {
context.logger.info('✔ Finished uploading files...');
context.logger.info('Start CloudFront invalidation...');
const cloudFront = new CloudFront(context, deployConfig);
const success = await cloudFront.invalidate();
if (success) {
context.logger.info('✔ Finished CloudFront invalidation...');
return { success: true };
} else {
context.logger.error(`❌ Error during CloudFront invalidation`);
return {
error: `❌ Error during CloudFront invalidation`,
success: false,
};
}
} else {
return {
error: `❌ Error during files upload`,
success: false,
};
}
} else {
context.logger.error(`❌ Missing authentication settings for AWS`);
return {
error: `❌ Missing authentication settings for AWS`,
success: false,
};
}
} else {
return {
error: `❌ Application build failed`,
success: false,
};
}
}
);