Skip to content

Commit

Permalink
Merge pull request #81 from dominykas/cleanup-command
Browse files Browse the repository at this point in the history
  • Loading branch information
dominykas authored Feb 28, 2021
2 parents e603bf4 + 196d30a commit 075c33e
Show file tree
Hide file tree
Showing 29 changed files with 436 additions and 15 deletions.
21 changes: 21 additions & 0 deletions USAGE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
# Usage


## `wiby clean`



Use this command to clean up branches created by wiby (i.e. branches with the
"wiby-" prefix).

```
Options:
--dependent URL of a dependent [string]
--config Path to the configuration file. By default it will try to load
the configuration from the first file it finds in the current
working directory: `.wiby.json`, `.wiby.js` [string]
--all Remove all branches with "wiby-" prefix. By default, `wiby clean`
will only remove the branch that would be created if `wiby test`
ran in the current repository, on the current branch.
--dry-run Print the list of branches to be removed.
```


## `wiby result`


Expand Down
30 changes: 30 additions & 0 deletions bin/commands/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict'

const wiby = require('../..')

exports.desc = 'Use this command to clean up branches created by wiby (i.e. branches with the "wiby-" prefix).'

exports.builder = (yargs) => yargs
.option('dependent', {
desc: 'URL of a dependent',
type: 'string',
conflicts: 'config'
})
.option('config', {
desc: 'Path to the configuration file. By default it will try to load the configuration from the first file it finds in the current working directory: `.wiby.json`, `.wiby.js`',
type: 'string'
})
.option('all', {
desc: 'Remove all branches with "wiby-" prefix. By default, `wiby clean` will only remove the branch that would be created if `wiby test` ran in the current repository, on the current branch.'
})
.option('dry-run', {
desc: 'Print the list of branches to be removed.'
})

exports.handler = async (params) => {
const config = params.dependent
? { dependents: [{ repository: params.dependent }] }
: wiby.validate({ config: params.config })

return wiby.clean(config, params)
}
2 changes: 2 additions & 0 deletions bin/generate-usage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env node

'use strict'

/**
* Builds new content for USAGE.md page according to wiby --help commands list
*/
Expand Down
7 changes: 7 additions & 0 deletions bin/wiby
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/usr/bin/env node

'use strict'

process.on('unhandledRejection', (err) => {

throw err;
});

require('dotenv').config()

const chalk = require('chalk')
Expand Down
44 changes: 44 additions & 0 deletions lib/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

const github = require('./github')
const gitURLParse = require('git-url-parse')
const logger = require('./logger')

// setup logger namespace
const cleanCommandNamespace = 'wiby:clean'
const debug = logger(cleanCommandNamespace)

module.exports = async ({ dependents }, { all, dryRun }) => {
// enable log output for clean command without DEBUG env
logger.enableLogs(cleanCommandNamespace)

const parentPkgJSON = await require('./test').getLocalPackageJSON()
const parentPkgInfo = gitURLParse(parentPkgJSON.repository.url)
debug(`Parent module: ${parentPkgInfo.owner}/${parentPkgJSON.name}`)

console.log(dryRun ? 'Branches to be deleted:' : 'Branches deleted:')

for (const { repository: url } of dependents) {
const dependentPkgInfo = gitURLParse(url)

let branches

const branch = await require('./result').getBranchName(parentPkgJSON.name)

if (all) {
branches = await github.getWibyBranches(dependentPkgInfo.owner, dependentPkgInfo.name)
} else if (await github.getBranch(dependentPkgInfo.owner, dependentPkgInfo.name, branch)) {
branches = [branch]
} else {
branches = []
}

if (!dryRun) {
for (const branch of branches) {
await github.deleteBranch(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
}
}

console.log(`- ${dependentPkgInfo}: ${branches.length ? branches.join(', ') : '(none)'}`)
}
}
48 changes: 39 additions & 9 deletions lib/github.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
'use strict'

const { graphql } = require('@octokit/graphql')
const { Octokit } = require('@octokit/rest')

const queries = require('./graphql')

const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN
})
Expand All @@ -13,15 +18,7 @@ const graphqlWithAuth = graphql.defaults({
module.exports.getPackageJson = async function getPackageJson (owner, repo) {
try {
const resp = await graphqlWithAuth({
query: `query($owner: String!, $repo: String!) {
repository(name: $repo, owner: $owner) {
object(expression: "HEAD:package.json") {
... on Blob {
text
}
}
}
}`,
query: queries.getPackageJson,
owner: owner,
repo: repo
})
Expand All @@ -35,6 +32,16 @@ module.exports.getPackageJson = async function getPackageJson (owner, repo) {
}
}

module.exports.getWibyBranches = async function (owner, repo) {
const resp = await graphqlWithAuth({
query: queries.getWibyBranches,
owner: owner,
repo: repo
})
const edges = resp.organization.repository.refs.edges
return edges.map(({ node: { branchName } }) => branchName)
}

module.exports.getShas = async function getShas (owner, repo) {
const resp = await octokit.repos.listCommits({
owner,
Expand Down Expand Up @@ -91,6 +98,29 @@ module.exports.createBranch = async function createBranch (owner, repo, commitSh
})
}

module.exports.deleteBranch = async function deleteBranch (owner, repo, branch) {
await octokit.git.deleteRef({
owner,
repo,
ref: `heads/${branch}`
})
}

module.exports.getBranch = async function getBranch (owner, repo, branch) {
try {
return await octokit.repos.getBranch({
owner,
repo,
branch
})
} catch (err) {
if (err.status === 404) {
return undefined
}
throw err
}
}

module.exports.getChecks = async function getChecks (owner, repo, branch) {
return octokit.checks.listForRef({
owner,
Expand Down
9 changes: 9 additions & 0 deletions lib/graphql/getPackageJson.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query($owner: String!, $repo: String!) {
repository(name: $repo, owner: $owner) {
object(expression: "HEAD:package.json") {
... on Blob {
text
}
}
}
}
18 changes: 18 additions & 0 deletions lib/graphql/getWibyBranches.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
query getExistingRepoBranches($owner: String!, $repo: String!) {
organization(login: $owner) {
repository(name: $repo) {
id
name
refs(refPrefix: "refs/heads/", query: "wiby-", first: 100) {
edges {
node {
branchName: name
}
}
pageInfo {
endCursor
}
}
}
}
}
8 changes: 8 additions & 0 deletions lib/graphql/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict'

const fs = require('fs')
const path = require('path')

exports.getPackageJson = fs.readFileSync(path.join(__dirname, 'getPackageJson.graphql')).toString()

exports.getWibyBranches = fs.readFileSync(path.join(__dirname, 'getWibyBranches.graphql')).toString()
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict'

exports.clean = require('./clean')

exports.test = require('./test')

exports.result = require('./result')
Expand Down
2 changes: 2 additions & 0 deletions lib/logger.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const debugPkg = require('debug')

/**
Expand Down
2 changes: 2 additions & 0 deletions lib/result.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const test = require('./test')
const github = require('./github')
const gitURLParse = require('git-url-parse')
Expand Down
2 changes: 2 additions & 0 deletions lib/test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const fsPromises = require('fs').promises
const github = require('./github')
const gitURLParse = require('git-url-parse')
Expand Down
38 changes: 38 additions & 0 deletions test/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict'

require('dotenv').config()
const tap = require('tap')
const nock = require('nock')
const CONFIG = require('./fixtures/config')
const wiby = require('..')

tap.beforeEach(async () => {
nock.disableNetConnect()
})

tap.afterEach(async () => {
nock.cleanAll()
nock.enableNetConnect()
})

tap.test('wiby.clean()', async (tap) => {
tap.test('should check if the wiby branch exists', async (tap) => {
nock('https://api.github.com')
.get(`/repos/wiby-test/${CONFIG.DEP_REPO}/branches/wiby-wiby`)
.reply(404)

await wiby.clean({ dependents: [{ repository: `https://www.github.com/${CONFIG.DEP_ORG}/${CONFIG.DEP_REPO}` }] }, {})

// implied assertion - no DELETE requests expected - we don't need to delete the missing `wiby-wiby` branch
})

tap.test('should rethrow when github API inaccessible during branch check', async (tap) => {
nock('https://api.github.com')
.get(`/repos/wiby-test/${CONFIG.DEP_REPO}/branches/wiby-wiby`)
.reply(500)

await tap.rejects(
wiby.clean({ dependents: [{ repository: `https://www.github.com/${CONFIG.DEP_ORG}/${CONFIG.DEP_REPO}` }] }, {})
)
})
})
69 changes: 63 additions & 6 deletions test/cli.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const tap = require('tap')
const childProcess = require('child_process')
const path = require('path')
Expand Down Expand Up @@ -26,7 +28,7 @@ tap.test('test command', async (tap) => {
}
}).toString()

tap.equal(true, result.includes('Changes pushed to https://github.com/wiby-test/fakeRepo/blob/wiby-wiby/package.json'))
tap.includes(result, 'Changes pushed to https://github.com/wiby-test/fakeRepo/blob/wiby-wiby/package.json')
})

tap.test('test command should call test module with all deps from .wiby.json', async (tap) => {
Expand All @@ -37,9 +39,9 @@ tap.test('test command', async (tap) => {
}
}).toString()

tap.equal(true, result.includes('Changes pushed to https://github.com/wiby-test/pass/blob/wiby-wiby/package.json'))
tap.equal(true, result.includes('Changes pushed to https://github.com/wiby-test/fail/blob/wiby-wiby/package.json'))
tap.equal(true, result.includes('Changes pushed to https://github.com/wiby-test/partial/blob/wiby-wiby/package.json'))
tap.includes(result, 'Changes pushed to https://github.com/wiby-test/pass/blob/wiby-wiby/package.json')
tap.includes(result, 'Changes pushed to https://github.com/wiby-test/fail/blob/wiby-wiby/package.json')
tap.includes(result, 'Changes pushed to https://github.com/wiby-test/partial/blob/wiby-wiby/package.json')
})
})

Expand Down Expand Up @@ -146,8 +148,63 @@ tap.test('result command', async (tap) => {

tap.test('validate command', async (tap) => {
tap.test('should pass on wiby itself', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} validate`, { cwd: cwd }).toString()
console.info(result)
childProcess.execSync(`${wibyCommand} validate`, { cwd: cwd })
tap.end()
})
})

tap.test('clean command', async (tap) => {
tap.test('should delete test branch in all configured test modules', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean`, {
cwd: cwd,
env: {
NODE_OPTIONS: '-r ./test/fixtures/http/clean-command.js'
}
}).toString()

tap.includes(result, 'Branches deleted:')
tap.includes(result, '- https://github.com/wiby-test/partial: wiby-wiby')
tap.includes(result, '- git://github.com/wiby-test/fail: wiby-wiby')
tap.includes(result, '- git+https://github.com/wiby-test/pass: wiby-wiby')
})

tap.test('should delete test branch in the test module at dependent URI', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean --dependent="https://github.com/wiby-test/fakeRepo"`, {
cwd: cwd,
env: {
NODE_OPTIONS: '-r ./test/fixtures/http/clean-command.js'
}
}).toString()

tap.includes(result, 'Branches deleted:')
tap.includes(result, '- https://github.com/wiby-test/fakeRepo: wiby-wiby')
})

tap.test('should delete all wiby-* branches in all configured test modules', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean --all`, {
cwd: cwd,
env: {
NODE_OPTIONS: '-r ./test/fixtures/http/clean-command-all.js'
}
}).toString()

tap.includes(result, 'Branches deleted:')
tap.includes(result, '- https://github.com/wiby-test/partial: wiby-partial-one, wiby-partial-two')
tap.includes(result, '- git://github.com/wiby-test/fail: wiby-fail-one, wiby-fail-two')
tap.includes(result, '- git+https://github.com/wiby-test/pass: wiby-pass-one, wiby-pass-two')
})

tap.test('should not delete during dry-run', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean --dry-run`, {
cwd: cwd,
env: {
NODE_OPTIONS: '-r ./test/fixtures/http/clean-command-dry.js'
}
}).toString()

tap.includes(result, 'Branches to be deleted:')
tap.includes(result, '- https://github.com/wiby-test/partial: wiby-wiby')
tap.includes(result, '- git://github.com/wiby-test/fail: wiby-wiby')
tap.includes(result, '- git+https://github.com/wiby-test/pass: wiby-wiby')
})
})
Loading

0 comments on commit 075c33e

Please sign in to comment.