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

Name wiby test branches based on the dependency branch name #85

Merged
merged 4 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion lib/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ module.exports = async ({ dependents }, { all, dryRun }) => {

let branches

const branch = await context.getTestingBranchName(parentPkgJSON.name)
const parentBranchName = await context.getParentBranchName()
const branch = await context.getTestingBranchName(parentBranchName)

if (all) {
branches = await github.getWibyBranches(dependentPkgInfo.owner, dependentPkgInfo.name)
Expand Down
17 changes: 14 additions & 3 deletions lib/context.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
'use strict'

const simpleGit = require('simple-git')
const fsPromises = require('fs').promises

exports.getTestingBranchName = async function getTestingBranchName (parentPackageName) {
return `wiby-${parentPackageName}`
exports.getParentBranchName = async function getParentBranchName () {
const { current } = await simpleGit().branch()

return current
}

exports.getTestingBranchName = function getTestingBranchName (parentBranchName) {
return `wiby-${parentBranchName}`
}

exports.getDependencyLink = async function getDependencyLink (owner, repo, commitish) {
return `${owner}/${repo}#${commitish}`
}

exports.getLocalPackageJSON = async function getLocalPackageJSON () {
Expand All @@ -15,7 +26,7 @@ exports.getLocalPackageJSON = async function getLocalPackageJSON () {
The check should search both the dev and peer dependencies to find out if the dependency is
regular, dev or peer.
*/
exports.checkPackageInPackageJSON = function checkPackageInPackageJSON (dep, packageJSON) {
exports.checkDependentUsesParent = function checkDependentUsesParent (dep, packageJSON) {
const dependencyKeyNames = [
'dependencies',
'devDependencies',
Expand Down
5 changes: 3 additions & 2 deletions lib/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ module.exports = async function ({ dependents }) {
const dependentPkgJSON = await github.getPackageJson(dependentPkgInfo.owner, dependentPkgInfo.name)
debug(`Dependent module: ${dependentPkgInfo.owner}/${dependentPkgInfo.name}`)

if (!context.checkPackageInPackageJSON(parentPkgJSON.name, dependentPkgJSON)) {
if (!context.checkDependentUsesParent(parentPkgJSON.name, dependentPkgJSON)) {
throw new Error(`${parentPkgInfo.owner}/${parentPkgJSON.name} not found in the package.json of ${dependentPkgInfo.owner}/${dependentPkgInfo.name}`)
}

const branch = await context.getTestingBranchName(parentPkgJSON.name)
const parentBranchName = await context.getParentBranchName()
const branch = await context.getTestingBranchName(parentBranchName)
let resp = await github.getChecks(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
if (resp.data.check_runs.length === 0) {
resp = await github.getCommitStatusesForRef(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
Expand Down
59 changes: 24 additions & 35 deletions lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,47 @@ module.exports = async function ({ dependents }) {
logger.enableLogs(testCommandNamespace)

const parentPkgJSON = await context.getLocalPackageJSON()
const parentPkgInfo = gitURLParse(parentPkgJSON.repository.url)
debug(`Parent module: ${parentPkgInfo.owner}/${parentPkgJSON.name}`)
const parentRepositoryInfo = gitURLParse(parentPkgJSON.repository.url)
const parentBranchName = await context.getParentBranchName()
debug(`Parent module: ${parentRepositoryInfo.owner}/${parentPkgJSON.name}`)

const commitURL = await getCommitURL(parentPkgInfo.owner, parentPkgInfo.name)
debug('Commit URL to test:', commitURL)
const parentDependencyLink = await context.getDependencyLink(parentRepositoryInfo.owner, parentRepositoryInfo.name, parentBranchName)
debug('Commit URL to test:', parentDependencyLink)

for (const { repository: url } of dependents) {
const dependentPkgInfo = gitURLParse(url)
const dependentPkgJSON = await github.getPackageJson(dependentPkgInfo.owner, dependentPkgInfo.name)
debug(`Dependent module: ${dependentPkgInfo.owner}/${dependentPkgInfo.name}`)
const dependentRepositoryInfo = gitURLParse(url)
const dependentPkgJson = await github.getPackageJson(dependentRepositoryInfo.owner, dependentRepositoryInfo.name)
debug(`Dependent module: ${dependentRepositoryInfo.owner}/${dependentRepositoryInfo.name}`)

if (!context.checkPackageInPackageJSON(parentPkgJSON.name, dependentPkgJSON)) {
throw new Error(`${parentPkgInfo.owner}/${parentPkgJSON.name} not found in the package.json of ${dependentPkgInfo.owner}/${dependentPkgInfo.name}`)
if (!context.checkDependentUsesParent(parentPkgJSON.name, dependentPkgJson)) {
throw new Error(`${parentRepositoryInfo.owner}/${parentPkgJSON.name} not found in the package.json of ${dependentRepositoryInfo.owner}/${dependentRepositoryInfo.name}`)
}

const patchedPackageJSON = applyPatch(commitURL, parentPkgJSON.name, dependentPkgJSON)
await pushPatch(patchedPackageJSON, dependentPkgInfo.owner, dependentPkgInfo.name, parentPkgJSON.name)
const patchedPackageJSON = applyPatch(parentDependencyLink, parentPkgJSON.name, dependentPkgJson, parentPkgJSON.name)
await pushPatch(patchedPackageJSON, dependentRepositoryInfo.owner, dependentRepositoryInfo.name, parentPkgJSON.name, parentBranchName)
}
}

const getCommitHash = async function getCommitHash (owner, repo) {
const [headSha] = await github.getShas(owner, repo)
return headSha
}

const getCommitURL = async function getCommitURL (owner, repo, hash) {
hash = hash || await getCommitHash(owner, repo)

const patch = `${owner}/${repo}#${hash}`
return patch
}

const applyPatch = module.exports.applyPatch =
function applyPatch (patch, module, dependentPkgJSON) {
const dependencyType = context.checkPackageInPackageJSON(module, dependentPkgJSON)
const dependencyType = context.checkDependentUsesParent(module, dependentPkgJSON)
if (!dependencyType) {
throw new Error('Dependency not found in package.json')
}
dependentPkgJSON[dependencyType][module] = patch
return dependentPkgJSON
}

async function pushPatch (packageJSON, owner, repo, dep) {
const file = JSON.stringify(packageJSON, null, 2) + '\n' // assumes package.json is using two spaces
async function pushPatch (dependentPkgJson, dependentOwner, dependentRepo, parentName, parentBranchName) {
const file = JSON.stringify(dependentPkgJson, null, 2) + '\n' // assumes package.json is using two spaces
const encodedFile = Buffer.from(file).toString('base64')
const message = `wiby: update ${dep}`
const branch = await context.getTestingBranchName(dep)

const [headSha, treeSha] = await github.getShas(owner, repo)
const blobSha = await github.createBlob(owner, repo, encodedFile)
const newTreeSha = await github.createTree(owner, repo, treeSha, blobSha)
const commitSha = await github.createCommit(owner, repo, message, newTreeSha, headSha)
await github.createBranch(owner, repo, commitSha, branch)
debug(`Changes pushed to https://github.com/${owner}/${repo}/blob/${branch}/package.json`)
const message = `wiby: update ${parentName}`
const branch = await context.getTestingBranchName(parentBranchName)

const [headSha, treeSha] = await github.getShas(dependentOwner, dependentRepo)
const blobSha = await github.createBlob(dependentOwner, dependentRepo, encodedFile)
const newTreeSha = await github.createTree(dependentOwner, dependentRepo, treeSha, blobSha)
const commitSha = await github.createCommit(dependentOwner, dependentRepo, message, newTreeSha, headSha)
await github.createBranch(dependentOwner, dependentRepo, commitSha, branch)
debug(`Changes pushed to https://github.com/${dependentOwner}/${dependentRepo}/blob/${branch}/package.json`)
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@
"git-url-parse": "^11.1.2",
"joi": "^17.2.1",
"node-fetch": "^2.6.0",
"simple-git": "^2.35.1",
"yargs": "^16.0.0"
},
"devDependencies": {
"nock": "^13.0.3",
"standard": "^16.0.0",
"tap": "^14.10.7"
"tap": "^14.10.7",
"tmp": "^0.2.1"
},
"standard": {
"ignore": [
Expand Down
26 changes: 15 additions & 11 deletions test/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,36 @@
require('dotenv').config()
const tap = require('tap')
const nock = require('nock')

const CONFIG = require('./fixtures/config')
const gitFixture = require('./fixtures/git')

const wiby = require('..')

tap.beforeEach(async () => {
nock.disableNetConnect()
})
tap.test('wiby.clean()', async (tap) => {
tap.beforeEach(async () => {
nock.disableNetConnect()
gitFixture.init()
})

tap.afterEach(async () => {
nock.cleanAll()
nock.enableNetConnect()
})
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`)
.get(`/repos/wiby-test/${CONFIG.DEP_REPO}/branches/wiby-running-unit-tests`)
.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
// implied assertion - no DELETE requests expected - we don't need to delete the missing `wiby-running-unit-tests` 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`)
.get(`/repos/wiby-test/${CONFIG.DEP_REPO}/branches/wiby-running-unit-tests`)
.reply(500)

await tap.rejects(
Expand Down
31 changes: 18 additions & 13 deletions test/cli/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,44 @@ const tap = require('tap')
const childProcess = require('child_process')
const path = require('path')

const cwd = path.join(__dirname, '..', '..')
const wibyCommand = path.join(cwd, 'bin', 'wiby')
const gitFixture = require('../fixtures/git')

const wibyCommand = path.join(__dirname, '..', '..', 'bin', 'wiby')
const fixturesPath = path.resolve(path.join(__dirname, '..', 'fixtures'))

tap.test('clean command', async (tap) => {
tap.beforeEach(async () => {
gitFixture.init()
})

tap.test('should delete test branch in all configured test modules', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/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.includes(result, '- https://github.com/wiby-test/partial: wiby-running-unit-tests')
tap.includes(result, '- git://github.com/wiby-test/fail: wiby-running-unit-tests')
tap.includes(result, '- git+https://github.com/wiby-test/pass: wiby-running-unit-tests')
})

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: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/http/clean-command.js`
}
}).toString()
tap.includes(result, 'Branches deleted:')
tap.includes(result, '- https://github.com/wiby-test/fakeRepo: wiby-wiby')
tap.includes(result, '- https://github.com/wiby-test/fakeRepo: wiby-running-unit-tests')
})

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

tap.test('should not delete during dry-run', async (tap) => {
const result = childProcess.execSync(`${wibyCommand} clean --dry-run`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/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')
tap.includes(result, '- https://github.com/wiby-test/partial: wiby-running-unit-tests')
tap.includes(result, '- git://github.com/wiby-test/fail: wiby-running-unit-tests')
tap.includes(result, '- git+https://github.com/wiby-test/pass: wiby-running-unit-tests')
})
})
21 changes: 13 additions & 8 deletions test/cli/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ const childProcess = require('child_process')
const path = require('path')
const fs = require('fs')

const cwd = path.join(__dirname, '..', '..')
const wibyCommand = path.join(cwd, 'bin', 'wiby')
const gitFixture = require('../fixtures/git')

const wibyCommand = path.join(__dirname, '..', '..', 'bin', 'wiby')
const fixturesPath = path.resolve(path.join(__dirname, '..', 'fixtures'))

const PENDING_RESULT_EXIT_CODE = 64

tap.test('result command', async (tap) => {
tap.beforeEach(async () => {
gitFixture.init()
})

tap.test('result command should fail when config and dependent provided', async (tap) => {
try {
childProcess.execSync(`${wibyCommand} result --config=.wiby.json --dependent="https://github.com/wiby-test/fakeRepo"`, { cwd: cwd }).toString()
childProcess.execSync(`${wibyCommand} result --config=.wiby.json --dependent="https://github.com/wiby-test/fakeRepo"`).toString()
tap.fail()
} catch (err) {
tap.equal(true, err.message.includes('Arguments dependent and config are mutually exclusive'))
Expand All @@ -30,8 +35,8 @@ tap.test('result command', async (tap) => {

try {
childProcess.execSync(`${wibyCommand} result --dependent="https://github.com/wiby-test/fakeRepo"`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/http/result-command-positive.js`
}
})
Expand All @@ -52,8 +57,8 @@ tap.test('result command', async (tap) => {

try {
childProcess.execSync(`${wibyCommand} result`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/http/result-command-positive.js`
}
})
Expand All @@ -65,7 +70,7 @@ tap.test('result command', async (tap) => {
}
})

tap.test('result command handles empty response from github.getChecks()', tap => {
tap.test('result command handles empty response from github.getChecks()', (tap) => {
const expected = fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'expected-outputs', 'result', 'result-output-single-dependant.md'),
'utf-8'
Expand All @@ -74,8 +79,8 @@ tap.test('result command', async (tap) => {

try {
childProcess.execSync(`${wibyCommand} result --dependent="https://github.com/wiby-test/fakeRepo"`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/http/result-command-empty-branch-checks.js`
}
})
Expand All @@ -98,8 +103,8 @@ tap.test('result command', async (tap) => {

try {
childProcess.execSync(`${wibyCommand} result --dependent="https://github.com/wiby-test/fakeRepo"`, {
cwd: cwd,
env: {
...process.env,
NODE_OPTIONS: `-r ${fixturesPath}/http/result-command-positive-checks-failed.js`
}
})
Expand Down
Loading