-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(setup): add github actions as CI option (#502)
* prepare setup for github actions * add base github actions integration * add manual prepare config generation * fix * checkout to base branch * switch to release branch before trigger * add schedule config * scheduleCircleCI -> schedulePrepare * rename NPM_TOKEN to NPM_AUTH_TOKEN for consistency * fix vars names and typos * Github to GitHub * fix typo * fix prepare * return ciIntegration * chore: rename files * fix formatting * use duble quotes in gh actions * use single quote in condition * use bash if statement to choose package manager Co-authored-by: Eunjae Lee <[email protected]>
- Loading branch information
1 parent
d55895c
commit 923cc87
Showing
8 changed files
with
381 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | ||
|
@@ -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]', | ||
|
@@ -62,7 +54,7 @@ export default ({ | |
|
||
function getConfig({ | ||
baseBranch, | ||
scheduleCircleCI, | ||
schedulePrepare, | ||
cronExpr, | ||
gitUserName, | ||
gitUserEmail, | ||
|
@@ -114,7 +106,7 @@ jobs: | |
- run: | ||
name: Run Tests | ||
command: yarn test | ||
<% if (scheduleCircleCI) { %> | ||
<% if (schedulePrepare) { %> | ||
prepare_release: | ||
<<: *defaults | ||
steps: | ||
|
@@ -149,7 +141,7 @@ workflows: | |
- release_if_needed: | ||
requires: | ||
- test | ||
<% if (scheduleCircleCI) { %> | ||
<% if (schedulePrepare) { %> | ||
schedule_release: | ||
triggers: | ||
- schedule: | ||
|
@@ -162,6 +154,6 @@ workflows: | |
- prepare_release | ||
<% } %> | ||
`, | ||
{ baseBranch, scheduleCircleCI, cronExpr, gitUserName, gitUserEmail } | ||
{ baseBranch, schedulePrepare, cronExpr, gitUserName, gitUserEmail } | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
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({ | ||
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-schedule-prepare.yml', | ||
dir, | ||
dryRun, | ||
}), | ||
|
||
() => { | ||
print(' You still need to finish setting up at GitHub Actions.'); | ||
// add link to readme here | ||
}, | ||
].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: | | ||
if [ -f "yarn.lock" ]; then | ||
yarn install | ||
else | ||
npm install | ||
fi | ||
- 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 | ||
with: | ||
fetch-depth: 0 | ||
ref: <%= baseBranch %> | ||
- uses: actions/setup-node@master | ||
- run: | | ||
if [ -f "yarn.lock" ]; then | ||
yarn install | ||
else | ||
npm install | ||
fi | ||
- 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 | ||
with: | ||
fetch-depth: 0 | ||
ref: <%= baseBranch %> | ||
- uses: actions/setup-node@master | ||
- run: | | ||
if [ -f "yarn.lock" ]; then | ||
yarn install | ||
else | ||
npm install | ||
fi | ||
- 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 } | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}; | ||
} |
Oops, something went wrong.