Skip to content

Commit bce15d1

Browse files
committed
feat(appflow): Support downloading WWW_ZIP after deploy build
1 parent cae11db commit bce15d1

File tree

1 file changed

+50
-1
lines changed
  • packages/@ionic/cli/src/commands/deploy

1 file changed

+50
-1
lines changed

packages/@ionic/cli/src/commands/deploy/build.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { CommandLineInputs, CommandLineOptions, MetadataGroup } from '@ionic/cli-framework';
22
import { LOGGER_LEVELS } from '@ionic/cli-framework-output';
33
import { sleep } from '@ionic/utils-process';
4+
import { tmpfilepath } from '@ionic/utils-fs';
45
import { columnar } from '@ionic/utils-terminal';
56
import * as chalk from 'chalk';
67
import * as Debug from 'debug';
8+
import * as fs from 'fs';
79

810
import { CommandMetadata } from '../../definitions';
911
import { isSuperAgentError } from '../../guards';
1012
import { input, strong, weak } from '../../lib/color';
1113
import { Command } from '../../lib/command';
1214
import { FatalException } from '../../lib/errors';
15+
import { createRequest, download } from '../../lib/utils/http';
1316

1417
const debug = Debug('ionic:commands:deploy:build');
1518

1619
interface DeployBuild {
20+
artifact_name: string;
1721
job_id: number;
1822
id: string;
1923
caller_id: number;
@@ -30,6 +34,10 @@ interface DeployBuild {
3034
pending_channels: string[];
3135
}
3236

37+
interface DownloadUrl {
38+
url: string | null;
39+
}
40+
3341
export class BuildCommand extends Command {
3442
async getMetadata(): Promise<CommandMetadata> {
3543
const dashUrl = this.env.config.getDashUrl();
@@ -40,7 +48,7 @@ export class BuildCommand extends Command {
4048
groups: [MetadataGroup.PAID],
4149
summary: 'Create a deploy build on Appflow',
4250
description: `
43-
This command creates a deploy build on Ionic Appflow. While the build is running, it prints the remote build log to the terminal.
51+
This command creates a deploy build on Ionic Appflow. While the build is running, it prints the remote build log to the terminal. If the build is successful, it downloads the created web build zip file in the current directory.
4452
4553
Customizing the build:
4654
- The ${input('--environment')} and ${input('--channel')} options can be used to customize the groups of values exposed to the build.
@@ -118,6 +126,15 @@ Apart from ${input('--commit')}, every option can be specified using the full na
118126
throw new Error(`Build ${build.state}`);
119127
}
120128

129+
const url = await this.getDownloadUrl(appflowId, buildId, token);
130+
131+
if (!url.url) {
132+
throw new Error('Missing URL in response');
133+
}
134+
135+
const filename = await this.downloadBuild(url.url, build.artifact_name);
136+
this.env.log.ok(`Artifact downloaded: ${filename}`);
137+
121138
}
122139

123140
async createDeployBuild(appflowId: string, token: string, options: CommandLineOptions): Promise<DeployBuild> {
@@ -209,4 +226,36 @@ Apart from ${input('--commit')}, every option can be specified using the full na
209226
}
210227
}
211228
}
229+
230+
async getDownloadUrl(appflowId: string, buildId: number, token: string): Promise<DownloadUrl> {
231+
const { req } = await this.env.client.make('GET', `/apps/${appflowId}/packages/${buildId}/download?artifact_type=WWW_ZIP`);
232+
req.set('Authorization', `Bearer ${token}`).send();
233+
234+
try {
235+
const res = await this.env.client.do(req);
236+
return res.data as DownloadUrl;
237+
} catch (e) {
238+
if (isSuperAgentError(e)) {
239+
if (e.response.status === 401) {
240+
this.env.log.error('Try logging out and back in again.');
241+
}
242+
const apiErrorMessage = (e.response.body.error && e.response.body.error.message) ? e.response.body.error.message : 'Api Error';
243+
throw new FatalException(`Unable to get download URL for build ${buildId}: ` + apiErrorMessage);
244+
} else {
245+
throw e;
246+
}
247+
}
248+
}
249+
250+
async downloadBuild(url: string, filename: string): Promise<string> {
251+
const { req } = await createRequest('GET', url, this.env.config.getHTTPConfig());
252+
253+
const tmpFile = tmpfilepath('ionic-package-build');
254+
const ws = fs.createWriteStream(tmpFile);
255+
await download(req, ws, {});
256+
fs.copyFileSync(tmpFile, filename);
257+
fs.unlinkSync(tmpFile);
258+
return filename;
259+
}
260+
212261
}

0 commit comments

Comments
 (0)