Skip to content

Commit

Permalink
feat: add create deploy to new release
Browse files Browse the repository at this point in the history
Fix set repository url of commits
  • Loading branch information
lgaticaq committed Feb 5, 2020
1 parent 5644ffa commit 1211e9d
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: coverage
run: |
npm i -g coveralls
npx nyc check-coverage --lines 100 --per-file
npx nyc check-coverage
npx nyc report > lcov.info
coveralls < lcov.info
env:
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
| Step | Description |
|--------------------|---------------------------------------------------------------------------------------------|
| `verifyConditions` | Verify the presence of the `CUSTOM_ENV` environment variable. |
| `publish` | Deploy app. |
| `verifyConditions` | Verify the presence of the `SENTRY_AUTH_TOKEN` `SENTRY_ORG` and `SENTRY_PROJECT` environment variable. |
| `publish` | Create release and deploy in sentry project. |

## Install

Expand Down Expand Up @@ -47,12 +47,18 @@ The plugin can be configured in the [**semantic-release** configuration file](ht
| `SENTRY_AUTH_TOKEN` | Sentry token created in [profile](https://docs.sentry.io/api/auth/#id1) |
| `SENTRY_ORG` | Sentry orgnazitaion name |
| `SENTRY_PROJECT` | Sentry project name |
| `DEPLOY_START` | Sentry deploy start timestamp. Optional for deploy |
| `DEPLOY_END` | Sentry deploy end timestamp. Optional for deploy |

### Options

| Variable | Description |
| --------- | ----------------------------------------------------------------- |
| `repositoryUrl` | A valid url for add link to commits of new release. Optional. Ex: https://github.com/owner/repo |
| `tagsUrl` | A valid url for add link to new release. Optional. Ex: https://github.com/owner/repo/releases/tag/vx.y.z |
| `environment` | Sentry environment. Optional for deploy. Default production |
| `deployName` | Deploy name. Optional for deploy |
| `deployUrl` | Deploy url. Optional for deploy |

### Examples

Expand All @@ -66,6 +72,7 @@ The plugin can be configured in the [**semantic-release** configuration file](ht
[
"@eclass/semantic-release-sentry-releases",
{
"repositoryUrl": "https://github.com/owner/repo",
"tagsUrl": "https://github.com/owner/repo/releases/tag/"
}
]
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

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

13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"description": "semantic-release plugin to create releases in sentry",
"main": "src/index.js",
"scripts": {
"lint": "eslint . --fix",
"format": "prettier-standard '{src,test}/**/*.js'",
"lint": "prettier-standard --lint '{src,test}/**/*.js'",
"ts-compile-check": "tsc -p tsconfig.json --noEmit",
"test": "nyc mocha test"
},
"engines": {
Expand Down Expand Up @@ -59,7 +59,8 @@
"nyc": "15.0.0",
"nyc-config-common": "1.0.1",
"prettier-standard": "16.1.0",
"semantic-release": "17.0.2"
"semantic-release": "17.0.2",
"typescript": "3.7.5"
},
"peerDependencies": {
"semantic-release": ">=11.0.0 <18.0.0"
Expand Down Expand Up @@ -99,9 +100,9 @@
},
"nyc": {
"extends": "nyc-config-common",
"branches": 100,
"lines": 100,
"branches": 70,
"lines": 80,
"functions": 100,
"statements": 100
"statements": 80
}
}
2 changes: 1 addition & 1 deletion src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const [homepage] = pkg.homepage.split('#')
const linkify = file => `${homepage}/blob/master/${file}`

/**
* @typedef {import('semantic-release').Context} Context
* @typedef {import('./types').Context} Context
*/
/**
* @typedef {Object} SemanticReleaseError
Expand Down
2 changes: 1 addition & 1 deletion src/get-error.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const SemanticReleaseError = require('@semantic-release/error')
const ERROR_DEFINITIONS = require('./errors')

/** @typedef {import('semantic-release').Context} Context */
/** @typedef {import('./types').Context} Context */
/**
* @param {string} code -
* @param {Context} ctx -
Expand Down
65 changes: 49 additions & 16 deletions src/publish.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,77 @@
const getError = require('./get-error')
const { createRelease } = require('./request')
// @ts-ignore
const pkg = require('../package.json')
const { createRelease, createDeploy } = require('./request')

/**
* @typedef {import('./types').Context} Context
* @typedef {import('./types').Config} Config
* @typedef {import('semantic-release').Commit} Commit
* @typedef {import('./request').SentryReleaseParams} SentryReleaseParams
* @typedef {import('./request').SentryDeployParams} SentryDeployParams
* @typedef {import('./request').SentryReleaseSuccessResponse} SentryReleaseSuccessResponse
* @typedef {import('./request').SentryDeploySuccessResponse} SentryDeploySuccessResponse
*/
/**
* @typedef {Object} PublishResult
* @property {SentryReleaseSuccessResponse} release
* @property {SentryDeploySuccessResponse} deploy
*/
/**
* @param {Config} pluginConfig -
* @param {Context} ctx -
* @returns {Promise<SentryReleaseSuccessResponse>} -
* @returns {Promise<PublishResult>} -
* @example
* publish(pluginConfig, ctx)
*/
module.exports = async (pluginConfig, ctx) => {
try {
const url = pluginConfig.tagsUrl || ''
/** @type {SentryReleaseParams} */
const data = {
commits: ctx.commits.map(commit => ({
id: commit.hash,
repository: pkg.repository.url,
message: commit.message,
author_name: commit.author.name,
author_email: commit.author.email,
timestamp: commit.committerDate
})),
const releaseDate = {
commits: ctx.commits.map(commit => {
const newCommit = {
id: commit.hash,
message: commit.message,
author_name: commit.author.name,
author_email: commit.author.email,
timestamp: commit.committerDate
}
if (pluginConfig.repositoryUrl) {
newCommit.repository = pluginConfig.repositoryUrl
}
return newCommit
}),
version: ctx.nextRelease.version,
projects: [ctx.env.SENTRY_PROJECT]
}
if (url !== '') data.url = url
return await createRelease(
data,
if (url !== '') releaseDate.url = url
const release = await createRelease(
releaseDate,
ctx.env.SENTRY_AUTH_TOKEN,
ctx.env.SENTRY_ORG
)
/** @type {SentryDeployParams} */
const deployData = {
environment: pluginConfig.environment || 'production'
}
if (pluginConfig.deployName) {
deployData.name = pluginConfig.deployName
}
if (pluginConfig.deployUrl) {
deployData.name = pluginConfig.deployUrl
}
if (ctx.env.DEPLOY_START) {
deployData.dateStarted = ctx.env.DEPLOY_START
}
if (ctx.env.DEPLOY_END) {
deployData.dateStarted = ctx.env.DEPLOY_END
}
const deploy = await createDeploy(
deployData,
ctx.env.SENTRY_AUTH_TOKEN,
ctx.env.SENTRY_ORG,
ctx.nextRelease.version
)
return { release, deploy }
} catch (err) {
throw getError('ESENTRYDEPLOY', ctx)
}
Expand Down
69 changes: 58 additions & 11 deletions src/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,28 @@ const TYPES = {
* @property {string} [url] -
* @property {string} version -
*/
/**
* @typedef {Object} SentryDeploySuccessResponse
* @property {string} id -
* @property {string} name -
* @property {string} url -
* @property {string} environment -
* @property {string} dateStarted -
* @property {string} dateFinished -
*/
/**
* @typedef {Object} SentryReleasePatchSet
* @property {string} path -
* @property {PatchSetType} type -
*/
/**
* @typedef {Object} SentryReleaseCommit
* @property {string} repository -
* @property {string} message -
* @property {string} [repository] -
* @property {string} [message] -
* @property {Array<SentryReleasePatchSet>} [patch_set] -
* @property {string} author_name -
* @property {string} [author_name] -
* @property {string} [author_email] -
* @property {string} timestamp -
* @property {string} [timestamp] -
*/
/**
* @typedef {Object} SentryReleaseParams
Expand All @@ -58,19 +67,28 @@ const TYPES = {
* @property {Array<string>} [refs] -
*/
/**
* @param {SentryReleaseParams} data -
* @typedef {Object} SentryDeployParams
* @property {string} environment -
* @property {string} [name] -
* @property {string} [url] -
* @property {string} [dateStarted] -
* @property {string} [dateFinished] -
*/

/**
* @param {string} path -
* @param {*} data -
* @param {string} token -
* @param {string} org -
* @returns {Promise<SentryReleaseSuccessResponse>} -
* @returns {Promise<*>} -
* @example
* await createRelease(data, token, org)
* await request(path, data, token)
*/
const createRelease = (data, token, org) =>
const request = (path, data, token) =>
new Promise((resolve, reject) => {
const postData = JSON.stringify(data)
const options = {
hostname: 'sentry.io',
path: `/api/0/organizations/${org}/releases/`,
path,
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
Expand Down Expand Up @@ -102,6 +120,35 @@ const createRelease = (data, token, org) =>
req.end()
})

/**
* @param {SentryReleaseParams} data -
* @param {string} token -
* @param {string} org -
* @returns {Promise<SentryReleaseSuccessResponse>} -
* @example
* await createRelease(data, token, org)
*/
const createRelease = (data, token, org) => {
return request(`/api/0/organizations/${org}/releases/`, data, token)
}

/**
* @param {SentryDeployParams} data -
* @param {string} token -
* @param {string} org -
* @param {string} version -
* @returns {Promise<SentryDeploySuccessResponse>} -
* @example
* await createDeploy(data, token, org, version)
*/
const createDeploy = (data, token, org, version) => {
return request(
`/api/0/organizations/${org}/releases/${version}/deploys/`,
data,
token
)
}

/**
* @param {string} token -
* @param {string} org -
Expand Down Expand Up @@ -130,4 +177,4 @@ const verify = (token, org) =>
req.end()
})

module.exports = { createRelease, verify }
module.exports = { createRelease, createDeploy, verify }
14 changes: 10 additions & 4 deletions src/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import SemanticRelease from 'semantic-release'
import { Context as SemanticReleaseContext } from 'semantic-release'
import { Config as SemanticReleaseConfig } from 'semantic-release'

export interface Context extends SemanticRelease.Context {
export interface Context extends SemanticReleaseContext {
commits?: SemanticRelease.Commit[]
}

export interface Config extends SemanticRelease.Config {
// Set url of repo tags. Ex: https://gitlab.com/my-org/my-repo/-/tags
export interface Config extends SemanticReleaseConfig {
// Set url of repository tags. Ex: https://gitlab.com/my-org/my-repo
repositoryUrl?: string
// Set url of repository tags. Ex: https://gitlab.com/my-org/my-repo/-/tags
tagsUrl?: string
environment?: string
deployName?: string
deployUrl?: string
}
11 changes: 10 additions & 1 deletion test/publish.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ describe('Publish', () => {
url: null,
version: '1.0.0'
})
.post('/api/0/organizations/valid/releases/1.0.0/deploys/')
.reply(201, {
name: 'amazon',
url: 'https://api.example.com/',
environment: 'production',
dateStarted: '2020-02-05T10:29:59Z',
dateFinished: '2020-02-05T10:30:43Z',
id: '5044917'
})
})

it(SERVER_ERROR_TITLE, async () => {
Expand Down Expand Up @@ -102,6 +111,6 @@ describe('Publish', () => {
ctx.env.SENTRY_PROJECT = 'project'
// @ts-ignore
const result = await publish({ tagsUrl }, ctx)
expect(result.version).to.equal('1.0.0')
expect(result.release.version).to.equal('1.0.0')
})
})
14 changes: 14 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"lib": [ "es2017", "es7" ],
"allowJs": true,
"checkJs": true,
"downlevelIteration": true,
"outDir": "build",
"skipLibCheck": true
},
"exclude": [
"node_modules",
"coverage"
]
}

0 comments on commit 1211e9d

Please sign in to comment.