1 | import * as yargs from "yargs";
|
2 | import { loadDotenv } from "backfill-utils-dotenv";
|
3 | import { getCacheStorageProvider, ICacheStorage } from "backfill-cache";
|
4 | import { logger, setLogLevel } from "backfill-logger";
|
5 | import { createConfig, Config } from "backfill-config";
|
6 | import {
|
7 | getRawBuildCommand,
|
8 | createBuildCommand,
|
9 | BuildCommand
|
10 | } from "./commandRunner";
|
11 | import { IHasher, Hasher } from "backfill-hasher";
|
12 |
|
13 | export { createDefaultConfig } from "backfill-config";
|
14 |
|
15 | import { initializeWatcher, closeWatcher } from "./audit";
|
16 |
|
17 |
|
18 | loadDotenv();
|
19 |
|
20 | export async function backfill(
|
21 | config: Config,
|
22 | cacheStorage: ICacheStorage,
|
23 | buildCommand: BuildCommand,
|
24 | hasher: IHasher
|
25 | ): Promise<void> {
|
26 | const {
|
27 | cacheStorageConfig,
|
28 | outputFolder,
|
29 | name,
|
30 | mode,
|
31 | logFolder,
|
32 | producePerformanceLogs,
|
33 | validateOutput
|
34 | } = config;
|
35 |
|
36 | logger.setName(name);
|
37 | logger.setMode(mode);
|
38 | logger.setCacheProvider(cacheStorageConfig.provider);
|
39 |
|
40 | const createPackageHash = async () => await hasher.createPackageHash();
|
41 | const fetch = async (hash: string) =>
|
42 | await cacheStorage.fetch(hash, outputFolder);
|
43 | const run = async () => {
|
44 | try {
|
45 | await buildCommand();
|
46 | } catch (err) {
|
47 | throw new Error(`Command failed with the following error:\n\n${err}`);
|
48 | }
|
49 | };
|
50 | const put = async (hash: string) => {
|
51 | try {
|
52 | await cacheStorage.put(hash, outputFolder);
|
53 | } catch (err) {
|
54 | logger.error(
|
55 | `Failed to persist the cache with the following error:\n\n${err}`
|
56 | );
|
57 | }
|
58 | };
|
59 |
|
60 | switch (mode) {
|
61 | case "READ_WRITE": {
|
62 | const hash = await createPackageHash();
|
63 |
|
64 | if (!(await fetch(hash))) {
|
65 | await run();
|
66 | await put(hash);
|
67 | }
|
68 |
|
69 | break;
|
70 | }
|
71 | case "READ_ONLY": {
|
72 | const hash = await createPackageHash();
|
73 |
|
74 | if (!(await fetch(hash))) {
|
75 | await run();
|
76 | }
|
77 |
|
78 | break;
|
79 | }
|
80 | case "WRITE_ONLY": {
|
81 | const hash = await createPackageHash();
|
82 |
|
83 | await run();
|
84 | await put(hash);
|
85 |
|
86 | break;
|
87 | }
|
88 | case "PASS": {
|
89 | await run();
|
90 | break;
|
91 | }
|
92 | }
|
93 |
|
94 | if (validateOutput) {
|
95 | const hashOfOutput = await hasher.hashOfOutput();
|
96 | logger.setHashOfOutput(hashOfOutput);
|
97 | }
|
98 |
|
99 | if (producePerformanceLogs) {
|
100 | await logger.toFile(logFolder);
|
101 | }
|
102 | }
|
103 |
|
104 | export async function main(): Promise<void> {
|
105 | try {
|
106 | const config = createConfig();
|
107 | const {
|
108 | cacheStorageConfig,
|
109 | clearOutputFolder,
|
110 | hashGlobs,
|
111 | internalCacheFolder,
|
112 | logFolder,
|
113 | logLevel,
|
114 | outputFolder,
|
115 | packageRoot
|
116 | } = config;
|
117 |
|
118 | if (logLevel) {
|
119 | setLogLevel(logLevel);
|
120 | }
|
121 |
|
122 | const helpString = "Backfills unchanged packages.";
|
123 |
|
124 | const argv = yargs
|
125 | .strict()
|
126 | .usage(helpString)
|
127 | .alias("h", "help")
|
128 | .version(false)
|
129 | .option("audit", {
|
130 | description: "Compare files changed with those cached",
|
131 | type: "boolean"
|
132 | }).argv;
|
133 |
|
134 | const buildCommand = createBuildCommand(
|
135 | argv["_"],
|
136 | clearOutputFolder,
|
137 | outputFolder
|
138 | );
|
139 |
|
140 | const cacheStorage = getCacheStorageProvider(
|
141 | cacheStorageConfig,
|
142 | internalCacheFolder
|
143 | );
|
144 |
|
145 | const hasher = new Hasher(
|
146 | { packageRoot, outputFolder },
|
147 | getRawBuildCommand()
|
148 | );
|
149 |
|
150 | if (argv["audit"]) {
|
151 | initializeWatcher(
|
152 | packageRoot,
|
153 | internalCacheFolder,
|
154 | logFolder,
|
155 | outputFolder,
|
156 | hashGlobs
|
157 | );
|
158 | }
|
159 |
|
160 | await backfill(config, cacheStorage, buildCommand, hasher);
|
161 |
|
162 | if (argv["audit"]) {
|
163 | await closeWatcher();
|
164 | }
|
165 | } catch (err) {
|
166 | logger.error(err);
|
167 | process.exit(1);
|
168 | }
|
169 | }
|