Skip to content

Commit

Permalink
add-new-npm-publish-script (#24)
Browse files Browse the repository at this point in the history
add new npm publish script
  • Loading branch information
tomas-zijdemans-vipps authored Jan 12, 2024
1 parent d914fc5 commit 227cec6
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 32 deletions.
6 changes: 3 additions & 3 deletions scripts/build_npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { build, emptyDir } from "./script_deps.ts";
* This script builds the SDK for NPM.
*
* It is run from the root of the repository with:
* 'Deno run -A scripts/build_npm.ts 1.0.0'
* 'deno run -A scripts/build_npm.ts 1.0.0'
*
* '1.0.0' is the version, or git tag, you wish to use.
*
* after running the script, the SDK can be published to NPM with:
* 'cd npm && npm publish --access public'
* 'npm publish ./npm --access public'
*
* @example Deno run -A scripts/build_npm.ts 1.0.0 && cd npm && npm publish --access public
* @example deno run -A scripts/build_npm.ts 1.0.0 && npm publish ./npm --access public
*/

await emptyDir("./npm");
Expand Down
33 changes: 4 additions & 29 deletions scripts/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,16 @@
* @param THRESHOLD - The minimum branch coverage threshold (in percentage) required for the project.
*/

import { run } from "./run.ts";

// Minimum branch coverage threshold (in percentage)
const THRESHOLD = 90;

const getCommandOutput = async (command: Deno.Command) => {
const { code, stdout, stderr } = await command.output();
const error = new TextDecoder().decode(stderr);
if (code || error) {
console.error(error);
Deno.exit(1);
}
const output = new TextDecoder().decode(stdout);
return output;
};

// Run tests with coverage enabled
const testCmd = new Deno.Command(Deno.execPath(), {
args: [
"test",
"--coverage",
],
});

// Check that the command ran successfully
await getCommandOutput(testCmd);
await run(`${Deno.execPath()} test --coverage`);

// Calculate branch coverage
const covCmd = new Deno.Command(Deno.execPath(), {
args: [
"coverage",
"./coverage",
],
});

// Check that the command ran successfully
const coverageReport = await getCommandOutput(covCmd);
const coverageReport = await run(`${Deno.execPath()} coverage ./coverage`);

// Remove ANSI escape codes
const words = coverageReport.replaceAll("\x1b", " ").split(" ");
Expand Down
101 changes: 101 additions & 0 deletions scripts/publish_latest_tag_to_npm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { colors, gt, parse, Spinner } from "./script_deps.ts";
import { run } from "./run.ts";

const PACKAGE_NAME = `@vippsmobilepay/sdk`;

const spinnerTags = new Spinner({ message: `Fetching latest tags...` });
spinnerTags.start();
await run(`git fetch --tags`);
spinnerTags.stop();

// Finding latest tagged commit across branches
const latestTaggedCommit = await run(`git rev-list --tags --max-count=1`);
const trimmedCommit = latestTaggedCommit.trim();
console.log(colors.gray(`Latest tag found ${trimmedCommit}`));

// Finding latest tag name
const latestTagName = await run(`git describe --tags ${trimmedCommit}`);
const trimmedTag = latestTagName.trim();
console.log(colors.gray(`Latest tag name: ${trimmedTag}`));

const spinnerNpm = new Spinner({
message: `Fetching latest published npm version...`,
});
spinnerNpm.start();
const latestNpmVersion = await run(`npm show ${PACKAGE_NAME} version`);
spinnerNpm.stop();
console.log(colors.gray(`Latest npm version: ${latestNpmVersion}`));

try {
const latestSemVer = parse(trimmedTag);
const latestNpmSemVer = parse(latestNpmVersion);
const tagIsGreaterThanNpm = gt(latestSemVer, latestNpmSemVer);
if (!tagIsGreaterThanNpm) {
console.log(
colors.white(
`📀 Latest tag version ${trimmedTag}. 📮 Latest npm version ${latestNpmVersion}`,
),
);
console.log(colors.white(`No need to publish. Bye! 👋`));
Deno.exit(0);
}
} catch (error) {
console.log(`Could not parse tag and npm values 💥`);
console.error(error);
Deno.exit(1);
}
const build = prompt(
colors.green(
colors.bold(`Do you want to build ${trimmedTag} for npm? (y/n)`),
),
);
if (build?.toLowerCase().trim() !== "y") {
console.log(colors.white(`No problemo. Bye! 👋`));
Deno.exit(0);
}

const spinnerBuild = new Spinner({ message: `Building...` });
spinnerBuild.start();
const buildOutput = await run(
`${Deno.execPath()} run -A scripts/build_npm.ts ${trimmedTag}`,
);
spinnerBuild.stop();
console.log(buildOutput);

const publish = prompt(
colors.green(
colors.bold(`Do you want to publish ${trimmedTag} to npm? (y/n)`),
),
);
if (publish?.toLowerCase().trim() !== "y") {
console.log(`No problemo. Bye! 👋`);
Deno.exit(0);
}

const spinnerPublish = new Spinner({ message: `Publishing...` });
spinnerPublish.start();
// Igonre npm errors since we are checking for them later
await run(`npm publish ./npm --access public --dry-run`, true);
spinnerPublish.stop();

const spinnerNewNpm = new Spinner({
message: `Checking new published npm package...`,
});
spinnerNewNpm.start();
const newNpmVersion = await run(`npm show ${PACKAGE_NAME} version`);
spinnerNewNpm.stop();

if (newNpmVersion.trim() !== trimmedTag) {
console.log(
colors.red(`💥 Published version ${newNpmVersion} != ${trimmedTag}`),
);
console.log(colors.red(`💥 Something went wrong. Please check npm logs.`));
Deno.exit(1);
}

console.log(colors.white(`🚀 Published package! 🚀`));
console.log(
colors.white(
`🔗 https://www.npmjs.com/package/${PACKAGE_NAME}/v/${trimmedTag}`,
),
);
24 changes: 24 additions & 0 deletions scripts/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const getCommandOutput = async (
command: Deno.Command,
ignoreErrors = false,
) => {
const { code, stdout, stderr } = await command.output();
const error = new TextDecoder().decode(stderr);
if ((code || error) && !ignoreErrors) {
console.error(error);
Deno.exit(1);
}
const output = new TextDecoder().decode(stdout);
return output;
};

// The command might terminate the program.
export const run = async (command: string, ignoreErrors = false) => {
const words = command.split(" ");
const cmd = words[0];
const args = words.slice(1);
const denoCmd = new Deno.Command(cmd, { args });

const output = await getCommandOutput(denoCmd, ignoreErrors);
return output;
};
4 changes: 4 additions & 0 deletions scripts/script_deps.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export { gt, parse } from "https://deno.land/std@0.211.0/semver/mod.ts";
export { Spinner } from "https://deno.land/std@0.211.0/cli/mod.ts";
export * as colors from "https://deno.land/std@0.211.0/fmt/colors.ts";

export { build, emptyDir } from "https://deno.land/x/dnt@0.39.0/mod.ts";

0 comments on commit 227cec6

Please sign in to comment.