Skip to content

Commit c969a35

Browse files
authored
gitignore output bundle in angular adpater builds (#390)
1 parent 6fe7af5 commit c969a35

File tree

6 files changed

+100
-8
lines changed

6 files changed

+100
-8
lines changed

packages/@apphosting/adapter-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"scripts": {
2424
"build": "rm -rf dist && tsc && chmod +x ./dist/bin/*",
2525
"test": "npm run test:unit && npm run test:functional",
26-
"test:unit": "ts-mocha -p tsconfig.json src/**/*.spec.ts",
26+
"test:unit": "ts-mocha -p tsconfig.json 'src/**/*.spec.ts' 'src/*.spec.ts'",
2727
"test:functional": "node --loader ts-node/esm ./e2e/run-local.ts",
2828
"localregistry:start": "npx verdaccio --config ../publish-dev/verdaccio-config.yaml",
2929
"localregistry:publish": "(npm view --registry=http://localhost:4873 @apphosting/adapter-angular && npm unpublish --@apphosting:registry=http://localhost:4873 --force); npm publish --@apphosting:registry=http://localhost:4873"

packages/@apphosting/adapter-angular/src/bin/build.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ describe("build commands", () => {
1515
outputBundleOptions = {
1616
browserDirectory: resolve(tmpDir, "dist", "test", "browser"),
1717
bundleYamlPath: resolve(tmpDir, ".apphosting", "bundle.yaml"),
18+
outputDirectoryBasePath: resolve(tmpDir, ".apphosting"),
1819
serverFilePath: resolve(tmpDir, "dist", "test", "server", "server.mjs"),
1920
needsServerGenerated: false,
2021
};
@@ -82,6 +83,7 @@ metadata:
8283
const expectedOutputBundleOptions = {
8384
browserDirectory: "/browser",
8485
bundleYamlPath: resolve(".apphosting", "bundle.yaml"),
86+
outputDirectoryBasePath: resolve(".apphosting"),
8587
needsServerGenerated: false,
8688
serverFilePath: path.join("/server", "server.mjs"),
8789
};

packages/@apphosting/adapter-angular/src/bin/build.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
checkBuildConditions,
55
validateOutputDirectory,
66
parseOutputBundleOptions,
7-
outputBundleExists,
7+
metaFrameworkOutputBundleExists,
88
} from "../utils.js";
99
import { getBuildOptions, runBuild } from "@apphosting/common";
1010

@@ -21,7 +21,11 @@ if (!output) {
2121
}
2222

2323
const angularVersion = process.env.FRAMEWORK_VERSION || "unspecified";
24-
if (!outputBundleExists()) {
24+
// Frameworks like nitro, analog, nuxt generate the output bundle during their own build process
25+
// when `npm run build` is called which we don't want to overwrite immediately after.
26+
// We only want to overwrite if the existing output is from a previous framework adapter
27+
// build on a plain angular app.
28+
if (!metaFrameworkOutputBundleExists()) {
2529
const outputBundleOptions = parseOutputBundleOptions(output);
2630
const root = process.cwd();
2731
await generateBuildOutput(root, outputBundleOptions, angularVersion);

packages/@apphosting/adapter-angular/src/interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { URL } from "node:url";
44
// options to help generate output directory
55
export interface OutputBundleOptions {
66
bundleYamlPath: string;
7+
outputDirectoryBasePath: string;
78
serverFilePath: string;
89
browserDirectory: string;
910
needsServerGenerated: boolean;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
const importUtils = import("@apphosting/adapter-angular/dist/utils.js");
2+
import assert from "assert";
3+
import fs from "fs";
4+
import * as path from "path";
5+
import { stringify as yamlStringify } from "yaml";
6+
import os from "os";
7+
import type { OutputBundleConfig } from "@apphosting/common";
8+
9+
function generateTmpDir(): string {
10+
return fs.mkdtempSync(path.join(os.tmpdir(), "test-files"));
11+
}
12+
13+
describe("metaFrameworkOutputBundleExists", () => {
14+
let bundlePath: string;
15+
const originalCwd = process.cwd.bind(process);
16+
17+
beforeEach(() => {
18+
const tmpDir = generateTmpDir();
19+
process.cwd = () => tmpDir;
20+
fs.mkdirSync(path.resolve(tmpDir, ".apphosting"));
21+
bundlePath = path.resolve(tmpDir, ".apphosting", "bundle.yaml");
22+
});
23+
24+
afterEach(() => {
25+
process.cwd = originalCwd;
26+
});
27+
28+
it("unrecognized bundle", async () => {
29+
const { metaFrameworkOutputBundleExists } = await importUtils;
30+
const content = "chicken: bok bok";
31+
fs.writeFileSync(bundlePath, yamlStringify(content));
32+
assert(!metaFrameworkOutputBundleExists());
33+
});
34+
35+
it("no bundle exists", async () => {
36+
const { metaFrameworkOutputBundleExists } = await importUtils;
37+
assert(!metaFrameworkOutputBundleExists());
38+
});
39+
40+
it("meta-framework bundle exists", async () => {
41+
const { metaFrameworkOutputBundleExists } = await importUtils;
42+
const outputBundle: OutputBundleConfig = {
43+
version: "v1",
44+
runConfig: {
45+
runCommand: `does not matter`,
46+
},
47+
metadata: {
48+
framework: "nitro",
49+
},
50+
};
51+
fs.writeFileSync(bundlePath, yamlStringify(outputBundle));
52+
assert(metaFrameworkOutputBundleExists());
53+
});
54+
55+
it("angular bundle exists", async () => {
56+
const { metaFrameworkOutputBundleExists } = await importUtils;
57+
const outputBundle: OutputBundleConfig = {
58+
version: "v1",
59+
runConfig: {
60+
runCommand: `does not matter`,
61+
},
62+
metadata: {
63+
framework: "angular",
64+
},
65+
};
66+
fs.writeFileSync(bundlePath, yamlStringify(outputBundle));
67+
assert(!metaFrameworkOutputBundleExists());
68+
});
69+
});

packages/@apphosting/adapter-angular/src/utils.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@ import { resolve, normalize, relative, dirname, join } from "path";
77
import { stringify as yamlStringify } from "yaml";
88
import { OutputBundleOptions, OutputPaths, buildManifestSchema } from "./interface.js";
99
import { createRequire } from "node:module";
10+
import { parse as parseYaml } from "yaml";
1011
import stripAnsi from "strip-ansi";
1112
import {
1213
BuildOptions,
1314
OutputBundleConfig,
1415
EnvVarConfig,
1516
Metadata,
1617
Availability,
18+
updateOrCreateGitignore,
1719
} from "@apphosting/common";
1820

1921
// fs-extra is CJS, readJson can't be imported using shorthand
20-
export const { writeFile, move, readJson, mkdir, copyFile, readFileSync, existsSync } = fsExtra;
22+
export const { writeFile, move, readJson, mkdir, copyFile, readFileSync, existsSync, ensureDir } =
23+
fsExtra;
2124

2225
const require = createRequire(import.meta.url);
2326
const __filename = fileURLToPath(import.meta.url);
@@ -135,6 +138,7 @@ export function populateOutputBundleOptions(outputPaths: OutputPaths): OutputBun
135138
}
136139
return {
137140
bundleYamlPath: resolve(outputBundleDir, "bundle.yaml"),
141+
outputDirectoryBasePath: outputBundleDir,
138142
serverFilePath: resolve(baseDirectory, serverRelativePath, "server.mjs"),
139143
browserDirectory: resolve(baseDirectory, browserRelativePath),
140144
needsServerGenerated,
@@ -210,6 +214,10 @@ export async function generateBuildOutput(
210214
await generateServer(outputBundleOptions);
211215
}
212216
await generateBundleYaml(outputBundleOptions, cwd, angularVersion);
217+
// generateBundleYaml creates the output directory (if it does not already exist).
218+
// We need to make sure it is gitignored.
219+
const normalizedBundleDir = normalize(relative(cwd, outputBundleOptions.outputDirectoryBasePath));
220+
updateOrCreateGitignore(cwd, [`/${normalizedBundleDir}/`]);
213221
}
214222

215223
// add environment variable to bundle.yaml if needed for specific versions
@@ -233,7 +241,7 @@ async function generateBundleYaml(
233241
cwd: string,
234242
angularVersion: string,
235243
): Promise<void> {
236-
await mkdir(dirname(opts.bundleYamlPath));
244+
await ensureDir(dirname(opts.bundleYamlPath));
237245
const outputBundle: OutputBundleConfig = {
238246
version: "v1",
239247
runConfig: {
@@ -270,10 +278,18 @@ export const isMain = (meta: ImportMeta) => {
270278
return process.argv[1] === fileURLToPath(meta.url);
271279
};
272280

273-
export const outputBundleExists = () => {
281+
export const metaFrameworkOutputBundleExists = () => {
274282
const outputBundleDir = resolve(".apphosting");
275-
if (existsSync(outputBundleDir)) {
276-
return true;
283+
const bundleYamlPath = join(outputBundleDir, "bundle.yaml");
284+
if (existsSync(bundleYamlPath)) {
285+
try {
286+
const bundle = parseYaml(readFileSync(bundleYamlPath, "utf8"));
287+
if (bundle?.metadata?.framework && bundle.metadata.framework !== "angular") {
288+
return true;
289+
}
290+
} catch (e) {
291+
logger.debug("Failed to parse bundle.yaml, assuming it can be overwritten", e);
292+
}
277293
}
278294
return false;
279295
};

0 commit comments

Comments
 (0)