Skip to content

Commit

Permalink
Merge pull request #126 from codecov/azure-provider
Browse files Browse the repository at this point in the history
feat: Azure, GitLab, Appveyor providers
  • Loading branch information
thomasrockhu authored Jun 9, 2021
2 parents aeb905b + c723ad7 commit 648a8cf
Show file tree
Hide file tree
Showing 20 changed files with 1,116 additions and 104 deletions.
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
2. Collect the needed enviromental variables for each section (you can use provider_circleci.js if you get confused)
3. Copy provider_template.js and fill it in.
4. Add your new providers list in https://github.com/codecov/uploader/blob/master/src/ci_providers/index.js
5. Open a PR and we'll take a look!
5. Copy test/providers/provider_template.test.js and fill it in.
6. Ensure 100% code coverage on the new provider code.
7. Open a PR and we'll take a look!
6 changes: 6 additions & 0 deletions src/ci_providers/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
const providerAppveyorci = require('./provider_appveyorci')
const providerAzurepipelines = require('./provider_azurepipelines')
const providerCircleci = require('./provider_circleci')
const providerGitHubactions = require('./provider_githubactions')
const providerGitLabci = require('./provider_gitlabci')
const providerJenkinsci = require('./provider_jenkinsci')
const providerLocal = require('./provider_local')
const providerTravisci = require('./provider_travisci')

// Please make sure provider_local is last
const providers = [
providerAppveyorci,
providerAzurepipelines,
providerCircleci,
providerGitHubactions,
providerGitLabci,
providerJenkinsci,
providerTravisci,
providerLocal,
Expand Down
72 changes: 72 additions & 0 deletions src/ci_providers/provider_appveyorci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
function detect (envs) {
return (envs.CI == 'true' || envs.CI == 'True') && (envs.APPVEYOR == 'true' || envs.APPVEYOR == 'True')
}

function _getBuild (inputs) {
const { args, envs } = inputs
return args.build || encodeURIComponent(envs.APPVEYOR_JOB_ID)
}

function _getBuildURL (inputs) {
const { envs } = inputs
if (envs.APPVEYOR_URL && envs.APPVEYOR_REPO_NAME && envs.APPVEYOR_BUILD_ID && envs.APPVEYOR_JOB_ID) {
return encodeURIComponent(
`${envs.APPVEYOR_URL}/project/${envs.APPVEYOR_REPO_NAME}/builds/${envs.APPVEYOR_BUILD_ID}/job/${envs.APPVEYOR_JOB_ID}`
)
}
return ''
}

function _getBranch (inputs) {
const { args, envs } = inputs
return args.branch || envs.APPVEYOR_REPO_BRANCH || ''
}

function _getJob (envs) {
if (envs.APPVEYOR_ACCOUNT_NAME && envs.APPVEYOR_PROJECT_SLUG && envs.APPVEYOR_BUILD_VERSION) {
return `${envs.APPVEYOR_ACCOUNT_NAME}%2F${envs.APPVEYOR_PROJECT_SLUG}%2F${envs.APPVEYOR_BUILD_VERSION}`
}
return ''
}

function _getPR (inputs) {
const { args, envs } = inputs
return args.pr || envs.APPVEYOR_PULL_REQUEST_NUMBER || ''
}

function _getService () {
return 'appveyor'
}

function getServiceName () {
return 'Appveyor CI'
}

function _getSHA (inputs) {
const { args, envs } = inputs
return args.sha || envs.APPVEYOR_REPO_COMMIT || ''
}

function _getSlug (inputs) {
const { args, envs } = inputs
return args.slug || envs.APPVEYOR_REPO_NAME || ''
}

function getServiceParams (inputs) {
return {
branch: _getBranch(inputs),
build: _getBuild(inputs),
buildURL: _getBuildURL(inputs),
commit: _getSHA(inputs),
job: _getJob(inputs.envs),
pr: _getPR(inputs),
service: _getService(),
slug: _getSlug(inputs)
}
}

module.exports = {
detect,
getServiceName,
getServiceParams
}
105 changes: 105 additions & 0 deletions src/ci_providers/provider_azurepipelines.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
var childProcess = require('child_process')
var { log } = require('../helpers/logger')

function detect (envs) {
return !!envs.SYSTEM_TEAMFOUNDATIONSERVERURI
}

function _getBuild (inputs) {
const { args, envs } = inputs
return args.build || envs.BUILD_BUILDNUMBER || ''
}

function _getBuildURL (inputs) {
const { args, envs } = inputs
if (envs.SYSTEM_TEAMPROJECT && envs.BUILD_BUILDID) {
return encodeURIComponent(`${envs.SYSTEM_TEAMFOUNDATIONSERVERURI}${envs.SYSTEM_TEAMPROJECT}/_build/results?buildId=${envs.BUILD_BUILDID}`)
}
return ''
}

function _getBranch (inputs) {
const { args, envs } = inputs
let branch = ''
if (envs.BUILD_SOURCEBRANCH) {
branch = envs.BUILD_SOURCEBRANCH.replace('refs/heads/', '')
}
return args.branch || branch
}

function _getJob (envs) {
return envs.BUILD_BUILDID || ''
}

function _getPR (inputs) {
const { args, envs } = inputs
return args.pr || envs.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER || envs.SYSTEM_PULLREQUEST_PULLREQUESTID || ''
}

function _getService () {
return 'azure_pipelines'
}

function getServiceName () {
return 'Azure Pipelines'
}

function _getSHA (inputs) {
const { args, envs } = inputs
let commit = envs.BUILD_SOURCEVERSION

if (_getPR(inputs)) {
const mergeCommitRegex = /^[a-z0-9]{40} [a-z0-9]{40}$/
const mergeCommitMessage = childProcess.execSync(
`git show --no-patch --format="%P"`
)
if (mergeCommitRegex.exec(mergeCommitMessage)) {
const mergeCommit = mergeCommitMessage.split(" ")[1]
log(` Fixing merge commit SHA ${commit} -> ${mergeCommit}`)
commit = mergeCommit
}
}

return args.sha || commit || ''
}

function _getProject (inputs) {
const { envs } = inputs
return envs.SYSTEM_TEAMPROJECT || ''
}

function _getServerURI (inputs) {
const { envs } = inputs
return envs.SYSTEM_TEAMFOUNDATIONSERVERURI
}

function _getSlug (inputs) {
const { args } = inputs
return args.slug || ''
}
/**
* Generates and return the serviceParams object
*
* @param {args: {}, envs: {}} inputs an object of arguments and enviromental variable key/value pairs
* @returns { branch: String, build: String, buildURL: String, commit: String, job: String, pr: String, service: String, slug: String}
*/
function getServiceParams (inputs) {
return {
branch: _getBranch(inputs),
build: _getBuild(inputs),
buildURL: _getBuildURL(inputs),
commit: _getSHA(inputs),
job: _getJob(inputs.envs),
pr: _getPR(inputs),
project: _getProject(inputs),
server_uri: _getServerURI(inputs),
service: _getService(),
slug: _getSlug(inputs)
}
}

module.exports = {
detect,
getServiceName,
getServiceParams
}
66 changes: 66 additions & 0 deletions src/ci_providers/provider_gitlabci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const { parseSlugFromRemoteAddr } = require('../helpers/git')

function detect (envs) {
return envs.GITLAB_CI
}

function _getBuild (inputs) {
const { args, envs } = inputs
return args.build || envs.CI_BUILD_ID || envs.CI_JOB_ID || ''
}

function _getBuildURL (inputs) {
return ''
}

function _getBranch (inputs) {
const { args, envs } = inputs
return args.branch || envs.CI_BUILD_REF_NAME || envs.CI_COMMIT_REF_NAME || ''
}

function _getJob (envs) {
return ''
}

function _getPR (inputs) {
const { args } = inputs
return args.pr || ''
}

function _getService () {
return 'gitlab'
}

function getServiceName () {
return 'GitLab CI'
}

function _getSHA (inputs) {
const { args, envs } = inputs
return args.sha || envs.CI_BUILD_REF || envs.CI_COMMIT_SHA || ''
}

function _getSlug (inputs) {
const { args, envs } = inputs
const remoteAddr = envs.CI_BUILD_REPO || envs.CI_REPOSITORY_URL
return args.slug || envs.CI_PROJECT_PATH || parseSlugFromRemoteAddr(remoteAddr) || ''
}

function getServiceParams (inputs) {
return {
branch: _getBranch(inputs),
build: _getBuild(inputs),
buildURL: _getBuildURL(inputs),
commit: _getSHA(inputs),
job: _getJob(inputs.envs),
pr: _getPR(inputs),
service: _getService(),
slug: _getSlug(inputs)
}
}

module.exports = {
detect,
getServiceName,
getServiceParams
}
25 changes: 4 additions & 21 deletions src/ci_providers/provider_local.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const childprocess = require('child_process')
const { parseSlug } = require('../helpers/git')

function detect (envs) {
return !envs.CI
Expand Down Expand Up @@ -36,7 +37,8 @@ function _getJob (envs) {

// eslint-disable-next-line no-unused-vars
function _getPR (inputs) {
return ''
const { args } = inputs
return args.pr || ''
}

// This is the value that gets passed to the Codecov uploader
Expand Down Expand Up @@ -64,33 +66,14 @@ function _getSHA (inputs) {
}
}

function _parseSlug (slug) {
// origin https://github.com/torvalds/linux.git (fetch)

// [email protected]: codecov / uploader.git

if (slug.match('http')) {
// Type is http(s)
const phaseOne = slug.split('//')[1].replace('.git', '')
const phaseTwo = phaseOne.split('/')
const cleanSlug = `${phaseTwo[1]}/${phaseTwo[2]}`
return cleanSlug
} else if (slug.match('@')) {
// Type is git
const cleanSlug = slug.split(':')[1].replace('.git', '')
return cleanSlug
}
throw new Error(`Unable to parse slug URL: ${slug}`)
}

function _getSlug (inputs) {
const { args } = inputs
try {
const slug = childprocess
.spawnSync('git', ['config', '--get', 'remote.origin.url'])
.stdout.toString()
.trimRight()
return args.slug || _parseSlug(slug)
return args.slug || parseSlug(slug)
} catch (error) {
throw new Error(`There was an error getting the slug from git: ${error}`)
}
Expand Down
9 changes: 8 additions & 1 deletion src/ci_providers/provider_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,14 @@ function _getJob (envs) {
*/
// eslint-disable-next-line no-unused-vars
function _getPR (inputs) {
return ''
const { args } = inputs
try {
return args.pr || ''
} catch (error) {
throw new Error(
`There was an error getting the branch name from git: ${error}`
)
}
}

/**
Expand Down
43 changes: 43 additions & 0 deletions src/helpers/git.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var childProcess = require('child_process')

function parseSlug (slug) {
// origin https://github.com/torvalds/linux.git (fetch)
// [email protected]: codecov / uploader.git
if (typeof slug != 'string') {
return ''
}

if (slug.match('http')) {
// Type is http(s)
const phaseOne = slug.split('//')[1].replace('.git', '')
const phaseTwo = phaseOne.split('/')
const cleanSlug = `${phaseTwo[1]}/${phaseTwo[2]}`
return cleanSlug
} else if (slug.match('@')) {
// Type is git
const cleanSlug = slug.split(':')[1].replace('.git', '')
return cleanSlug
}
throw new Error(`Unable to parse slug URL: ${slug}`)
}

function parseSlugFromRemoteAddr (remoteAddr) {
let slug = ""
if (!remoteAddr) {
remoteAddr = childProcess.execSync(
`git config --get remote.origin.url || hg paths default || echo ''`
)
}
if (remoteAddr) {
slug = parseSlug(remoteAddr)
}
if (slug == "/") {
slug = ""
}
return slug
}

module.exports = {
parseSlug,
parseSlugFromRemoteAddr,
}
Loading

0 comments on commit 648a8cf

Please sign in to comment.