Merge pull request #462 from cla-assistant/Corporate-CLA
Corporate CLA (membership check) functionality
This commit is contained in:
Коммит
c7e3d7a568
|
@ -33,12 +33,13 @@ class ClaService {
|
|||
return github.call(args)
|
||||
}
|
||||
|
||||
async _checkAll(users, repoId, orgId, sharedGist, gist_url, gist_version, onDates) {
|
||||
async _checkAll(users, repoId, orgId, sharedGist, gist_url, gist_version, onDates, hasExternalCommiter) {
|
||||
let promises = []
|
||||
const userMap = {
|
||||
signed: [],
|
||||
not_signed: [],
|
||||
unknown: []
|
||||
unknown: [],
|
||||
hasExternalCommiter
|
||||
}
|
||||
if (!users) {
|
||||
throw new Error(`There are no users to check :( users: ${users}, repoId: ${repoId}, orgId: ${orgId}, sharedGist: ${sharedGist}, gist_url: ${gist_url}, gist_version: ${gist_version}, onDates: ${onDates}`)
|
||||
|
@ -93,10 +94,16 @@ class ClaService {
|
|||
}
|
||||
onDates.forEach(date => {
|
||||
dateConditions = dateConditions.concat([{
|
||||
created_at: { $lte: date },
|
||||
end_at: { $gt: date }
|
||||
created_at: {
|
||||
$lte: date
|
||||
},
|
||||
end_at: {
|
||||
$gt: date
|
||||
}
|
||||
}, {
|
||||
created_at: { $lte: date },
|
||||
created_at: {
|
||||
$lte: date
|
||||
},
|
||||
end_at: undefined
|
||||
}])
|
||||
})
|
||||
|
@ -108,7 +115,9 @@ class ClaService {
|
|||
const queries = [query]
|
||||
if (query.userId) {
|
||||
const queryForOldCLAs = _.clone(query)
|
||||
queryForOldCLAs.userId = { $exists: false }
|
||||
queryForOldCLAs.userId = {
|
||||
$exists: false
|
||||
}
|
||||
queries.push(queryForOldCLAs)
|
||||
delete query.user
|
||||
}
|
||||
|
@ -144,6 +153,31 @@ class ClaService {
|
|||
})
|
||||
}
|
||||
|
||||
async _getGHOrgMembers(org) {
|
||||
try {
|
||||
const response = await github.call({
|
||||
obj: 'orgs',
|
||||
fun: 'listMembers',
|
||||
arg: {
|
||||
org: org
|
||||
}
|
||||
})
|
||||
const orgMembers = []
|
||||
response.data.map((orgMember) => {
|
||||
orgMembers.push({
|
||||
name: orgMember.login,
|
||||
id: orgMember.id
|
||||
})
|
||||
})
|
||||
|
||||
return orgMembers
|
||||
|
||||
} catch (error) {
|
||||
logger.error(new Error(error).stack)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// let getOrg = function (args, done) {
|
||||
// let deferred = q.defer()
|
||||
// orgService.get(args, function (err, org) {
|
||||
|
@ -178,7 +212,9 @@ class ClaService {
|
|||
token = token || config.server.github.token
|
||||
|
||||
if (owner && !repo) {
|
||||
return await orgService.get({ org: owner })
|
||||
return await orgService.get({
|
||||
org: owner
|
||||
})
|
||||
}
|
||||
|
||||
const ghRepo = await repoService.getGHRepo({
|
||||
|
@ -187,13 +223,17 @@ class ClaService {
|
|||
token: token
|
||||
})
|
||||
try {
|
||||
const linkedRepo = await repoService.get({ repoId: ghRepo.id })
|
||||
const linkedRepo = await repoService.get({
|
||||
repoId: ghRepo.id
|
||||
})
|
||||
if (linkedRepo) {
|
||||
return linkedRepo
|
||||
}
|
||||
throw 'There is no linked repo'
|
||||
} catch (error) {
|
||||
const linkedOrg = await orgService.get({ orgId: ghRepo.owner.id })
|
||||
const linkedOrg = await orgService.get({
|
||||
orgId: ghRepo.owner.id
|
||||
})
|
||||
if (linkedOrg) {
|
||||
return linkedOrg
|
||||
}
|
||||
|
@ -316,7 +356,9 @@ class ClaService {
|
|||
*/
|
||||
async checkUserSignature(args) {
|
||||
const cla = await this.getLastSignature(args)
|
||||
return { signed: !!cla }
|
||||
return {
|
||||
signed: !!cla
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -333,6 +375,9 @@ class ClaService {
|
|||
const organizationOverrideEnabled = config.server.feature_flag.organization_override_enabled
|
||||
const item = await this._getLinkedItem(args.repo, args.owner, args.token)
|
||||
let signees = []
|
||||
var hasExternalCommiter = {
|
||||
check: false
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
throw new Error('No linked item found')
|
||||
|
@ -344,7 +389,9 @@ class ClaService {
|
|||
args.onDates = [new Date()]
|
||||
|
||||
if (!args.gist) {
|
||||
return ({ signed: true })
|
||||
return ({
|
||||
signed: true
|
||||
})
|
||||
}
|
||||
|
||||
const gist = await this._getGistObject(args.gist, item.token)
|
||||
|
@ -359,23 +406,62 @@ class ClaService {
|
|||
}
|
||||
args.onDates.push(new Date(pullRequest.created_at))
|
||||
|
||||
const isOrgHead = pullRequest.head.repo.owner.type === 'Organization'
|
||||
if (organizationOverrideEnabled && isOrgHead) {
|
||||
const { owner: headOrg } = pullRequest.head.repo
|
||||
if (item.isUserWhitelisted !== undefined && item.isUserWhitelisted(headOrg.login)) {
|
||||
return ({ signed: true })
|
||||
}
|
||||
const { signed, userMap } = await this._checkAll(
|
||||
[{ name: headOrg.login, id: headOrg.id }],
|
||||
item.repoId,
|
||||
item.orgId,
|
||||
item.sharedGist,
|
||||
item.gist,
|
||||
args.gist_version,
|
||||
args.onDates
|
||||
)
|
||||
if (signed && userMap.signed.includes(headOrg.login)) {
|
||||
return ({ signed, userMap })
|
||||
if (pullRequest.head && pullRequest.head.repo && pullRequest.head.repo.owner) {
|
||||
const isOrgHead = pullRequest.head.repo.owner.type === 'Organization'
|
||||
if (organizationOverrideEnabled && isOrgHead) {
|
||||
const {
|
||||
owner: headOrg
|
||||
} = pullRequest.head.repo
|
||||
if (item.isUserWhitelisted !== undefined && item.isUserWhitelisted(headOrg.login)) {
|
||||
const orgMembers = await this._getGHOrgMembers(headOrg.login)
|
||||
const committers = await repoService.getPRCommitters(args)
|
||||
var externalCommitters = _.differenceBy(committers, orgMembers, 'id')
|
||||
if (!externalCommitters || externalCommitters.length === 0) {
|
||||
return ({
|
||||
signed: true
|
||||
})
|
||||
|
||||
} else if (externalCommitters.length > 0) {
|
||||
externalCommitters = externalCommitters.filter(externalCommitter =>
|
||||
externalCommitter && !(item.isUserWhitelisted !== undefined && item.isUserWhitelisted(externalCommitter.name))
|
||||
)
|
||||
hasExternalCommiter.check = true
|
||||
hasExternalCommiter.orgName = headOrg.login
|
||||
return this._checkAll(
|
||||
externalCommitters,
|
||||
item.repoId,
|
||||
item.orgId,
|
||||
item.sharedGist,
|
||||
item.gist,
|
||||
args.gist_version,
|
||||
args.onDates,
|
||||
hasExternalCommiter
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
const {
|
||||
signed,
|
||||
userMap
|
||||
} = await this._checkAll(
|
||||
[{
|
||||
name: headOrg.login,
|
||||
id: headOrg.id
|
||||
}],
|
||||
item.repoId,
|
||||
item.orgId,
|
||||
item.sharedGist,
|
||||
item.gist,
|
||||
args.gist_version,
|
||||
args.onDates,
|
||||
hasExternalCommiter
|
||||
)
|
||||
if (signed && userMap.signed.includes(headOrg.login)) {
|
||||
return ({
|
||||
signed,
|
||||
userMap
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,7 +488,8 @@ class ClaService {
|
|||
item.sharedGist,
|
||||
item.gist,
|
||||
args.gist_version,
|
||||
args.onDates
|
||||
args.onDates,
|
||||
hasExternalCommiter.check
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -469,7 +556,11 @@ class ClaService {
|
|||
'created_at': '*',
|
||||
'gist_url': '*',
|
||||
'gist_version': '*'
|
||||
}, { sort: { 'created_at': -1 } })
|
||||
}, {
|
||||
sort: {
|
||||
'created_at': -1
|
||||
}
|
||||
})
|
||||
|
||||
clas.forEach((cla) => {
|
||||
if (repoList.indexOf(cla.repo) < 0) {
|
||||
|
@ -494,12 +585,16 @@ class ClaService {
|
|||
const repoList = []
|
||||
const uniqueClaList = []
|
||||
try {
|
||||
await findCla({ $or: selector }, repoList, uniqueClaList)
|
||||
await findCla({
|
||||
$or: selector
|
||||
}, repoList, uniqueClaList)
|
||||
} catch (error) {
|
||||
logger.warn(new Error(error).stack)
|
||||
}
|
||||
try {
|
||||
await findCla({ user: args.user }, repoList, uniqueClaList)
|
||||
await findCla({
|
||||
user: args.user
|
||||
}, repoList, uniqueClaList)
|
||||
} catch (error) {
|
||||
logger.warn(new Error(error).stack)
|
||||
}
|
||||
|
@ -620,4 +715,4 @@ class ClaService {
|
|||
}
|
||||
|
||||
|
||||
module.exports = new ClaService()
|
||||
module.exports = new ClaService()
|
|
@ -4,7 +4,7 @@ const logger = require('../services/logger')
|
|||
|
||||
const commentText = (signed, badgeUrl, claUrl, userMap, recheckUrl) => {
|
||||
if (signed) {
|
||||
return '[![CLA assistant check](' + badgeUrl + ')](' + claUrl + ') <br/>All committers have signed the CLA.'
|
||||
return `[![CLA assistant check](${badgeUrl})](${claUrl}) <br/>All committers have signed the CLA.`
|
||||
}
|
||||
|
||||
let committersCount = 1
|
||||
|
@ -13,7 +13,7 @@ const commentText = (signed, badgeUrl, claUrl, userMap, recheckUrl) => {
|
|||
}
|
||||
|
||||
let youAll = (committersCount > 1 ? 'you all' : 'you')
|
||||
let text = '[![CLA assistant check](' + badgeUrl + ')](' + claUrl + ') <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that ' + youAll + ' sign our [Contributor License Agreement](' + claUrl + ') before we can accept your contribution.<br/>'
|
||||
let text = `[![CLA assistant check](${badgeUrl})](${claUrl}) <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that ${youAll} sign our [Contributor License Agreement](${claUrl}) before we can accept your contribution.<br/>`
|
||||
if (committersCount > 1) {
|
||||
text += '**' + userMap.signed.length + '** out of **' + (userMap.signed.length + userMap.not_signed.length) + '** committers have signed the CLA.<br/>'
|
||||
userMap.signed.forEach(function (signee) {
|
||||
|
@ -25,16 +25,19 @@ const commentText = (signed, badgeUrl, claUrl, userMap, recheckUrl) => {
|
|||
text += '<br/>'
|
||||
}
|
||||
|
||||
if (userMap && userMap.hasExternalCommiter && userMap.hasExternalCommiter.check == true) {
|
||||
text += ` <br/> **Note:** In case you are already a member of **${userMap.hasExternalCommiter.orgName}**, there is no need to sign the CLA again because **${userMap.hasExternalCommiter.orgName}** has already signed the (Corporate) CLA, hence just make sure that your membership is public. If you are not a member of **${userMap.hasExternalCommiter.orgName}** then you need to accept our CLA. <br/>`
|
||||
}
|
||||
|
||||
if (userMap && userMap.unknown && userMap.unknown.length > 0) {
|
||||
let seem = (userMap.unknown.length > 1 ? 'seem' : 'seems')
|
||||
text += '<hr/>**' + userMap.unknown.join(', ') + '** ' + seem + ' not to be a GitHub user.'
|
||||
text += `<hr/>**${userMap.unknown.join(', ')}** ${seem} not to be a GitHub user.`
|
||||
text += ' You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please [add the email address used for this commit to your account](https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/#commits-are-not-linked-to-any-user).<br/>'
|
||||
}
|
||||
text += '<sub>You have signed the CLA already but the status is still pending? Let us [recheck](' + recheckUrl + ') it.</sub>'
|
||||
text += `<sub>You have signed the CLA already but the status is still pending? Let us [recheck](${recheckUrl}) it.</sub>`
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
class PullRequestService {
|
||||
async badgeComment(owner, repo, pullNumber, signed, userMap) {
|
||||
let badgeUrl = url.pullRequestBadge(signed)
|
||||
|
|
|
@ -83,13 +83,17 @@ const stub = () => {
|
|||
|
||||
sinon.stub(github, 'call').callsFake(async (args) => {
|
||||
if (args.obj === 'pulls' && args.fun === 'get') {
|
||||
if (testErr.getPR) { throw testErr.getPR }
|
||||
if (testErr.getPR) {
|
||||
throw testErr.getPR
|
||||
}
|
||||
return testRes.getPR
|
||||
} else if (args.obj === 'gists' && args.fun === 'get') {
|
||||
if (testErr.gistData) {
|
||||
throw testErr.gistData
|
||||
}
|
||||
return testRes.gistData
|
||||
} else if (args.obj === 'orgs' && args.fun === 'listMembers') {
|
||||
return testRes.getOrgMembers
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -145,33 +149,49 @@ describe('cla:getLastSignature', () => {
|
|||
gist_version: 'xyz',
|
||||
repoId: 123,
|
||||
org_cla: false,
|
||||
created_at: { $lte: now },
|
||||
end_at: { $gt: now }
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: {
|
||||
$gt: now
|
||||
}
|
||||
}, {
|
||||
userId: 'userId',
|
||||
gist_url: 'url/gistId',
|
||||
gist_version: 'xyz',
|
||||
repoId: 123,
|
||||
org_cla: false,
|
||||
created_at: { $lte: now },
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: undefined
|
||||
}, {
|
||||
user: 'user',
|
||||
userId: { $exists: false },
|
||||
userId: {
|
||||
$exists: false
|
||||
},
|
||||
gist_url: 'url/gistId',
|
||||
gist_version: 'xyz',
|
||||
repoId: 123,
|
||||
org_cla: false,
|
||||
created_at: { $lte: now },
|
||||
end_at: { $gt: now }
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: {
|
||||
$gt: now
|
||||
}
|
||||
}, {
|
||||
user: 'user',
|
||||
userId: { $exists: false },
|
||||
userId: {
|
||||
$exists: false
|
||||
},
|
||||
gist_url: 'url/gistId',
|
||||
gist_version: 'xyz',
|
||||
repoId: 123,
|
||||
org_cla: false,
|
||||
created_at: { $lte: now },
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: undefined
|
||||
}, {
|
||||
userId: 'userId',
|
||||
|
@ -179,15 +199,21 @@ describe('cla:getLastSignature', () => {
|
|||
gist_version: 'xyz',
|
||||
owner: undefined,
|
||||
repo: undefined,
|
||||
created_at: { $lte: now },
|
||||
end_at: { $gt: now }
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: {
|
||||
$gt: now
|
||||
}
|
||||
}, {
|
||||
userId: 'userId',
|
||||
gist_url: 'url/gistId',
|
||||
gist_version: 'xyz',
|
||||
owner: undefined,
|
||||
repo: undefined,
|
||||
created_at: { $lte: now },
|
||||
created_at: {
|
||||
$lte: now
|
||||
},
|
||||
end_at: undefined
|
||||
}]
|
||||
}), true)
|
||||
|
@ -247,7 +273,9 @@ describe('cla:getLastSignature', () => {
|
|||
gist_url: 'url/gistId',
|
||||
created_at: '2012-06-20T11:34:15Z',
|
||||
gist_version: 'xyz',
|
||||
save: async () => { throw 'Update error.' }
|
||||
save: async () => {
|
||||
throw 'Update error.'
|
||||
}
|
||||
}
|
||||
|
||||
CLA.findOne.restore()
|
||||
|
@ -300,12 +328,20 @@ describe('cla:getLastSignature', () => {
|
|||
const prCreateDateString = '1970-01-01T00:00:00.000Z'
|
||||
const prCreateDate = new Date(prCreateDateString)
|
||||
testErr.getPR = null
|
||||
testRes.getPR = { data: { created_at: prCreateDate } }
|
||||
testRes.getPR = {
|
||||
data: {
|
||||
created_at: prCreateDate
|
||||
}
|
||||
}
|
||||
CLA.findOne.restore()
|
||||
sinon.stub(CLA, 'findOne').callsFake(async (query) => {
|
||||
assert.equal(query.$or.length, 8)
|
||||
assert.deepEqual(query.$or[0].created_at, { $lte: now })
|
||||
assert.deepEqual(query.$or[2].created_at, { $lte: prCreateDate })
|
||||
assert.deepEqual(query.$or[0].created_at, {
|
||||
$lte: now
|
||||
})
|
||||
assert.deepEqual(query.$or[2].created_at, {
|
||||
$lte: prCreateDate
|
||||
})
|
||||
return testRes.claFindOne
|
||||
})
|
||||
|
||||
|
@ -426,9 +462,15 @@ describe('cla:checkPullRequestSignatures', () => {
|
|||
testRes.gistData = {
|
||||
data: {
|
||||
url: 'url',
|
||||
files: { xyFile: { content: 'some content' } },
|
||||
files: {
|
||||
xyFile: {
|
||||
content: 'some content'
|
||||
}
|
||||
},
|
||||
updated_at: '2011-06-20T11:34:15Z',
|
||||
history: [{ version: 'xyz' }]
|
||||
history: [{
|
||||
version: 'xyz'
|
||||
}]
|
||||
}
|
||||
}
|
||||
testRes.repoServiceGet = {
|
||||
|
@ -545,8 +587,7 @@ describe('cla:checkPullRequestSignatures', () => {
|
|||
try {
|
||||
await cla.checkPullRequestSignatures(args)
|
||||
assert(false, 'should have thrown error')
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
assert(error, testErr.getPR)
|
||||
}
|
||||
})
|
||||
|
@ -720,7 +761,11 @@ describe('cla:checkPullRequestSignatures', () => {
|
|||
}
|
||||
|
||||
try {
|
||||
const { userMap: { not_signed } } = await cla.checkPullRequestSignatures(args)
|
||||
const {
|
||||
userMap: {
|
||||
not_signed
|
||||
}
|
||||
} = await cla.checkPullRequestSignatures(args)
|
||||
assert.equal(not_signed.length, 0)
|
||||
} finally {
|
||||
config.server.feature_flag.required_signees = ''
|
||||
|
@ -784,9 +829,25 @@ describe('cla:checkPullRequestSignatures', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('should call callback function immediately if organization is whitelisted', async () => {
|
||||
it('should call callback function immediately if organization is whitelisted and there are no external committers ', async () => {
|
||||
config.server.feature_flag.required_signees = 'submitter committer'
|
||||
testRes.repoServiceGet.isUserWhitelisted = login => login === testRes.getPR.data.head.repo.owner.login
|
||||
testRes.repoServiceGetCommitters = [{
|
||||
name: 'login1',
|
||||
id: '123'
|
||||
}, {
|
||||
name: 'login2',
|
||||
id: '321'
|
||||
}]
|
||||
testRes.getOrgMembers = {
|
||||
data: [{
|
||||
login: 'login1',
|
||||
id: '123'
|
||||
}, {
|
||||
login: 'login2',
|
||||
id: '321'
|
||||
}]
|
||||
}
|
||||
const args = {
|
||||
repo: 'myRepo',
|
||||
owner: 'owner',
|
||||
|
@ -795,20 +856,64 @@ describe('cla:checkPullRequestSignatures', () => {
|
|||
|
||||
try {
|
||||
const result = await cla.checkPullRequestSignatures(args)
|
||||
const { signed } = result
|
||||
const {
|
||||
signed
|
||||
} = result
|
||||
assert(signed)
|
||||
sinon.assert.notCalled(CLA.findOne)
|
||||
} finally {
|
||||
config.server.feature_flag.required_signees = ''
|
||||
}
|
||||
})
|
||||
it('should check if the external committer has signed the CLA, If the organization is whitelisted ', async () => {
|
||||
config.server.feature_flag.required_signees = 'submitter committer'
|
||||
testRes.repoServiceGet.isUserWhitelisted = login => login === testRes.getPR.data.head.repo.owner.login
|
||||
testRes.repoServiceGetCommitters = [{
|
||||
name: 'login1',
|
||||
id: '123'
|
||||
}, {
|
||||
name: 'externallogin',
|
||||
id: '555'
|
||||
}, {
|
||||
name: 'login2',
|
||||
id: '321'
|
||||
}]
|
||||
testRes.getOrgMembers = {
|
||||
data: [{
|
||||
login: 'login1',
|
||||
id: '123'
|
||||
}, {
|
||||
login: 'login2',
|
||||
id: '321'
|
||||
}]
|
||||
}
|
||||
const args = {
|
||||
repo: 'myRepo',
|
||||
owner: 'owner',
|
||||
number: '1'
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await cla.checkPullRequestSignatures(args)
|
||||
const {
|
||||
signed
|
||||
} = result
|
||||
assert(signed)
|
||||
sinon.assert.called(CLA.findOne)
|
||||
} finally {
|
||||
config.server.feature_flag.required_signees = ''
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('cla.check', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub(cla, 'checkUserSignature')
|
||||
sinon.stub(cla, 'checkPullRequestSignatures').resolves({ signed: true, userMap: {} })
|
||||
sinon.stub(cla, 'checkPullRequestSignatures').resolves({
|
||||
signed: true,
|
||||
userMap: {}
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -893,9 +998,15 @@ describe('cla:sign', () => {
|
|||
testRes.gistData = {
|
||||
data: {
|
||||
url: 'url',
|
||||
files: { xyFile: { content: 'some content' } },
|
||||
files: {
|
||||
xyFile: {
|
||||
content: 'some content'
|
||||
}
|
||||
},
|
||||
updated_at: '2011-06-20T11:34:15Z',
|
||||
history: [{ version: 'xyz' }]
|
||||
history: [{
|
||||
version: 'xyz'
|
||||
}]
|
||||
}
|
||||
}
|
||||
testErr.orgServiceGet = null
|
||||
|
@ -1322,7 +1433,9 @@ describe('cla:getGist', () => {
|
|||
beforeEach(() => {
|
||||
sinon.stub(github, 'call').callsFake(async (args) => {
|
||||
assert.equal(args.arg.gist_id, 'gistId')
|
||||
return { data: {} }
|
||||
return {
|
||||
data: {}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1366,7 +1479,7 @@ describe('cla:getLinkedItem', () => {
|
|||
testRes.repoServiceGet = {
|
||||
repoId: '1',
|
||||
repo: 'Hello-World',
|
||||
owner: 'octocat',
|
||||
owner: 'login0',
|
||||
gist: 'url/gistId',
|
||||
token: 'abc',
|
||||
isUserWhitelisted: function () {
|
||||
|
@ -1375,7 +1488,7 @@ describe('cla:getLinkedItem', () => {
|
|||
}
|
||||
testRes.orgServiceGet = {
|
||||
orgId: '1',
|
||||
org: 'octocat',
|
||||
org: 'login0',
|
||||
gist: 'url/gistId',
|
||||
token: 'abc'
|
||||
}
|
||||
|
@ -1408,7 +1521,7 @@ describe('cla:getLinkedItem', () => {
|
|||
|
||||
const args = {
|
||||
repo: 'Hello-World',
|
||||
owner: 'octocat'
|
||||
owner: 'login0'
|
||||
}
|
||||
|
||||
await cla.getLinkedItem(args)
|
||||
|
@ -1433,7 +1546,7 @@ describe('cla:getLinkedItem', () => {
|
|||
it('should return linked repo even corresponding org is also linked', async () => {
|
||||
const args = {
|
||||
repo: 'Hello-World',
|
||||
owner: 'octocat',
|
||||
owner: 'login0',
|
||||
token: 'test_token'
|
||||
}
|
||||
|
||||
|
@ -1447,7 +1560,7 @@ describe('cla:getLinkedItem', () => {
|
|||
it('should return linked org when repo is not linked', async () => {
|
||||
const args = {
|
||||
repo: 'Hello-World',
|
||||
owner: 'octocat',
|
||||
owner: 'login0',
|
||||
token: 'test_token'
|
||||
}
|
||||
testRes.repoServiceGet = null
|
||||
|
@ -1461,7 +1574,7 @@ describe('cla:getLinkedItem', () => {
|
|||
|
||||
it('should only check linked org if repo name is not provided', async () => {
|
||||
const args = {
|
||||
owner: 'octocat'
|
||||
owner: 'login0'
|
||||
}
|
||||
|
||||
await cla.getLinkedItem(args)
|
||||
|
@ -1585,14 +1698,20 @@ describe('cla:isClaRequired', () => {
|
|||
|
||||
it('should require a CLA when pull request exceed minimum file changes', async () => {
|
||||
testRes.repoServiceGet.minFileChanges = 2
|
||||
testRes.getPR = { data: { changed_files: 2 } }
|
||||
testRes.getPR = {
|
||||
data: {
|
||||
changed_files: 2
|
||||
}
|
||||
}
|
||||
|
||||
const claIsRequired = await cla.isClaRequired(args)
|
||||
|
||||
sinon.assert.calledWithMatch(github.call, {
|
||||
obj: 'pulls',
|
||||
fun: 'get',
|
||||
arg: { noCache: true }
|
||||
arg: {
|
||||
noCache: true
|
||||
}
|
||||
})
|
||||
assert(claIsRequired)
|
||||
})
|
||||
|
@ -1611,7 +1730,9 @@ describe('cla:isClaRequired', () => {
|
|||
sinon.assert.calledWithMatch(github.call, {
|
||||
obj: 'pulls',
|
||||
fun: 'get',
|
||||
arg: { noCache: true }
|
||||
arg: {
|
||||
noCache: true
|
||||
}
|
||||
})
|
||||
assert(claIsRequired)
|
||||
})
|
||||
|
@ -1654,7 +1775,9 @@ describe('cla:isClaRequired', () => {
|
|||
|
||||
const claIsRequired = await cla.isClaRequired(args)
|
||||
|
||||
sinon.assert.calledWithMatch(github.call, { token: 'abc' })
|
||||
sinon.assert.calledWithMatch(github.call, {
|
||||
token: 'abc'
|
||||
})
|
||||
assert(claIsRequired)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -191,7 +191,11 @@ describe('pullRequest:badgeComment', () => {
|
|||
}
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1)
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, undefined, {
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
||||
|
@ -204,7 +208,11 @@ describe('pullRequest:badgeComment', () => {
|
|||
return 'githubRes'
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1)
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, undefined, {
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
||||
|
@ -220,7 +228,51 @@ describe('pullRequest:badgeComment', () => {
|
|||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user1'],
|
||||
unknown: ['user1']
|
||||
unknown: ['user1'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
it('should add 2 notes to the comment if there is a external committer (corporate CLA) and he/she is not a GitHub User ', async () => {
|
||||
direct_call_data = testDataComments_withCLAComment
|
||||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'updateComment')
|
||||
assert.equal(args.basicAuth.user, 'cla-assistant')
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') >= 0)
|
||||
assert(args.arg.body.indexOf('If you have already a GitHub account, please [add the email address used for this commit to your account]') >= 0)
|
||||
return 'githubRes'
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user1'],
|
||||
unknown: ['user1'],
|
||||
hasExternalCommiter: {
|
||||
check: true
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
||||
it('should add anly one note (not a Github user) to the comment if there is no external committer (corporate CLA)', async () => {
|
||||
direct_call_data = testDataComments_withCLAComment
|
||||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'updateComment')
|
||||
assert.equal(args.basicAuth.user, 'cla-assistant')
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') < 0)
|
||||
assert(args.arg.body.indexOf('If you have already a GitHub account, please [add the email address used for this commit to your account]') >= 0)
|
||||
return 'githubRes'
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user1'],
|
||||
unknown: ['user1'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -235,7 +287,10 @@ describe('pullRequest:badgeComment', () => {
|
|||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user1'],
|
||||
unknown: ['user1']
|
||||
unknown: ['user1'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -250,7 +305,10 @@ describe('pullRequest:badgeComment', () => {
|
|||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user1', 'user2'],
|
||||
unknown: ['user1', 'user2']
|
||||
unknown: ['user1', 'user2'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -260,6 +318,7 @@ describe('pullRequest:badgeComment', () => {
|
|||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'createComment')
|
||||
assert(args.arg.body.indexOf('sign our [Contributor License Agreement]') >= 0)
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') < 0)
|
||||
assert(args.arg.body.indexOf('**1** out of **2**') >= 0)
|
||||
assert(args.arg.body.indexOf(':white_check_mark: user1') >= 0)
|
||||
assert(args.arg.body.indexOf(':x: user2') >= 0)
|
||||
|
@ -268,7 +327,32 @@ describe('pullRequest:badgeComment', () => {
|
|||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: ['user1'],
|
||||
not_signed: ['user2']
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
||||
it('should add a note to the commment for Corporate CLA and write a list of signed and not signed external committers on create', async () => {
|
||||
direct_call_data = []
|
||||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'createComment')
|
||||
assert(args.arg.body.indexOf('sign our [Contributor License Agreement]') >= 0)
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') >= 0)
|
||||
assert(args.arg.body.indexOf('**1** out of **2**') >= 0)
|
||||
assert(args.arg.body.indexOf(':white_check_mark: user1') >= 0)
|
||||
assert(args.arg.body.indexOf(':x: user2') >= 0)
|
||||
return 'githubRes'
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: ['user1'],
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: true
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -278,6 +362,7 @@ describe('pullRequest:badgeComment', () => {
|
|||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'createComment')
|
||||
assert(args.arg.body.indexOf('sign our [Contributor License Agreement]') >= 0)
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') < 0)
|
||||
assert(args.arg.body.indexOf('**0** out of **1**') < 0)
|
||||
assert(args.arg.body.indexOf(':x: user2') < 0)
|
||||
return 'githubRes'
|
||||
|
@ -285,7 +370,31 @@ describe('pullRequest:badgeComment', () => {
|
|||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user2']
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
||||
it('should add a note for Corporate CLA and should NOT write a list of signed and not signed users on create if there is only one external committer ', async () => {
|
||||
direct_call_data = []
|
||||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'createComment')
|
||||
assert(args.arg.body.indexOf('sign our [Contributor License Agreement]') >= 0)
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') >= 0)
|
||||
assert(args.arg.body.indexOf('**0** out of **1**') < 0)
|
||||
assert(args.arg.body.indexOf(':x: user2') < 0)
|
||||
return 'githubRes'
|
||||
}
|
||||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: [],
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: true
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -295,6 +404,7 @@ describe('pullRequest:badgeComment', () => {
|
|||
assertionFunction = async (args) => {
|
||||
assert.equal(args.fun, 'updateComment')
|
||||
assert(args.arg.body.indexOf('sign our [Contributor License Agreement]') >= 0)
|
||||
assert(args.arg.body.indexOf('In case you are already a member of') < 0)
|
||||
assert(args.arg.body.indexOf('**1** out of **2**') >= 0)
|
||||
assert(args.arg.body.indexOf(':white_check_mark: user1') >= 0)
|
||||
assert(args.arg.body.indexOf(':x: user2') >= 0)
|
||||
|
@ -303,7 +413,10 @@ describe('pullRequest:badgeComment', () => {
|
|||
|
||||
await pullRequest.badgeComment('login', 'myRepo', 1, false, {
|
||||
signed: ['user1'],
|
||||
not_signed: ['user2']
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
})
|
||||
assert(!logger.warn.called)
|
||||
})
|
||||
|
@ -403,7 +516,13 @@ describe('pullRequest:editComment', () => {
|
|||
const args = {
|
||||
repo: 'myRepo',
|
||||
owner: 'owner',
|
||||
number: 1
|
||||
number: 1,
|
||||
userMap: {
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
await pullRequest.editComment(args)
|
||||
|
@ -419,7 +538,10 @@ describe('pullRequest:editComment', () => {
|
|||
signed: false,
|
||||
userMap: {
|
||||
signed: ['user1'],
|
||||
not_signed: ['user2']
|
||||
not_signed: ['user2'],
|
||||
hasExternalCommiter: {
|
||||
check: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче