Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(setup): add github actions as CI option #502

Merged
merged 23 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions packages/shipjs/src/flow/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import askQuestions from '../step/setup/askQuestions';
import addDevDependencies from '../step/setup/addDevDependencies';
import addScriptsToPackageJson from '../step/setup/addScriptsToPackageJson';
import addShipConfig from '../step/setup/addShipConfig';
import addCircleCIConfig from '../step/setup/addCircleCIConfig';
import integrations from '../step/setup/CI';
import { print } from '../util';
import { success } from '../color';

Expand All @@ -19,15 +19,14 @@ async function setup({ help = false, dir = '.', dryRun = false }) {
const {
baseBranch,
releaseBranch,
configureCircleCI,
scheduleCircleCI,
cronExpr,
useMonorepo,
mainVersionFile,
packagesToBump,
packagesToPublish,
isScoped,
isPublic,
ciIntegration,
ciConfig,
} = await askQuestions({ dir });
jeetiss marked this conversation as resolved.
Show resolved Hide resolved
const outputs = [
addDevDependencies({ dependencies: ['shipjs'], dir, dryRun }),
Expand All @@ -44,11 +43,16 @@ async function setup({ help = false, dir = '.', dryRun = false }) {
dir,
dryRun,
}),
addCircleCIConfig({
integrations[ciIntegration].addConfig({
...ciConfig,
isScoped,
isPublic,
baseBranch,
configureCircleCI,
scheduleCircleCI,
cronExpr,
releaseBranch,
useMonorepo,
mainVersionFile,
packagesToBump,
packagesToPublish,
dir,
dryRun,
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { getGitConfig } from 'shipjs-lib';
import runStep from '../runStep';
import runStep from '../../runStep';
import fs from 'fs';
import path from 'path';
import ejs from 'ejs';
import mkdirp from 'mkdirp';
import { print } from '../../util';
import { info, warning } from '../../color';
import { print } from '../../../util';
import { info, warning } from '../../../color';

export default ({
baseBranch,
configureCircleCI,
scheduleCircleCI,
cronExpr,
dir,
dryRun,
}) =>
export default ({ baseBranch, schedulePrepare, cronExpr, dir, dryRun }) =>
runStep(
{
title: 'Creating CircleCI configuration',
skipIf: () => !configureCircleCI,
},
() => {
const filePath = path.resolve(dir, '.circleci', 'config.yml');
Expand All @@ -38,7 +30,7 @@ export default ({
}
const content = getConfig({
baseBranch,
scheduleCircleCI,
schedulePrepare,
cronExpr,
gitUserName: getGitConfig('user.name') || 'Your Name',
gitUserEmail: getGitConfig('user.email') || '[email protected]',
Expand All @@ -62,7 +54,7 @@ export default ({

function getConfig({
baseBranch,
scheduleCircleCI,
schedulePrepare,
cronExpr,
gitUserName,
gitUserEmail,
Expand Down Expand Up @@ -114,7 +106,7 @@ jobs:
- run:
name: Run Tests
command: yarn test
<% if (scheduleCircleCI) { %>
<% if (schedulePrepare) { %>
prepare_release:
<<: *defaults
steps:
Expand Down Expand Up @@ -149,7 +141,7 @@ workflows:
- release_if_needed:
requires:
- test
<% if (scheduleCircleCI) { %>
<% if (schedulePrepare) { %>
schedule_release:
triggers:
- schedule:
Expand All @@ -162,6 +154,6 @@ workflows:
- prepare_release
<% } %>
`,
{ baseBranch, scheduleCircleCI, cronExpr, gitUserName, gitUserEmail }
{ baseBranch, schedulePrepare, cronExpr, gitUserName, gitUserEmail }
);
}
202 changes: 202 additions & 0 deletions packages/shipjs/src/step/setup/CI/addGithubActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { getGitConfig } from 'shipjs-lib';
import runStep from '../../runStep';
import fs from 'fs';
import path from 'path';
import ejs from 'ejs';
import mkdirp from 'mkdirp';
import { print } from '../../../util';
import { info, warning } from '../../../color';

export default ({
baseBranch,
releaseBranch,
manualPrepare,
schedulePrepare,
cronExpr,
dir,
dryRun,
}) =>
runStep(
{
title: 'Creating GitHub Actions configuration',
},
() => {
const gitUserName = getGitConfig('user.name') || 'Your Name';
const gitUserEmail = getGitConfig('user.email') || '[email protected]';

const log = [
createGithubAction({
jeetiss marked this conversation as resolved.
Show resolved Hide resolved
content: getBaseConfig({ releaseBranch }),
actionPath: '.github/workflows/shipjs-trigger.yml',
dir,
dryRun,
}),
manualPrepare &&
createGithubAction({
content: getManualPrepareConfig({
baseBranch,
gitUserName,
gitUserEmail,
}),
actionPath: '.github/workflows/shipjs-manual-prepare.yml',
dir,
dryRun,
}),
schedulePrepare &&
createGithubAction({
content: getScheduleConfig({
baseBranch,
cronExpr,
gitUserName,
gitUserEmail,
}),
actionPath: '.github/workflows/shipjs-schedules-prepare.yml',
dir,
dryRun,
}),

() => {
print(' You still need to finish setting up at GitHub Actions.');
// add link to readme here
jeetiss marked this conversation as resolved.
Show resolved Hide resolved
},
].filter(Boolean);

return () => log.forEach(printResult => printResult());
}
);

function createGithubAction({ content, actionPath, dir, dryRun }) {
const filePath = path.resolve(dir, actionPath);

if (fs.existsSync(filePath)) {
return () => {
print(`${warning('✘')} \`${actionPath}\` already exists.`);
};
}

if (dryRun) {
print(actionPath);
print(content);
} else {
mkdirp.sync(path.dirname(filePath));
fs.writeFileSync(filePath, content);
}
return () => {
print(`${info('✔')} Created \`${actionPath}\`.`);
};
}

function getBaseConfig({ releaseBranch }) {
return ejs.render(
`
name: Ship js trigger
on:
push:
branches:
- <%= releaseBranch %>
jobs:
build:
name: Build
runs-on: Ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
registry-url: 'https://registry.npmjs.org'
- run: git switch <%= releaseBranch %>
- run: npm install
- run: npm run release:trigger
env:
GITHUB_TOKEN: \${{ secrets.GH_TOKEN }}
NODE_AUTH_TOKEN: \${{ secrets.NPM_AUTH_TOKEN }}

`,
{ releaseBranch }
);
}

function getManualPrepareConfig({ baseBranch, gitUserName, gitUserEmail }) {
return ejs.render(
`
name: Ship js Manual Prepare
on:
issue_comment:
types: [created]
jobs:
manual_prepare:
if: |
github.event_name == 'issue_comment' &&
(github.event.comment.author_association == 'member' || github.event.comment.author_association == 'owner') &&
startsWith(github.event.comment.body, '@shipjs prepare')
runs-on: Ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
- run: git checkout <%= baseBranch %>
- run: npm install
- run: |
git config --global user.email '<%= gitUserEmail %>'
git config --global user.name '<%= gitUserName %>'
- run: npm run release:prepare -- --yes --no-browse
env:
GITHUB_TOKEN: \${{ secrets.GH_TOKEN }}

create_done_comment:
if: success()
needs: manual_prepare
runs-on: Ubuntu-latest
steps:
- uses: actions/github@master
env:
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
with:
args: comment '@\${{ github.actor }} \`shipjs prepare\` done'

create_fail_comment:
if: cancelled() || failure()
needs: manual_prepare
runs-on: Ubuntu-latest
steps:
- uses: actions/github@master
env:
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
with:
args: comment '@\${{ github.actor }} \`shipjs prepare\` fail'

`,
{ baseBranch, gitUserName, gitUserEmail }
);
}

function getScheduleConfig({
baseBranch,
cronExpr,
gitUserName,
gitUserEmail,
}) {
return ejs.render(
`
name: Ship js Schedule Prepare
on:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '<%= cronExpr %>'
jobs:
schedule_prepare:
runs-on: Ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
- run: git switch <%= baseBranch %>
- run: npm install
- run: |
git config --global user.email '<%= gitUserEmail %>'
git config --global user.name '<%= gitUserName %>'
- run: npm run release:prepare -- --yes --no-browse
env:
GITHUB_TOKEN: \${{ secrets.GH_TOKEN }}

`,
{ baseBranch, cronExpr, gitUserName, gitUserEmail }
);
}
37 changes: 37 additions & 0 deletions packages/shipjs/src/step/setup/CI/askCircleCI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import inquirer from 'inquirer';
import formatMessage from '../formatMessage';

export default async function askCircleCI() {
const { schedulePrepare } = await inquirer.prompt([
{
type: 'confirm',
name: 'schedulePrepare',
message: 'Schedule your release via CircleCI?',
default: true,
},
]);
const offset = new Date().getTimezoneOffset() / 60;
const hour = 11 + offset;
const tuesday = 2;
const defaultCronExpr = `0 ${hour} * * ${tuesday}`;
const { cronExpr } = await inquirer.prompt(
[
schedulePrepare
? {
type: 'input',
name: 'cronExpr',
message: formatMessage(
'When to release?',
'To learn about cron expressions, visit https://crontab.guru/\nThe default value ("Every Tuesday 11am")'
),
default: defaultCronExpr,
}
: undefined,
].filter(Boolean)
);

return {
schedulePrepare,
cronExpr,
};
}
Loading