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

Allow global configuration using the .github repo #56

Merged
merged 1 commit into from
Jul 8, 2022
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
27 changes: 1 addition & 26 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const Sentry = require('@sentry/node');
Sentry.init({ dsn: process.env.SENTRY_DSN });
const generated = require('@noqcks/generated');
const minimatch = require("minimatch")
const yaml = require('js-yaml');

const labels = {
XS: {
Expand Down Expand Up @@ -59,30 +58,6 @@ function sizeLabel (lineCount, l) {
return [l.XXL.color, l.XXL.name]
}

/**
* getSizes grabs size information from the .github/labels.yml file
* so that each repository can define its own label sizes
* @param context The context of the PullRequest.
* @param owner The owner of the repository.
* @param repo The repository where the .gitattributes file is located.
*/
async function getCustomLabels(context, owner, repo) {
const path = ".github/labels.yml"

let response;
try {
response = await context.octokit.repos.getContent({owner, repo, path})
const content = yaml.load(
Buffer.from(response.data.content, 'base64').toString('utf-8'),
schema="JSON_SCHEMA",
json=true,
);
return {...labels, ...content}
} catch (e) {
return labels
}
}

/**
* getCustomGeneratedFiles will grab a list of file globs that determine
* generated files from the repos .gitattributes.
Expand Down Expand Up @@ -169,7 +144,7 @@ module.exports = app => {

// get list of custom generated files as defined in .gitattributes
const customGeneratedFiles = await getCustomGeneratedFiles(context, owner, repo)
const customLabels = await getCustomLabels(context, owner, repo);
const customLabels = await context.config('labels.yml', labels)

// list of files modified in the pull request
const res = await context.octokit.pulls.listFiles({
Expand Down
15 changes: 0 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"@noqcks/generated": "^1.0.1",
"@probot/adapter-aws-lambda-serverless": "^2.0.2",
"@sentry/node": "^4.3.0",
"js-yaml": "^4.1.0",
"minimatch": "^3.0.4",
"probot": "^11.0.6"
},
Expand Down
107 changes: 106 additions & 1 deletion tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const label = {
medium: "size%2FM"
}
const baseURL = `/repos/${owner}/${repo}`
const baseUrlDotGitHub = `/repos/${owner}/.github`

// Mocks
const mockListFiles = require('./mocks/listFiles.json')
Expand All @@ -22,6 +23,22 @@ const prOpenedPayload = require('./fixtures/pull_request.opened.json')
const prEditedPayload = require('./fixtures/pull_request.edited.json')
const prSynchronizedPayload = require('./fixtures/pull_request.synchronized.json')

// Custom configurations
const confCustomNameSLabel= {
S: {
name: 'customsmall',
lines: 10,
color: '5D9801',
},
}
const confOnlyMLabel = {
M: {
name: 'size/M',
lines: 30,
color: '7F7203',
},
}

describe('Pull Request Size', () => {
let probot;
beforeEach(() => {
Expand All @@ -40,6 +57,11 @@ describe('Pull Request Size', () => {
// listFiles
.get(baseURL+`/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// if label.yml not found, default labels will be used
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(404) // no label.yml config found in the current repo
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(404) // no label.yml config found in the user's .github repo
// getLabel
.get(baseURL+`/labels/${label.small}`)
.reply(200, mockLabel)
Expand All @@ -65,7 +87,12 @@ describe('Pull Request Size', () => {
// listFiles
.get(baseURL+`/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// // getLabel
// if label.yml not found, default labels will be used
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(404) // no label.yml config found in the current repo
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(404) // no label.yml config found in the user's .github repo
// getLabel
.get(baseURL+`/labels/${label.small}`)
.reply(200, mockLabel)
// createLabel
Expand Down Expand Up @@ -93,6 +120,11 @@ describe('Pull Request Size', () => {
// listFiles
.get(baseURL+`/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// if label.yml not found, default labels will be used
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(404) // no label.yml config found in the current repo
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(404) // no label.yml config found in the user's .github repo
// deleteLabel label/M
.delete(baseURL+`/issues/${pull_number}/labels/${label.medium}`)
.reply(200)
Expand All @@ -118,6 +150,11 @@ describe('Pull Request Size', () => {
// listFiles
.get(baseURL+`/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// if label.yml not found, default labels will be used
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(404) // no label.yml config found in the current repo
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(404) // no label.yml config found in the user's .github repo
// createLabel
.post(baseURL+`/labels`)
.reply(201, mockLabel)
Expand All @@ -132,6 +169,74 @@ describe('Pull Request Size', () => {
})
})

test('verify custom labels from current repo takes precedence to the default ones', async () => {
nock("https://api.github.com")
// listFiles
.get(baseURL + `/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// use custom name label for S
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(200, JSON.stringify(confCustomNameSLabel))
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(500) // this call shouldn't take place as the current repo contains its own config file
// get label will return 404 for a non-existing label
.get(baseURL + '/labels/customsmall')
.reply(404)
// create the custom label
.post(baseURL + `/labels`, (body) => {
expect(body).toStrictEqual({ name: 'customsmall', color: '5D9801' })
return true
})
.reply(201)
// addLabels and verify custom name
.post(baseURL+`/issues/${pull_number}/labels`, (body) => {
expect(body).toStrictEqual({"labels": ["customsmall"]})
return true;
})
.reply(200)

// Simulates delivery of an issues.opened webhook
await probot.receive({
name: 'pull_request.opened',
payload: prOpenedPayload
})

// verify the .github repo was not accessed for fetching the configuration file
expect(nock.activeMocks())
.toEqual(expect.arrayContaining(
[`GET https://api.github.com:443${baseUrlDotGitHub}/contents/.github%2Flabels.yml`]))
})

test('verify merge of default missing labels using configuration from the .github repo', async () => {
nock("https://api.github.com")
// listFiles
.get(baseURL + `/pulls/${pull_number}/files`)
.reply(200, mockListFiles)
// use configuraion with only the M label set in .github repo
.get(baseURL + '/contents/.github%2Flabels.yml')
.reply(404) // no label.yml config found in the current repo
.get(baseUrlDotGitHub + `/contents/.github%2Flabels.yml`)
.reply(200, JSON.stringify(confOnlyMLabel))
// get label will return the mocked label
.get(baseURL + `/labels/${label.small}`)
.reply(200, mockLabel)
// addLabels and verify S label name is the default one
.post(baseURL + `/issues/${pull_number}/labels`, (body) => {
expect(body).toStrictEqual({"labels": ["size/S"]})
return true;
})
.reply(200)

// Simulates delivery of an issues.opened webhook
await probot.receive({
name: 'pull_request.opened',
payload: prOpenedPayload
})

// verify all stubs were called
expect(nock.isDone()).toBeTruthy()
})

afterEach(() => {
nock.cleanAll();
nock.enableNetConnect();
Expand Down