Skip to content

Commit 1445f28

Browse files
committed
Add ng-deploy
1 parent ce12956 commit 1445f28

35 files changed

+1303
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

src/deploy/builders/actions/__tests__/deploy.spec.js

+95
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/deploy/builders/actions/__tests__/deploy.spec.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import deploy from '../deploy';
2+
3+
import { JsonObject, logging } from '@angular-devkit/core';
4+
import { BuilderContext, BuilderRun, ScheduleOptions, Target, } from '@angular-devkit/architect/src/index2';
5+
import { FirebaseDeployConfig, FirebaseTools } from '../../../shared/types';
6+
7+
8+
let context: BuilderContext;
9+
let firebaseMock: FirebaseTools;
10+
11+
const FIREBASE_PROJECT = 'ikachu-aa3ef';
12+
const PROJECT = 'pirojok-project';
13+
14+
describe('Deploy Angular apps', () => {
15+
beforeEach(() => initMocks());
16+
17+
it('should check if the user is authenticated by invoking list', async () => {
18+
const spy = spyOn(firebaseMock, 'list');
19+
const spyLogin = spyOn(firebaseMock, 'login');
20+
await deploy(firebaseMock, context, 'host', FIREBASE_PROJECT);
21+
expect(spy).toHaveBeenCalled();
22+
expect(spyLogin).not.toHaveBeenCalled();
23+
});
24+
25+
it('should invoke login if list rejects', async () => {
26+
firebaseMock.list = () => Promise.reject();
27+
const spy = spyOn(firebaseMock, 'list').and.callThrough();
28+
const spyLogin = spyOn(firebaseMock, 'login');
29+
await deploy(firebaseMock, context, 'host', FIREBASE_PROJECT);
30+
expect(spy).toHaveBeenCalled();
31+
expect(spyLogin).toHaveBeenCalled();
32+
});
33+
34+
it('should invoke the builder', async () => {
35+
const spy = spyOn(context, 'scheduleTarget').and.callThrough();
36+
await deploy(firebaseMock, context, 'host', FIREBASE_PROJECT);
37+
expect(spy).toHaveBeenCalled();
38+
expect(spy).toHaveBeenCalledWith({
39+
target: 'build',
40+
configuration: 'production',
41+
project: PROJECT
42+
});
43+
});
44+
45+
it('should invoke firebase.deploy', async () => {
46+
const spy = spyOn(firebaseMock, 'deploy').and.callThrough();
47+
await deploy(firebaseMock, context, 'host', FIREBASE_PROJECT);
48+
expect(spy).toHaveBeenCalled();
49+
expect(spy).toHaveBeenCalledWith({
50+
cwd: 'host', only: 'hosting:' + PROJECT
51+
});
52+
});
53+
54+
describe('error handling', () => {
55+
it('throws if there is no firebase project', async () => {
56+
expect(deploy(firebaseMock, context, 'host')).rejects.toThrow(/Cannot find firebase project/);
57+
});
58+
59+
it('throws if there is no target project', async () => {
60+
context.target = undefined;
61+
expect(deploy(firebaseMock, context, 'host', FIREBASE_PROJECT)).rejects.toThrow(/Cannot execute the build target/);
62+
});
63+
});
64+
});
65+
66+
const initMocks = () => {
67+
firebaseMock = {
68+
login: () => Promise.resolve(),
69+
list: () => Promise.resolve([]),
70+
deploy: (_: FirebaseDeployConfig) => Promise.resolve(),
71+
use: jest.fn()
72+
};
73+
74+
context = {
75+
target: {
76+
configuration: 'production',
77+
project: PROJECT,
78+
target: 'foo'
79+
},
80+
builder: {
81+
builderName: 'mock',
82+
description: 'mock',
83+
optionSchema: false
84+
},
85+
currentDirectory: 'cwd',
86+
id: 1,
87+
logger: new logging.Logger('mock'),
88+
workspaceRoot: 'cwd',
89+
getTargetOptions: (_: Target) => Promise.resolve({}),
90+
reportProgress: (_: number, __?: number, ___?: string) => {
91+
},
92+
reportStatus: (_: string) => {
93+
},
94+
reportRunning: () => {
95+
},
96+
scheduleBuilder: (_: string, __?: JsonObject, ___?: ScheduleOptions) => Promise.resolve({} as BuilderRun),
97+
scheduleTarget: (_: Target, __?: JsonObject, ___?: ScheduleOptions) => Promise.resolve({} as BuilderRun)
98+
};
99+
};
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { BuilderContext } from '@angular-devkit/architect/src/index2';
2+
import { FirebaseTools } from '../../shared/types';
3+
export default function deploy(firebaseTools: FirebaseTools, context: BuilderContext, projectRoot: string, firebaseProject?: string): Promise<void>;

src/deploy/builders/actions/deploy.js

+49
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/deploy/builders/actions/deploy.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/deploy/builders/actions/deploy.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { BuilderContext } from '@angular-devkit/architect/src/index2';
2+
import { FirebaseTools } from '../../shared/types';
3+
4+
export default async function deploy(firebaseTools: FirebaseTools, context: BuilderContext, projectRoot: string, firebaseProject?: string) {
5+
if (!firebaseProject) {
6+
throw new Error('Cannot find firebase project for your app in .firebaserc');
7+
}
8+
9+
try {
10+
await firebaseTools.list();
11+
} catch (e) {
12+
context.logger.warn("🚨 You're not logged into Firebase. Logging you in...");
13+
await firebaseTools.login();
14+
}
15+
if (!context.target) {
16+
throw new Error('Cannot execute the build target');
17+
}
18+
19+
context.logger.info(`📦 Building "${context.target.project}"`);
20+
21+
const run = await context.scheduleTarget({
22+
target: 'build',
23+
project: context.target.project,
24+
configuration: 'production'
25+
});
26+
await run.result;
27+
28+
try {
29+
await firebaseTools.use(firebaseProject, {project: firebaseProject});
30+
} catch (e) {
31+
throw new Error(`Cannot select firebase project '${firebaseProject}'`);
32+
}
33+
34+
35+
try {
36+
const success = await firebaseTools.deploy({only: 'hosting:' + context.target.project, cwd: projectRoot});
37+
context.logger.info(`🚀 Your application is now available at https://${success.hosting.split('/')[1]}.firebaseapp.com/`);
38+
} catch (e) {
39+
context.logger.error(e);
40+
}
41+
}

src/deploy/builders/builder.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
declare const _default: import("@angular-devkit/architect/src/internal").Builder<any>;
2+
export default _default;

src/deploy/builders/builder.js

+38
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/deploy/builders/builder.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)