Skip to content

Commit f285061

Browse files
committed
Package dependencies updated.
Code refactored Added express server to run the app in Heroku Added NodeJs binary as file, Instead of downloading from server ,
1 parent 7834449 commit f285061

19 files changed

+2931
-2672
lines changed

src/Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: node server.js

src/collection.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"schematics": {
44
"ng-add": {
55
"description": "Add @angular-schule/ngx-deploy-starter deploy schematic",
6-
"factory": "./ng-add#ngAdd",
7-
"schema": "./ng-add-schema.json",
6+
"factory": "./ng-add/ng-add#ngAdd",
7+
"schema": "./ng-add/ng-add-schema.json",
88
"aliases": ["install"]
99
}
1010
}

src/deploy/actions.spec.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { JsonObject, logging } from '@angular-devkit/core';
22
import { BuilderContext, BuilderRun, ScheduleOptions, Target } from '@angular-devkit/architect/src/index';
33
import deploy from './actions';
4+
import { SynchronousDelegateExpectedException } from '@angular-devkit/core/src/virtual-fs/host';
45

56
let context: BuilderContext;
6-
const mockEngine = { run: (_: string, __: any, __2: any) => Promise.resolve() }
77

88
const PROJECT = 'pirojok-project';
99

@@ -12,7 +12,7 @@ describe('Deploy Angular apps', () => {
1212

1313
it('should invoke the builder', async () => {
1414
const spy = spyOn(context, 'scheduleTarget').and.callThrough();
15-
await deploy(mockEngine, context, 'host', {});
15+
await deploy( context, 'host',"app", {});
1616

1717
expect(spy).toHaveBeenCalledWith({
1818
target: 'build',
@@ -25,7 +25,7 @@ describe('Deploy Angular apps', () => {
2525

2626
it('should invoke the builder with the baseHref', async () => {
2727
const spy = spyOn(context, 'scheduleTarget').and.callThrough();
28-
await deploy(mockEngine, context, 'host', { baseHref: '/folder'});
28+
await deploy(context, 'host',"app", { baseHref: '/folder'});
2929

3030
expect(spy).toHaveBeenCalledWith({
3131
target: 'build',
@@ -36,23 +36,35 @@ describe('Deploy Angular apps', () => {
3636
);
3737
});
3838

39-
it('should invoke engine.run', async () => {
40-
const spy = spyOn(mockEngine, 'run').and.callThrough();
41-
await deploy(mockEngine, context, 'host', {});
39+
// it('should invoke engine.run', async () => {
40+
// const spy = spyOn(mockEngine, 'run').and.callThrough();
41+
// await deploy(mockEngine, context, 'host', {});
4242

43-
expect(spy).toHaveBeenCalledWith('host', {}, context.logger);
44-
});
43+
// expect(spy).toHaveBeenCalledWith('host', {}, context.logger);
44+
// });
4545

4646
describe('error handling', () => {
4747
it('throws if there is no target project', async () => {
4848
context.target = undefined;
4949
try {
50-
await deploy(mockEngine, context, 'host', {});
50+
await deploy(context, 'host', "app", {});
5151
fail();
5252
} catch (e) {
5353
expect(e.message).toMatch(/Cannot execute the build target/);
5454
}
5555
});
56+
57+
it('return false if api Token not present', async () => {
58+
var output = await deploy(context, 'host', "app", {});
59+
expect(output.success).toEqual(false);
60+
});
61+
62+
it('return false if app name not present', async () => {
63+
var output = await deploy(context, 'host', "app", {
64+
herokuApiToken:"asd"
65+
});
66+
expect(output.success).toEqual(false);
67+
});
5668
});
5769
});
5870

src/deploy/actions.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { BuilderContext } from '@angular-devkit/architect';
22
import { json, logging } from '@angular-devkit/core';
3-
3+
import * as engine from '../engine/engine';
44
import { Schema } from './schema';
55

66

7+
78
export default async function deploy(
8-
engine: { run: (dir: string, options: Schema, outDir: string, logger: logging.LoggerApi) => Promise<void> },
99
context: BuilderContext,
1010
projectRoot: string,
1111
outDir: string,
1212
options: Schema
1313
) {
14-
14+
1515
if (options.noBuild) {
1616
context.logger.info(`📦 Skipping build`);
1717
} else {
@@ -36,7 +36,16 @@ export default async function deploy(
3636
await build.result;
3737
}
3838

39-
await engine.run(
39+
if (!options.herokuApiToken) {
40+
context.logger.error("🚨 Heroku API Token not found!");
41+
return { success: false };
42+
}
43+
if (!options.appName) {
44+
context.logger.error("🚨 Please specify Heroku Application in which you want to deploy!");
45+
return { success: false };
46+
}
47+
48+
return await engine.run(
4049
projectRoot,
4150
options,
4251
outDir,

src/deploy/builder.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import { NodeJsSyncHost } from '@angular-devkit/core/node';
44
import os from 'os';
55
import * as path from 'path';
66

7-
import * as engine from '../engine/engine';
87
import deploy from './actions';
98
import { Schema } from './schema';
109

1110
// Call the createBuilder() function to create a builder. This mirrors
1211
// createJobHandler() but add typings specific to Architect Builders.
13-
export default createBuilder<any>(
12+
export default createBuilder(
1413
async (
1514
options: Schema,
1615
context: BuilderContext
@@ -48,8 +47,7 @@ export default createBuilder<any>(
4847
// const workspaceRoot = workspace.root;
4948

5049
try {
51-
await deploy(
52-
engine,
50+
return await deploy(
5351
context,
5452
path.join(workspaceRoot),
5553
targets.build.options.outputPath,
@@ -60,7 +58,5 @@ export default createBuilder<any>(
6058
console.error(e);
6159
return { success: false };
6260
}
63-
64-
return { success: true };
6561
}
6662
);

src/deploy/schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
"targetDir": {
2222
"type": "string",
2323
"description": "This is one of the options you can freely choose according to your needs. --- We will 'deploy' to this folder."
24+
},
25+
"appName": {
26+
"type": "string",
27+
"description": "Application Name in which you want to deploy"
28+
},
29+
"herokuApiToken": {
30+
"type": "string",
31+
"description": "Heroku API Token for deploying the application"
2432
}
2533
}
2634
}

src/engine/engine.spec.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
import * as engine from './engine';
2-
import { NullLogger } from '@angular-devkit/core/src/logger';
2+
import { JsonObject, logging } from '@angular-devkit/core';
3+
import { Logger, LogLevel } from '@angular-devkit/core/src/logger';
4+
const Heroku = require('heroku-client');
5+
const logger: any = {
6+
error: (message: string) => { }
7+
}
8+
let heroku: any = null;
9+
jest.mock('heroku-client') // this auto mocks all methods on heroku-client
310

411
describe('engine', () => {
5-
it('should copy directory', () => {
12+
beforeEach(() => {
13+
heroku = new Heroku({ token: 'asd' });
14+
});
615

7-
// TODO: really write test here!
8-
expect(1 + 1).toEqual(2);
16+
it('should return false if application name not find in Heroku', async () => {
17+
const spy = spyOn(logger, 'error').and.callThrough();
18+
const result = await engine.run("", { appName: 'test' }, "app", logger);
19+
expect(result.success).toEqual(false);
20+
expect(spy).toHaveBeenCalledWith("🚨 test application not found in Heroku!");
921
});
22+
1023
});

src/engine/engine.ts

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,57 @@
1+
import { BuilderOutput } from '@angular-devkit/architect';
12
import { logging } from '@angular-devkit/core';
3+
import {
4+
copy,
5+
copyFileSync, ensureDir, move,
6+
readFileSync, remove
7+
} from 'fs-extra';
8+
import * as tar from 'tar';
29
import { Schema } from '../deploy/schema';
310
const Heroku = require('heroku-client');
4-
import * as tar from 'tar';
511
const fetch = require("node-fetch");
6-
import {
7-
ensureDir, copy, remove, move,
8-
copyFileSync, readFileSync, createWriteStream
9-
} from 'fs-extra';
1012

13+
const path = require("path");
1114

1215
// TODO: add your deployment code here!
1316
export async function run(dir: string,
1417
options: Schema,
1518
outDir: string,
16-
logger: logging.LoggerApi) {
19+
logger: logging.LoggerApi): Promise<BuilderOutput> {
1720

1821
try {
19-
20-
const heroku = new Heroku({ token: '' });
21-
22+
const heroku = new Heroku({ token: options.herokuApiToken });
2223
const result = await heroku.get('/apps');
23-
const site = result.find((app => app.name === 'ngx-deploy-demo'))
24+
let site: any = null;
25+
if (result && result.length > 0) {
26+
site = result.find((app => app.name === options.appName));
27+
}
28+
29+
if (!site) {
30+
logger.error(`🚨 ${options.appName} application not found in Heroku!`);
31+
return { success: false };
32+
}
2433

2534
const slugResult = await heroku.post(`/apps/${site.name}/slugs`, {
2635
body: {
2736
buildpack_provided_description: "heroku/nodejs",
28-
process_types: { "web": `node-v12.12.0-linux-x64/bin/node index.js` }
37+
process_types: { "web": `node-v15.6.0-linux-x64/bin/node server.js` }
2938
}
3039
});
40+
3141
logger.info('Copying Build Files');
3242
await remove(`${dir}/app`);
3343
await remove(`${dir}/tmp`);
3444
await remove(`${dir}/slug.tgz`);
3545
await ensureDir(`${dir}/app`);
3646
await ensureDir(`${dir}/tmp`);
37-
38-
await download();
47+
3948
await copy(`${outDir}`, `${dir}/app`);
40-
await moveNodeJS('node-v12.12.0-linux-x64', `${dir}/app/node-v12.12.0-linux-x64`)
41-
copyFileSync('index.js', `${dir}/app/index.js`);
49+
await tar.x({
50+
file: path.join(__dirname, "../", 'node-v15.6.0-linux-x64.tar')
51+
})
52+
await moveNodeJS('node-v15.6.0-linux-x64', `${dir}/app/node-v15.6.0-linux-x64`)
53+
copyFileSync(path.join(__dirname, "../", 'server.js'), `${dir}/app/server.js`);
54+
copyFileSync(path.join(__dirname, "../", 'Procfile'), `${dir}/app/Procfile`);
4255

4356
const tarResponse = await tar.c(
4457
{
@@ -68,6 +81,7 @@ export async function run(dir: string,
6881
});
6982

7083
logger.info('Deployment Success!');
84+
return { success: true };
7185
// await remove(`${dir}/app`);
7286
// await remove(`${dir}/tmp`);
7387
// await remove(`${dir}/slug.tgz`);
@@ -79,23 +93,6 @@ export async function run(dir: string,
7993
};
8094

8195

82-
async function download() {
83-
const res = await fetch('http://nodejs.org/dist/latest-v12.x/node-v12.12.0-linux-x64.tar.gz');
84-
await new Promise((resolve, reject) => {
85-
const fileStream = createWriteStream('./tmp/node-v12.12.0-linux-x64.tar.gz');
86-
res.body.pipe(fileStream);
87-
res.body.on("error", (err) => {
88-
reject(err);
89-
});
90-
fileStream.on("finish", function () {
91-
tar.x({
92-
file: './tmp/node-v12.12.0-linux-x64.tar.gz'
93-
})
94-
resolve();
95-
});
96-
});
97-
}
98-
9996
async function moveNodeJS(src, dest) {
10097
try {
10198
await move(src, dest)

src/interfaces.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
export interface WorkspaceProject {
3+
projectType?: string;
4+
architect?: Record<
5+
string,
6+
{ builder: string; options?: Record<string, any> }
7+
>;
8+
}
9+
10+
export interface Workspace {
11+
defaultProject?: string;
12+
projects: Record<string, WorkspaceProject>;
13+
}

src/ng-add-schema.json

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)