-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jeff Jagoda
committed
Jul 6, 2018
0 parents
commit 0b66fa1
Showing
13 changed files
with
4,985 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[*] | ||
end_of_line = lf | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[*.{js,json,yml}] | ||
charset = utf-8 | ||
indent_size = 2 | ||
indent_style = space |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/.nyc_output/ | ||
/node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
language: node_js | ||
node_js: | ||
- '8' | ||
- '9' | ||
- '10' | ||
before_install: yarn global add greenkeeper-lockfile@1 | ||
before_script: greenkeeper-lockfile-update | ||
script: yarn test | ||
after_script: greenkeeper-lockfile-upload | ||
after_success: yarn coverage | ||
notifications: | ||
email: | ||
on_success: never | ||
on_failure: always | ||
deploy: | ||
provider: npm | ||
email: $NPM_EMAIL | ||
api_key: $NPM_KEY | ||
on: | ||
tags: true | ||
repo: lifeomic/bitrise | ||
node: '8' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
bitrise | ||
======= | ||
|
||
[![Build Status](https://travis-ci.org/lifeomic/bitrise.svg?branch=master)](https://travis-ci.org/lifeomic/bitrise) | ||
[![Coverage Status](https://coveralls.io/repos/github/lifeomic/bitrise/badge.svg?branch=master)](https://coveralls.io/github/lifeomic/bitrise?branch=master) | ||
|
||
A simple API client for the [Bitrise API][bitrise-api]. | ||
|
||
## Usage | ||
|
||
$ npm install --save @lifeomic/bitrise | ||
|
||
## API | ||
|
||
### bitrise({ token }) | ||
|
||
Create a new client instance. `token` is a [personal access token][bitrise-auth]. | ||
|
||
const bitrise = require('@lifeomic/bitrise'); | ||
const client = bitrise({ token: 'some-token' }); | ||
|
||
### bitrise.app({ slug }) | ||
|
||
Create an app object. `slug` is the Bitrise app slug. | ||
|
||
const bitrise = require('@lifeomic/bitrise'); | ||
const app = bitrise({ token }).app({ slug }); | ||
|
||
An app has the following attributes: | ||
|
||
- **slug** — the app's unique identifier. | ||
|
||
### async app.triggerBuild(options) | ||
|
||
Trigger a new build for the app. Supported `options` include the following: | ||
|
||
- **commitHash** — the hash of the commit to checkout of SCM. By default | ||
the `master` branch is run. | ||
- **workflow** — the ID of the Bitrise workflow to run. | ||
|
||
Returns a `build` object representing the build that was started. A build has | ||
the following attributes: | ||
|
||
- **appSlug** — the slug of the application that the build is for. | ||
- **buildSlug** — the unique ID of the build. | ||
|
||
References: | ||
- https://devcenter.bitrise.io/api/v0.1/#post-appsapp-slugbuilds | ||
|
||
### async build.describe() | ||
|
||
Get all attributes for a build. | ||
|
||
References: | ||
- https://devcenter.bitrise.io/api/v0.1/#post-appsapp-slugbuilds | ||
|
||
### async build.follow() | ||
|
||
Poll on the logs for a build and print them to stdout. An error will be thrown | ||
if the build fails. | ||
|
||
References: | ||
- https://devcenter.bitrise.io/api/v0.1/#get-appsapp-slugbuildsbuild-sluglog | ||
- https://devcenter.bitrise.io/api/v0.1/#get-appsapp-slugbuildsbuild-slug | ||
|
||
### async build.isFinished() | ||
|
||
Returns `true` if the build has completed execution (regardless of success or | ||
failure). Returns `false` otherwise. This is just a convenience method for | ||
running `build.describe()` and checking the `finished_at` attribute. | ||
|
||
References: | ||
- https://devcenter.bitrise.io/api/v0.1/#get-appsapp-slugbuildsbuild-slug | ||
|
||
[bitrise-api]: https://devcenter.bitrise.io/api/v0.1/ "Bitrise API" | ||
[bitrise-auth]: https://devcenter.bitrise.io/api/v0.1/#authentication "API Authorization" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"name": "@lifeomic/bitrise", | ||
"version": "0.0.0", | ||
"description": "Bitrise API client", | ||
"main": "src/client.js", | ||
"repository": "https://github.com/lifeomic/bitrise.git", | ||
"author": "LifeOmic <development@lifeomic.com>", | ||
"license": "MIT", | ||
"scripts": { | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
"lint": "eslint .", | ||
"pretest": "yarn lint", | ||
"test": "nyc ava -v" | ||
}, | ||
"dependencies": { | ||
"axios": "^0.18.0" | ||
}, | ||
"devDependencies": { | ||
"@lifeomic/eslint-plugin-node": "^1.1.1", | ||
"ava": "^0.25.0", | ||
"coveralls": "^3.0.2", | ||
"eslint": "^4.0.0", | ||
"lodash": "^4.17.10", | ||
"luxon": "^1.3.1", | ||
"nyc": "^12.0.2", | ||
"sinon": "^6.1.0", | ||
"uuid": "^3.3.2" | ||
}, | ||
"ava": { | ||
"failWithoutAssertions": false, | ||
"files": [ | ||
"test/**/*.test.js" | ||
] | ||
}, | ||
"eslintConfig": { | ||
"extends": "plugin:@lifeomic/node/recommended" | ||
}, | ||
"nyc": { | ||
"branches": 100, | ||
"check-coverage": true, | ||
"functions": 100, | ||
"lines": 100, | ||
"statements": 100 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const build = require('./build'); | ||
const project = require('../package.json'); | ||
|
||
const buildParameters = ({ commitHash, workflow }) => { | ||
const parameters = {}; | ||
|
||
if (commitHash) { | ||
parameters.commit_hash = commitHash; | ||
} else { | ||
parameters.branch = 'master'; | ||
} | ||
|
||
if (workflow) { | ||
parameters.workflow_id = workflow; | ||
} | ||
|
||
return parameters; | ||
}; | ||
|
||
const triggerBuild = async ({ client, slug }, options = {}) => { | ||
const buildOptions = { | ||
build_params: buildParameters(options), | ||
hook_info: { type: 'bitrise' }, | ||
triggered_by: project.name | ||
}; | ||
|
||
const response = await client.post(`/apps/${slug}/builds`, buildOptions); | ||
return build({ appSlug: slug, client, buildSlug: response.data.build_slug }); | ||
}; | ||
|
||
module.exports = ({ client, slug }) => { | ||
const app = { slug }; | ||
app.triggerBuild = triggerBuild.bind(app, { client, slug }); | ||
return app; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
const describeBuild = async ({ appSlug, buildSlug, client }) => { | ||
const response = await client.get(`/apps/${appSlug}/builds/${buildSlug}`); | ||
return response.data.data; | ||
}; | ||
|
||
const followBuild = async ({ appSlug, buildSlug, client }) => { | ||
let timestamp; | ||
|
||
do { | ||
if (timestamp) { | ||
await sleep(5000); | ||
} | ||
|
||
const parameters = timestamp ? `?timestamp=${timestamp}` : ''; | ||
const response = await client.get(`/apps/${appSlug}/builds/${buildSlug}/log${parameters}`); | ||
|
||
// If the log has already been archived then polling is no good. Just | ||
// download and print the log data. | ||
if (response.data.is_archived && !timestamp) { | ||
const archiveResponse = await client.get(response.data.expiring_raw_log_url); | ||
process.stdout.write(archiveResponse.data); | ||
break; | ||
} | ||
|
||
response.data.log_chunks.forEach(({ chunk }) => process.stdout.write(chunk)); | ||
timestamp = response.data.timestamp; | ||
} while (timestamp); | ||
|
||
const attributes = await describeBuild({ appSlug, buildSlug, client }); | ||
|
||
if (attributes.status > 1) { | ||
throw new Error(`Build ${appSlug}/${buildSlug} failed`); | ||
} | ||
}; | ||
|
||
const isFinished = async ({ appSlug, buildSlug, client }) => { | ||
const attributes = await describeBuild({ appSlug, buildSlug, client }); | ||
return !!attributes.finished_at; | ||
}; | ||
|
||
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay)); | ||
|
||
module.exports = ({ appSlug, buildSlug, client }) => { | ||
const build = { appSlug, buildSlug }; | ||
const state = { appSlug, buildSlug, client }; | ||
|
||
build.describe = describeBuild.bind(build, state); | ||
build.follow = followBuild.bind(build, state); | ||
build.isFinished = isFinished.bind(build, state); | ||
|
||
return build; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const app = require('./app'); | ||
const assert = require('assert'); | ||
const axios = require('axios'); | ||
|
||
module.exports = ({ token }) => { | ||
assert(token, 'An access token is required'); | ||
|
||
const client = axios.create({ | ||
baseURL: 'https://api.bitrise.io/v0.1', | ||
headers: { Authorization: `token ${token}` } | ||
}); | ||
|
||
const instance = {}; | ||
instance.app = ({ slug }) => app({ client, slug }); | ||
return instance; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
const app = require('../src/app'); | ||
const axios = require('axios'); | ||
const sinon = require('sinon'); | ||
const test = require('ava'); | ||
const uuid = require('uuid/v4'); | ||
|
||
const { stubTriggerBuild } = require('./stubs'); | ||
|
||
test.beforeEach((test) => { | ||
const client = axios.create(); | ||
const slug = uuid(); | ||
|
||
test.context.app = app({ client, slug }); | ||
test.context.client = client; | ||
test.context.slug = slug; | ||
}); | ||
|
||
test('an app has a slug', (test) => { | ||
const { app, slug } = test.context; | ||
test.is(app.slug, slug); | ||
}); | ||
|
||
test('an app can trigger a new build', async (test) => { | ||
const { app, client, slug } = test.context; | ||
const stub = stubTriggerBuild({ appSlug: slug, axios: client }); | ||
|
||
const build = await app.triggerBuild(); | ||
test.is(build.appSlug, slug); | ||
test.is(build.buildSlug, stub.build.build_slug); | ||
|
||
sinon.assert.calledOnce(client.post); | ||
sinon.assert.calledWithExactly( | ||
client.post, | ||
sinon.match.string, | ||
sinon.match({ | ||
build_params: { branch: 'master' }, | ||
hook_info: { type: 'bitrise' }, | ||
triggered_by: '@lifeomic/bitrise' | ||
}) | ||
); | ||
}); | ||
|
||
test('an app can trigger a build for a specific commit', async (test) => { | ||
const { app, client, slug } = test.context; | ||
const commitHash = uuid(); | ||
const stub = stubTriggerBuild({ appSlug: slug, axios: client }); | ||
|
||
const build = await app.triggerBuild({ commitHash }); | ||
test.is(build.appSlug, slug); | ||
test.is(build.buildSlug, stub.build.build_slug); | ||
|
||
sinon.assert.calledOnce(client.post); | ||
sinon.assert.calledWithExactly( | ||
client.post, | ||
sinon.match.string, | ||
sinon.match({ | ||
build_params: { commit_hash: commitHash }, | ||
hook_info: { type: 'bitrise' }, | ||
triggered_by: '@lifeomic/bitrise' | ||
}) | ||
); | ||
}); | ||
|
||
test('an app can trigger a specific build workflow', async (test) => { | ||
const { app, client, slug } = test.context; | ||
const stub = stubTriggerBuild({ appSlug: slug, axios: client }); | ||
const workflow = 'test'; | ||
|
||
const build = await app.triggerBuild({ workflow }); | ||
test.is(build.appSlug, slug); | ||
test.is(build.buildSlug, stub.build.build_slug); | ||
|
||
sinon.assert.calledOnce(client.post); | ||
sinon.assert.calledWithExactly( | ||
client.post, | ||
sinon.match.string, | ||
sinon.match({ | ||
build_params: { branch: 'master', workflow_id: workflow }, | ||
hook_info: { type: 'bitrise' }, | ||
triggered_by: '@lifeomic/bitrise' | ||
}) | ||
); | ||
}); |
Oops, something went wrong.