Skip to content

Commit

Permalink
feat: integrated for semantic-release/exec (#38)
Browse files Browse the repository at this point in the history
* integrated for semantic-release/exec

* adjust test names

* adjust variables object name
  • Loading branch information
ZimGil committed Jul 11, 2019
1 parent 85c2e9d commit 3c9743b
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 29 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"@types/fs-extra": "^7.0.0",
"@types/jest": "^24.0.11",
"@types/lodash": "^4.14.123",
"@types/nconf": "^0.10.0",
"all-contributors-cli": "^6.2.0",
"coveralls": "^3.0.3",
"jest": "^24.5.0",
Expand All @@ -88,6 +89,7 @@
"fs-extra": "^8.0.1",
"lodash": "^4.17.11",
"manakin": "^0.5.2",
"nconf": "^0.10.0",
"twitter-lite": "^0.9.4"
},
"jest-stare": {
Expand Down
6 changes: 3 additions & 3 deletions src/__snapshots__/announce-it-cli-utils.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AnnounceItCli areEnvVariablesDefined should reject if at least 1 required environment variable is missing 1`] = `"These Environment variables are required: CONSUMER_KEY CONSUMER_SECRET ACCESS_TOKEN_KEY ACCESS_TOKEN_SECRET"`;
exports[`AnnounceItCli areVariablesDefined should reject if at least 1 required variable is missing 1`] = `"These Variables are required: CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET, branch"`;

exports[`AnnounceItCli areEnvVariablesDefined should reject if at least 1 required environment variable is missing 2`] = `"These Environment variables are required: CONSUMER_KEY CONSUMER_SECRET ACCESS_TOKEN_KEY ACCESS_TOKEN_SECRET"`;
exports[`AnnounceItCli areVariablesDefined should reject if at least 1 required variable is missing 2`] = `"These Variables are required: CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET, branch"`;

exports[`AnnounceItCli areEnvVariablesDefined should resolve if all required environment variables exists 1`] = `undefined`;
exports[`AnnounceItCli areVariablesDefined should resolve if all required variables exists 1`] = `undefined`;

exports[`AnnounceItCli findRoot should return the project root folder if ran inside npm project 1`] = `"project-root"`;

Expand Down
5 changes: 5 additions & 0 deletions src/__snapshots__/announce-it.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`KbAnnounceIt should create instance when given correct parameters 1`] = `
KbAnnounceIt {
"branchName": "TEST",
"client": Object {
"get": [Function],
"post": [Function],
Expand All @@ -23,6 +24,10 @@ exports[`kbAnnounceIt.announceRelease should post to twitter when stable release

exports[`kbAnnounceIt.announceRelease should post to twitter when unstable release and mentioned in packageDetails 1`] = `"test-template"`;

exports[`kbAnnounceIt.announceRelease should post to twitter when unstable release and mentioned in packageDetails as stable 1`] = `"test-template"`;

exports[`kbAnnounceIt.announceRelease should throw an error when unstable release and mentioned in packageDetails as unstable 1`] = `"Not a stable release"`;

exports[`kbAnnounceIt.announceRelease should throw an error when unstable release and not mentioned in packageDetails 1`] = `"Not a stable release"`;

exports[`kbAnnounceIt.announceRelease should throw error when twitter get credentials throws an error 1`] = `"Twitter Get Error"`;
Expand Down
5 changes: 5 additions & 0 deletions src/__snapshots__/read-package-details.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Object {
"description": "package description",
"homepage": "pizza.com",
"name": "package-name",
"release": Object {
"branches": Array [
"TEST",
],
},
"repository": Object {
"type": "",
"url": "",
Expand Down
18 changes: 11 additions & 7 deletions src/announce-it-cli-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,33 @@ const packageDetails: IPackageDetails = {
},
announcements: {
tweet: 'nice!'
},
release: {
branches: [ 'TEST' ]
}
};

describe('AnnounceItCli', () => {
const announceItCli = new AnnounceItCli();

describe('areEnvVariablesDefined', () => {
it('should resolve if all required environment variables exists', () => {
return expect(announceItCli.areEnvVariablesDefined({
describe('areVariablesDefined', () => {
it('should resolve if all required variables exists', () => {
return expect(announceItCli.areVariablesDefined({
CONSUMER_KEY: 'CONSUMER_KEY',
CONSUMER_SECRET: 'CONSUMER_SECRET',
ACCESS_TOKEN_KEY: 'ACCESS_TOKEN_KEY',
ACCESS_TOKEN_SECRET: 'ACCESS_TOKEN_SECRET'
ACCESS_TOKEN_SECRET: 'ACCESS_TOKEN_SECRET',
branch: 'TEST'
})).resolves.toMatchSnapshot();
});
it('should reject if at least 1 required environment variable is missing', () => {
return expect(announceItCli.areEnvVariablesDefined({
it('should reject if at least 1 required variable is missing', () => {
return expect(announceItCli.areVariablesDefined({
CONSUMER_KEY: 'CONSUMER_KEY',
CONSUMER_SECRET: 'CONSUMER_SECRET',
ACCESS_TOKEN_SECRET: 'ACCESS_TOKEN_SECRET'
}))
.rejects.toThrowErrorMatchingSnapshot()
.then(() => expect(announceItCli.areEnvVariablesDefined({}))
.then(() => expect(announceItCli.areVariablesDefined({}))
.rejects.toThrowErrorMatchingSnapshot());
});
});
Expand Down
17 changes: 10 additions & 7 deletions src/announce-it-cli-utils.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
#!/usr/bin/env node
import findRoot from 'find-root';
import { every, isString } from 'lodash';

import { KbAnnounceIt } from './announce-it';
import { readPackageDetails } from './read-package-details';

export class AnnounceItCli {
areEnvVariablesDefined(env: NodeJS.ProcessEnv): Promise<void> {
const envVariables = [
areVariablesDefined(env: NodeJS.ProcessEnv): Promise<void> {
const variables = [
'CONSUMER_KEY',
'CONSUMER_SECRET',
'ACCESS_TOKEN_KEY',
'ACCESS_TOKEN_SECRET'
'ACCESS_TOKEN_SECRET',
'branch'
];

const areEnvVariablesDefined = every(envVariables, (varName) => {
const areEnvVariablesDefined = every(variables, (varName) => {
return isString(env[ varName ]);
});

if (!areEnvVariablesDefined) {
return Promise.reject(new Error(`These Environment variables are required: ${ envVariables.join(' ') }`));
return Promise.reject(
new Error(`These Variables are required: ${ variables.join(', ') }`)
);
}

return Promise.resolve();
Expand All @@ -45,7 +47,8 @@ export class AnnounceItCli {
consumerKey: env.CONSUMER_KEY as string,
consumerSecret: env.CONSUMER_SECRET as string,
accessTokenKey: env.ACCESS_TOKEN_KEY as string,
accessTokenSecret: env.ACCESS_TOKEN_SECRET as string
accessTokenSecret: env.ACCESS_TOKEN_SECRET as string,
branch: env.branch as string
});

return announceIt.announceRelease(packageDetails);
Expand Down
9 changes: 7 additions & 2 deletions src/announce-it-cli.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
#!/usr/bin/env node
import manakin from 'manakin';
import nconf from 'nconf';

import { AnnounceItCli } from './announce-it-cli-utils';

// add console colors
// tslint:disable-next-line
manakin.global;

nconf.argv()
.env();

const announceItCli = new AnnounceItCli();

announceItCli.areEnvVariablesDefined(process.env)
const variables = nconf.get();
announceItCli.areVariablesDefined(variables)
.then(() => announceItCli.findRoot(process.cwd()))
.then((root) => announceItCli.runAnnounceItCli(root, process.env))
.then((root) => announceItCli.runAnnounceItCli(root, variables))
.catch((error: Error) => {
console.error('ERROR: Something went wrong');
console.error(error);
Expand Down
59 changes: 55 additions & 4 deletions src/announce-it.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ describe('KbAnnounceIt', () => {
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST'
consumerSecret: 'TEST',
branch: 'TEST'
});

expect(announceIt).toBeDefined();
Expand All @@ -87,6 +88,9 @@ describe('kbAnnounceIt.announceRelease', () => {
version: '0.0.0',
announcements: {
tweet: 'test-template'
},
release: {
branches: [ 'TEST' ]
}
};

Expand All @@ -97,7 +101,8 @@ describe('kbAnnounceIt.announceRelease', () => {
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST'
consumerSecret: 'TEST',
branch: 'TEST'
});
});

Expand All @@ -107,11 +112,53 @@ describe('kbAnnounceIt.announceRelease', () => {

it('should throw an error when unstable release and not mentioned in packageDetails', () => {
const testPackageDetails = cloneDeep(packageDetails);
testPackageDetails.version = '0.0.0-next.1';
announceIt = new KbAnnounceIt({
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST',
branch: 'unstable'
});

return expect(announceIt.announceRelease(testPackageDetails)).rejects.toThrowErrorMatchingSnapshot();
});

it('should throw an error when unstable release and mentioned in packageDetails as unstable', () => {
const testPackageDetails = cloneDeep(packageDetails);
testPackageDetails.release.branches = [{
name: 'unstable',
prerelease: true
}];
announceIt = new KbAnnounceIt({
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST',
branch: 'unstable'
});


return expect(announceIt.announceRelease(testPackageDetails)).rejects.toThrowErrorMatchingSnapshot();
});

it('should post to twitter when unstable release and mentioned in packageDetails as stable', () => {
const testPackageDetails = cloneDeep(packageDetails);
testPackageDetails.release.branches = [{
name: 'unstable',
prerelease: false
}];
announceIt = new KbAnnounceIt({
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST',
branch: 'unstable'
});


return expect(announceIt.announceRelease(testPackageDetails)).resolves.toMatchSnapshot();
});

it('should post to twitter when unstable release and mentioned in packageDetails', () => {
const testPackageDetails = cloneDeep(packageDetails);
testPackageDetails.version = '0.0.0-next.1';
Expand Down Expand Up @@ -154,6 +201,9 @@ describe('kbAnnounceIt.generateTweet', () => {
version: '0.0.0',
announcements: {
tweet: 'test-template'
},
release: {
branches: [ 'TEST' ]
}
};

Expand All @@ -164,7 +214,8 @@ describe('kbAnnounceIt.generateTweet', () => {
accessTokenKey: 'TEST',
accessTokenSecret: 'TEST',
consumerKey: 'TEST',
consumerSecret: 'TEST'
consumerSecret: 'TEST',
branch: 'TEST'
});
});

Expand Down
45 changes: 39 additions & 6 deletions src/announce-it.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forEach, get, isNil, isObject, template } from 'lodash';
import { forEach, get, isNil, isObject, template, chain, isString } from 'lodash';
import Twitter from 'twitter-lite';

import { IPackageDetails } from './read-package-details';
Expand All @@ -8,20 +8,34 @@ export interface IKbAnnounceItOptions {
consumerSecret: string;
accessTokenKey: string;
accessTokenSecret: string;
branch: string;
}

export interface IBranchObject {
name: string;
prerelease: boolean;
}

export interface IStabilityGroups {
stable: string[];
unstable: string[];
}

export class KbAnnounceIt {
private client: any;
private branchName: string;
constructor(options: IKbAnnounceItOptions) {

if (!get(options, 'consumerKey') ||
!get(options, 'consumerSecret') ||
!get(options, 'accessTokenKey') ||
!get(options, 'accessTokenSecret')) {
!get(options, 'accessTokenSecret') ||
!get(options, 'branch')) {

throw new Error('ERROR: missing required options');
}

this.branchName = options.branch;
this.client = new Twitter({
subdomain: 'api',
consumer_key: options.consumerKey,
Expand All @@ -32,10 +46,29 @@ export class KbAnnounceIt {
}

announceRelease(packageDetails: IPackageDetails): Promise<string> {
if (
!packageDetails.announcements.includeUnstable &&
!packageDetails.version.match(/^(\d+\.)+\d+$/)
) {
const releaseBranches: any[] = get(packageDetails, 'release.branches');

const branchesGroupedByStability: IStabilityGroups = chain(releaseBranches)
.groupBy((branch: string | IBranchObject) => {
if (isString(branch)) { return 'stable'; }
return branch.prerelease ? 'unstable' : 'stable';
})
.mapValues((branches: Array<string | IBranchObject>) =>
branches.map((branch) => isString(branch) ? branch : branch.name))
.defaultsDeep({
stable: [],
unstable: []
})
.value() as any;

const isIncludeUnstable = packageDetails.announcements.includeUnstable;
const isUnstableRelease = branchesGroupedByStability
.unstable.includes(this.branchName);
const isStableRelease = branchesGroupedByStability
.stable.includes(this.branchName);
const isNotRelease = !isUnstableRelease && !isStableRelease;

if ((!isIncludeUnstable && isUnstableRelease) || isNotRelease) {
return Promise.reject(new Error('Not a stable release'));
}

Expand Down
3 changes: 3 additions & 0 deletions src/read-package-details.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const packageDetails: IPackageDetails = {
},
announcements: {
tweet: 'nice!'
},
release: {
branches: [ 'TEST' ]
}
};

Expand Down
4 changes: 4 additions & 0 deletions src/read-package-details.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs-extra';
import { get, isString } from 'lodash';
import { IBranchObject } from './announce-it';

export interface IPackageDetails {
name: string;
Expand All @@ -15,6 +16,9 @@ export interface IPackageDetails {
tweet: string;
includeUnstable?: boolean;
};
release: {
branches: Array<string | IBranchObject>;
}
}

export function readPackageDetails(root: string): Promise<IPackageDetails> {
Expand Down

0 comments on commit 3c9743b

Please sign in to comment.