Skip to content

Commit

Permalink
feat: add version command to support CI usage
Browse files Browse the repository at this point in the history
  • Loading branch information
digitalsadhu committed Jul 2, 2020
1 parent 0ac9a5c commit 46cd6f5
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 0 deletions.
1 change: 1 addition & 0 deletions classes/publish/package/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ module.exports = class PublishApp {
cwd: this.cwd,
token: this.token,
dryRun: this.dryRun,
out: this.out,
};

const outgoing = {
Expand Down
148 changes: 148 additions & 0 deletions classes/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
'use strict';

const { copyFileSync, writeFileSync } = require('fs');
const { join, isAbsolute } = require('path');
const abslog = require('abslog');
const semver = require('semver');
// const { validators } = require('@eik/common');
const {
fetchPackageMeta,
calculateFilesHash,
compareHashes,
} = require('../utils');

module.exports = class Ping {
constructor({
logger,
server,
name,
version,
level = 'patch',
cwd,
js,
css,
map,
out = './.eik',
} = {}) {
this.log = abslog(logger);
this.server = server;
this.name = name;
this.version = version;
this.level = level;
this.cwd = cwd;
this.js = js;
if (typeof js === 'string') {
this.js = {
'./index.js': js,
};
}
this.css = css;
if (typeof css === 'string') {
this.css = {
'./index.css': css,
};
}
this.map = map;
this.out = out;
this.path = isAbsolute(out) ? out : join(cwd, out);
}

async run() {
// TODO: validate input
// version exists and is semver
// server is a url
// js or css files exist
// name is a string
// level is major, minor or patch

const { log, server, name, version, level, cwd, js, css, map, path, out } = this;

log.debug('Checking package version');
log.debug(`Current package determined to be ${version}`);
log.debug('Fetching package metadata from server.');

let meta;
try {
meta = await fetchPackageMeta(server, name, version);
} catch (err) {
throw new Error(
`Unable to fetch package metadata from server: ${err.message}`,
);
}

if (!meta) {
// version does not exist on server yet. No increment needed.
throw new Error(
`The current version of this package has not yet been published, version change is not needed.`,
);
}

log.debug('Hashing local files for comparison with server');

let localHash;
try {
const eikPathDest = join(path, './eik.json');
const eikJSON = {
name,
server,
js,
css,
'import-map': map,
out,
};
writeFileSync(eikPathDest, JSON.stringify(eikJSON, null, 2));

const localFiles = [ eikPathDest ];
log.debug(` ==> ${eikPathDest}`);

if (js) {
try {
for (const [key, val] of Object.entries(js)) {
const src = isAbsolute(val) ? val : join(cwd, val);
const dest = join(path, key);
copyFileSync(src, dest);
log.debug(` ==> ${dest}`);
localFiles.push(dest);
}
} catch (err) {
// throw new Error(`Failed to zip JavaScripts: ${err.message}`);
}
}
if (css) {
try {
for (const [key, val] of Object.entries(css)) {
const src = isAbsolute(val) ? val : join(cwd, val);
const dest = join(path, key);
copyFileSync(src, dest);
log.debug(` ==> ${dest}`);
localFiles.push(join(path, key));
}
} catch (err) {
// throw new Error(`Failed to zip CSS: ${err.message}`);
}
}

localHash = await calculateFilesHash(localFiles);
} catch (err) {
throw new Error(
`Unable to hash local files for comparison: ${err.message}`,
);
}

log.debug(`Comparing hashes:`)
log.debug(` ==> local: ${localHash}`);
log.debug(` ==> remote: ${meta.integrity}`);
const same = compareHashes(meta.integrity, localHash);

if (same) {
throw new Error(
`The current version of this package already contains these files, version change is not needed.`,
);
}

log.debug(`Incrementing by "${level}" level`);
const newVersion = semver.inc(version, level);
log.debug(` ==> ${newVersion}`);
return newVersion;
}
};
110 changes: 110 additions & 0 deletions commands/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use strict';

const { promises: fs, constants } = require('fs');
const { join } = require('path');
const ora = require('ora');
const VersionPackage = require('../classes/version');
const { logger, getDefaults, getCWD, writeEikJSON } = require('../utils');

exports.command = 'version [level]';

exports.aliases = ['v'];

exports.describe = `Compares local files with files on server and increments "version" field in eik.json if necessary.`;

exports.builder = (yargs) => {
const cwd = getCWD();
const defaults = getDefaults(cwd);

yargs.positional('level', {
describe: 'Semver level to increment version by',
default: 'patch',
type: 'string',
choices: ['major', 'minor', 'patch'],
});

yargs.options({
cwd: {
alias: 'c',
describe: 'Alter the current working directory.',
default: defaults.cwd,
type: 'string',
},
dryRun: {
alias: 'd',
describe:
'Terminates the publish early (before upload) and provides information about created bundles for inspection.',
default: false,
type: 'boolean',
},
debug: {
describe: 'Logs additional messages',
default: false,
type: 'boolean',
},
token: {
describe: `Provide a jwt token to be used to authenticate with the Eik server.
Automatically determined if authenticated (via eik login)`,
type: 'string',
alias: 't',
},
});

yargs.default('token', defaults.token, defaults.token ? '######' : '');

yargs.example(`eik version`);
yargs.example(`eik version minor`);
yargs.example(`eik v`);
};

exports.handler = async (argv) => {
const spinner = ora({ stream: process.stdout }).start('working...');
const { level, debug, dryRun, cwd, token } = argv;
const { name, version, server, js, css, map, out } = getDefaults(cwd);

try {
try {
await fs.access(join(cwd, 'eik.json'), constants.F_OK);
} catch (err) {
throw new Error(
'No eik.json file found in the current working directory. Please run eik init',
);
}

const log = logger(spinner, debug);

const options = {
logger: log,
name,
server,
version,
cwd,
token,
dryRun,
debug,
level,
js,
css,
map: Array.isArray(map) ? map : [map],
out,
};

const newVersion = await new VersionPackage(options).run();

if (dryRun) {
log.info(`Dry Run: new version needed, determined new version to be ${newVersion}`);
} else {
await writeEikJSON({ version: newVersion }, { cwd });
log.info(`New version ${newVersion} written back to eik.json`);
}

spinner.text = '';
spinner.stopAndPersist();
process.exit();
} catch (err) {
spinner.warn(err.message);
spinner.text = '';
spinner.stopAndPersist();
process.exit(1);
}
};
2 changes: 2 additions & 0 deletions utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const Artifact = require('./artifact');
const Alias = require('./alias');
const getDefaults = require('./get-defaults');
const getCWD = require('./get-cwd');
const writeEikJSON = require('./write-eik-json');

module.exports = {
resolvePath,
Expand All @@ -38,4 +39,5 @@ module.exports = {
Alias,
getDefaults,
getCWD,
writeEikJSON,
};
21 changes: 21 additions & 0 deletions utils/write-eik-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

const fs = require('fs').promises;
const { join } = require('path');

module.exports = async (data = {}, {
cwd = process.cwd(),
filename = 'eik.json',
}) => {
const eikpath = join(cwd, filename);
const eik = await fs.readFile(eikpath);
const eikjson = JSON.parse(eik);

await fs.writeFile(
eikpath,
JSON.stringify({
...eikjson,
...data,
}, null, 2),
);
};

0 comments on commit 46cd6f5

Please sign in to comment.