Skip to content

Commit

Permalink
lib/test: add initial prototype for wiby --test
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewhughes101 committed Jun 15, 2020
1 parent 9692bfb commit 0db2338
Show file tree
Hide file tree
Showing 9 changed files with 5,525 additions and 7 deletions.
20 changes: 17 additions & 3 deletions bin/wiby.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
#!/usr/bin/env node

require('dotenv').config()
const test = require('../lib/test')
const result = require('../lib/result')

if (process.argv[2] === 'test') {
test()
const args = require('yargs')
.option('test', {
alias: 't',
describe: 'Test your dependents'
})
.option('result', {
alias: 'r',
describe: 'Get the result of your tests'
})
.argv

if (args.test) {
test(args.test)
}

if (process.argv[2] === 'result') {
if (args.result) {
result()
}

// Usage: wiby --test URL
124 changes: 124 additions & 0 deletions lib/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
const { graphql } = require('@octokit/graphql')
const { Octokit } = require('@octokit/rest')
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN
})

const graphqlWithAuth = graphql.defaults({
headers: {
authorization: `token ${process.env.GITHUB_TOKEN}`
}
})

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: "master:package.json") {
... on Blob {
text
}
}
}
}`,
owner: owner,
repo: repo
})
return (JSON.parse(resp.repository.object.text))
} catch (err) {
if (err.errors && err.errors[0].type === 'NOT_FOUND') {
throw Error(`Could not find GitHub repository at https://www.github.com/${owner}/${repo}`)
} else {
throw err
}
}
}

module.exports.getPermissions =
async function getPermissions (owner, repo) {
try {
const resp = await graphqlWithAuth({
query: `query($owner: String!, $repo: String!) {
repository(name: $repo, owner: $owner) {
viewerPermission
}
}`,
owner: owner,
repo: repo
})
return resp.repository.viewerPermission
} catch (err) {
if (err.errors && err.errors[0].type === 'NOT_FOUND') {
throw Error(`Could not find GitHub repository at https://www.github.com/${owner}/${repo}`)
} else {
throw err
}
}
}

module.exports.getShas =
async function getShas (owner, repo) {
const resp = await octokit.repos.listCommits({
owner,
repo,
per_page: 1
})
const headSha = resp.data[0].sha
const treeSha = resp.data[0].commit.tree.sha
// console.log(`lastSha: ${headSha} treeSha: ${treeSha}`)
return [headSha, treeSha]
}

module.exports.createBlob =
async function createBlob (owner, repo, file) {
const {
data: { sha: blobSha }
} = await octokit.git.createBlob({
owner,
repo,
content: file,
encoding: 'base64'
})
return blobSha
}

module.exports.createTree = async function createTree (owner, repo, treeSha, blobSha) {
const resp = await octokit.git.createTree({
owner,
repo,
base_tree: treeSha,
tree: [
{ path: 'package.json', mode: '100644', sha: blobSha }
],
headers: {
Accept: 'application/json'
}
})
const newTreeSha = resp.data.sha
return newTreeSha
}

module.exports.createCommit =
async function createCommit (owner, repo, message, newTreeSha, headSha) {
const resp = await octokit.git.createCommit({
owner,
repo,
message: message,
tree: newTreeSha,
parents: [headSha]
})
const commitSha = resp.data.sha
return commitSha
}

module.exports.createBranch =
async function createBranch (owner, repo, commitSha, branch) {
await octokit.git.createRef({
owner,
repo,
sha: commitSha,
ref: `refs/heads/${branch}`
})
}
106 changes: 104 additions & 2 deletions lib/test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,105 @@
module.exports = () => {
console.log('wiby test')
const fsPromises = require('fs').promises
const fetch = require('node-fetch')
const github = require('./github')

module.exports = async function (url) {
const dep = await getLocalPackageName()
console.log('Got local package name: ', dep)
const [org, repo] = getOrgRepo(url)
console.log(`Got org: ${org} and repo: ${repo}`)
const packageJSON = await github.getPackageJson(org, repo)
if (!checkPackageInPackageJSON(dep, packageJSON)) {
throw new Error('Dependency not found in package.json')
}
const patch = await getPatch(dep)
console.log('Created patch: ', patch)
const patchedPackageJSON = applyPatch(patch, dep, packageJSON)
await pushPatch(patchedPackageJSON, org, repo, dep)
}

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

const checkPackageInPackageJSON = module.exports.checkPackageInPackageJSON =
function checkPackageInPackageJSON (dep, packageJSON) {
return Object.prototype.hasOwnProperty.call(packageJSON.dependencies, dep)
}

const getOrgRepo = module.exports.getOrgRepo =
function getOrgRepo (url) {
const repoOrgArr = (url.split('github.com'))[1].split('/')
const org = repoOrgArr[1]
const repo = repoOrgArr[2]
return [org, repo]
}

const getPatch = module.exports.getPatch =
async function getPatch (dep, hash) {
dep = dep || await getLocalPackageName()
const [org, repo] = await getGitHubOrgRepo(dep)
hash = hash || await getCommitHash(org, repo)
const patch = `${org}/${repo}#${hash}`
return patch
}

const getLocalPackageName = module.exports.getLocalPackageName =
async function getLocalPackageName (pkgPath) {
pkgPath = pkgPath || 'package.json'
let pkg = await fsPromises.readFile(pkgPath).catch((err) => {
throw (err)
})
pkg = JSON.parse(pkg)
return pkg.name
}

const getGitHubOrgRepo = module.exports.getGitHubOrgRepo =
async function getGitHubOrgRepo (dep) {
const urlRegex = /github.com\/([^/])+\/[^/]+/g
const resp = await fetchRegistryInfo(dep)
let org, repo
if (resp.repository && resp.repository.url) {
let gitUrl = (resp.repository.url).match(urlRegex)
if (gitUrl) {
gitUrl = gitUrl[0].replace(/(\.git)/g, '')
org = getOrgRepo(gitUrl)[0]
repo = getOrgRepo(gitUrl)[1]
}
}
if (!org && !repo) {
org = 'undefined'
repo = 'undefined'
}
return [org, repo]
}

const fetchRegistryInfo = module.exports.fetchRegistryInfo =
async function fetchRegistryInfo (dep) {
const resp = await fetch(`https://registry.npmjs.org/${dep}`)
return resp.json()
}

const applyPatch = module.exports.applyPatch =
function applyPatch (patch, dep, packageJSON) {
if (!Object.prototype.hasOwnProperty.call(packageJSON.dependencies, dep)) {
throw new Error('Dependency not found in package.json')
}
packageJSON.dependencies[dep] = patch
return packageJSON
}

async function pushPatch (packageJSON, owner, repo, dep) {
const file = JSON.stringify(packageJSON, null, 2) + '\n' // assumes package.json is using two spaces
const encodedFile = Buffer.from(file).toString('base64')
const message = `wiby: update ${dep}`
const branch = `wiby-${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)
console.log(`Changes pushed to https://github.com/${owner}/${repo}/blob/${branch}/package.json`)
}
Loading

0 comments on commit 0db2338

Please sign in to comment.