Skip to content

Commit

Permalink
feat(cli): refactoring and error handling in commands using apps-service
Browse files Browse the repository at this point in the history
  • Loading branch information
eikeland committed Sep 12, 2024
1 parent e9fa2c0 commit 34c5f67
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 358 deletions.
86 changes: 74 additions & 12 deletions packages/cli/src/bin/create-export-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ import semverValid from 'semver/functions/valid.js';
import { chalk, formatPath } from './utils/format.js';
import { Spinner } from './utils/spinner.js';

import { loadPackage } from './utils/load-package.js';
import { loadAppConfig } from './utils/load-app-config.js';
import { publishAppConfig, validateToken, type FusionEnv } from './utils/app-api.js';
import {
getEndpointUrl,
loadAppConfig,
loadPackage,
isAppRegistered,
requireToken,
publishAppConfig,
} from './utils/index.js';
import type { FusionEnv } from './utils/index.js';

import { ConfigExecuterEnv } from '../lib/utils/config.js';
import { resolveAppKey } from '../lib/app-package.js';
import { exit } from 'node:process';

export const createExportConfig = async (options: {
command?: ConfigExecuterEnv['command'];
Expand Down Expand Up @@ -55,13 +63,9 @@ export const createExportConfig = async (options: {
}

if (publish) {
spinner.info('Publishing config');

const validToken = validateToken();
if (!validToken) {
return;
}
spinner.info('Preparing to publishing config');

/* Make sure version is valid */
const version = publish === 'current' ? pkg.packageJson.version : publish;
if (!version || (!semverValid(version) && !['latest', 'preview'].includes(version))) {
spinner.fail(
Expand All @@ -70,12 +74,70 @@ export const createExportConfig = async (options: {
chalk.redBright(version),
'',
);
return;
exit(1);
}

/** make sure user has a valid token */
try {
spinner.info('Validating FUSION_TOKEN');

// make sure token exist
requireToken();

// call service discovery with token, will throw error if failed
await getEndpointUrl('apps', env, '');

spinner.succeed('Found valid FUSION_TOKEN');
} catch (e) {
const err = e as Error;
spinner.fail(chalk.bgRed(err.message));
exit(1);
}

const published = await publishAppConfig(appKey, version, config, env, service);
if (published) {
try {
spinner.info('Verifying that App is registered');

const state = { endpoint: '' };
try {
state.endpoint = await getEndpointUrl(`apps/${appKey}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while verifying app. service-discovery status: ${err.message}`,
);
}

await isAppRegistered(state.endpoint, appKey);
spinner.succeed(`${appKey} is registered`);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}

try {
spinner.info(`Publishing config to "${appKey}@${version}"`);

const state = { endpoint: '' };
try {
state.endpoint = await getEndpointUrl(
`apps/${appKey}/builds/${version}/config`,
env,
service,
);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while publishig config. service-discovery status: ${err.message}`,
);
}

await publishAppConfig(state.endpoint, appKey, config);
spinner.succeed('✅', 'Published config to version', chalk.yellowBright(version));
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}
}

Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/bin/create-export-manifest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import nodeFs from 'node:fs';
import { writeFile } from 'node:fs/promises';
import assert from 'node:assert';
import { execSync } from 'node:child_process';

import { SemVer, parse as parseSemver } from 'semver';

Expand Down
127 changes: 100 additions & 27 deletions packages/cli/src/bin/publish-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { bundleApplication } from './bundle-application.js';
import { resolveAppPackage, resolveAppKey } from '../lib/app-package.js';

import {
uploadAppBundle,
appRegistered,
validateToken,
isAppRegistered,
getEndpointUrl,
requireToken,
tagAppBundle,
type FusionEnv,
} from './utils/app-api.js';
uploadAppBundle,
} from './utils/index.js';
import type { FusionEnv } from './utils/index.js';

import { exit } from 'node:process';

export const publishApplication = async (options: {
tag: string;
Expand All @@ -20,46 +23,116 @@ export const publishApplication = async (options: {

const spinner = Spinner.Global({ prefixText: chalk.dim('Publish') });

const validToken = validateToken();
if (!validToken) {
return;
try {
spinner.info('Validating FUSION_TOKEN');

// make sure token exist
requireToken();

// call service discovery with token, will throw error if failed
await getEndpointUrl('apps', env, '');

spinner.succeed('Found valid FUSION_TOKEN');
} catch (e) {
const err = e as Error;
spinner.fail(chalk.bgRed(err.message));
exit(1);
}

const pkg = await resolveAppPackage();
const appKey = resolveAppKey(pkg.packageJson);

spinner.info(`Publishing app: "${appKey}" with tag: "${tag}"`);
try {
spinner.info('Verifying that App is registered');
const state = { endpoint: '' };
try {
state.endpoint = await getEndpointUrl(`apps/${appKey}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while verifying app is registered. service-discovery status: ${err.message}`,
);
}

spinner.info('Verifying that App is registered in api.');
const appResponse = await appRegistered(appKey, env, service);
if (!appResponse) {
return;
await isAppRegistered(state.endpoint, appKey);
spinner.succeed(`${appKey} is registered`);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}

const bundle = 'app-bundle.zip';

/* Zip app bundle */
spinner.info('Create bundle');
spinner.info('Creating zip bundle');

await bundleApplication({
archive: 'app-bundle.zip',
archive: bundle,
outDir: 'dist',
});

spinner.info('Uploading bundle');
const uploadedBundle = await uploadAppBundle(appKey, 'app-bundle.zip', env, service);
if (!uploadedBundle) {
return;
const state = {
uploadedBundle: { version: '' },
endpoint: '',
};

spinner.info(`Publishing app: "${appKey}" with tag: "${tag}"`);

/* Upload app bundle */
try {
spinner.info(
`Uploading bundle ${chalk.yellowBright(bundle)} to appKey ${chalk.yellowBright(appKey)}`,
);

try {
state.endpoint = await getEndpointUrl(`bundles/apps/${appKey}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while uploading app bundle. service-discovery status: ${err.message}`,
);
}

spinner.info(`Posting bundle to => ${state.endpoint}`);

state.uploadedBundle = await uploadAppBundle(state.endpoint, bundle);

spinner.succeed(
'✅',
`Uploaded bundle: "${chalk.greenBright(bundle)}" with version: ${chalk.greenBright(state.uploadedBundle.version)}"`,
);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}

spinner.info(`Tag app bundle with: ${tag}`);
const tagged = await tagAppBundle(tag, appKey, uploadedBundle.version, env, service);
try {
spinner.info(`Tagging ${state.uploadedBundle.version} with ${tag}`);

try {
state.endpoint = await getEndpointUrl(`apps/${appKey}/tags/${tag}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while tagging app. service-discovery status: ${err.message}`,
);
}

if (!tagged) {
return;
const tagged = await tagAppBundle(state.endpoint, state.uploadedBundle.version);
spinner.succeed(
'✅',
`Tagged version ${chalk.greenBright(tagged.version)} with ${chalk.greenBright(tagged.tagName)}`,
);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}

spinner.succeed(
'✅',
`Published app: "${chalk.greenBright(appKey)}"`,
`With version: "${chalk.greenBright(tagged.version)}"`,
`Tag: "${chalk.greenBright(tagged.tagName)}"`,
'⭐️',
`Published app: "${chalk.greenBright(appKey)}" version: "${chalk.greenBright(state.uploadedBundle.version)}" with tagg: "${chalk.greenBright(tag)}"`,
);
};
87 changes: 62 additions & 25 deletions packages/cli/src/bin/tag-application.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { exit } from 'node:process';
import { chalk } from './utils/format.js';
import { Spinner } from './utils/spinner.js';
import { resolveAppPackage, resolveAppKey } from '../lib/app-package.js';
import { appRegistered, validateToken, tagAppBundle, type FusionEnv } from './utils/app-api.js';
import { isAppRegistered, getEndpointUrl, requireToken, tagAppBundle } from './utils/index.js';
import type { FusionEnv } from './utils/index.js';

enum Tags {
preview = 'preview',
Expand All @@ -18,38 +20,73 @@ export const tagApplication = async (options: {

const spinner = Spinner.Global({ prefixText: chalk.dim('Tag') });

const validToken = validateToken();
if (!validToken) {
return;
}

const pkg = await resolveAppPackage();
const appKey = resolveAppKey(pkg.packageJson);

// if (!['preview', 'latest'].includes(tag)) {
if (!Object.values(Tags).includes(tag as Tags)) {
spinner.fail('😞', `Tag must match (${Tags.latest} | ${Tags.preview})`);
return;
exit(1);
}

spinner.info(`Tag app "${appKey}@${version}" with: "${tag}"`);
/** make sure user has a valid token */
try {
spinner.info('Validating FUSION_TOKEN');

// make sure token exist
requireToken();

spinner.info('Verifying that App is registered');
const registered = await appRegistered(appKey, env, service);
if (!registered) {
return;
// call service discovery with token, will throw error if failed
await getEndpointUrl('apps', env, '');

spinner.succeed('Found valid FUSION_TOKEN');
} catch (e) {
const err = e as Error;
spinner.fail(chalk.bgRed(err.message));
exit(1);
}

const tagged = await tagAppBundle(tag, appKey, version, env, service);
const pkg = await resolveAppPackage();
const appKey = resolveAppKey(pkg.packageJson);

try {
spinner.info('Verifying that App is registered');
const state = { endpoint: '' };
try {
state.endpoint = await getEndpointUrl(`apps/${appKey}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while verifying app is registered. service-discovery status: ${err.message}`,
);
}

if (!tagged) {
return;
await isAppRegistered(state.endpoint, appKey);
spinner.succeed(`${appKey} is registered`);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}

spinner.succeed(
'✅',
`App: "${chalk.greenBright(appKey)}"`,
`Version: "${chalk.greenBright(tagged.version)}"`,
`Tag: "${chalk.greenBright(tagged.tagName)}"`,
);
try {
spinner.info(`Tagging "${appKey}@${version}" with: "${tag}"`);
const state = { endpoint: '' };
try {
state.endpoint = await getEndpointUrl(`apps/${appKey}/tags/${tag}`, env, service);
} catch (e) {
const err = e as Error;
throw new Error(
`Could not get endpoint from service discovery while tagging app. service-discovery status: ${err.message}`,
);
}

const tagged = await tagAppBundle(state.endpoint, version);
spinner.succeed(
'✅',
`Tagged app: "${chalk.greenBright(appKey)}"`,
`version: "${chalk.greenBright(tagged.version)}"`,
`with tag: "${chalk.greenBright(tagged.tagName)}"`,
);
} catch (e) {
const err = e as Error;
spinner.fail('🙅‍♂️', chalk.bgRed(err.message));
exit(1);
}
};
Loading

0 comments on commit 34c5f67

Please sign in to comment.