Skip to content

Commit

Permalink
1.1.0 (#63)
Browse files Browse the repository at this point in the history
* Add ci node-version matrix

* Prettier 2 upgrade

* Bump deps

* Bump version

* Add support for optional version prefix
  • Loading branch information
tclindner authored Apr 17, 2020
1 parent 3b3f7e3 commit b6c98a1
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 43 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- run: npm ci
Expand Down
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ Create a workflow `.yml` file in your repo's `.github/workflows` directory. An [

#### `tagName`

**Required** The name of release in Sentry.
**Required** The tag being released. This is used as the Sentry release name. You can optionally prefix it using `releaseNamePrefix`.

#### `environment`

**Required** The name of the environment the release was deployed to.

#### `releaseNamePrefix`

**Optional** String that is prefixed to the tag to form the Sentry release name.

> Please review Sentry's documentation regarding max length and supported characters in release names.
For more information on these inputs, see the [API Documentation](https://developer.github.com/v3/repos/releases/#input)

### Environment Variables
Expand Down Expand Up @@ -98,6 +104,42 @@ jobs:
environment: qa
```

Assume you tagged your release as `v1.1.0`. `github.ref` would equal `refs/tags/v1.1.0`. This action automatically strips `refs/tags/`, so the Sentry release name is `v1.1.0`.

### Example workflow with optional release prefix

On every GitHub `release` event.

```yaml
name: ReleaseWorkflow
on:
release:
types: [published, prereleased]
jobs:
createSentryRelease:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Create a Sentry.io release
uses: tclindner/sentry-releases-action@v1.0.0
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: myAwesomeOrg
SENTRY_PROJECT: myAwesomeProject
with:
tagName: ${{ github.ref }}
environment: qa
releaseNamePrefix: myAwesomeProject-
```

Scenario 1: Assume you tagged your release as `v1.1.0`. `github.ref` would equal `refs/tags/v1.1.0`. This action automatically strips `refs/tags/`, so the Sentry release name is `myAwesomeProject-v1.1.0`.

Scenario 2: Assume you tagged your release as `1.1.0` and you set `releaseNamePrefix` to `myAwesomeProject@`. `github.ref` would equal `refs/tags/1.1.0`. This action automatically strips `refs/tags/`, so the Sentry release name is `myAwesomeProject@1.1.0`.

> Note: This action only works on Linux x86_64 systems.

## Contributing
Expand Down
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ name: 'Create a Sentry.io release'
description: 'Sentry.io releases for GitHub Actions'
inputs:
tagName:
description: 'Release version name'
description: 'Tag being released'
required: true
environment:
description: 'Environment name'
required: true
releaseNamePrefix:
description: 'String to prefix tagName with. Used as the Sentry release name.'
required: false
runs:
using: 'node12'
main: 'dist/index.js'
Expand Down
6 changes: 3 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ module.exports = {
branches: 100,
functions: 100,
lines: 100,
statements: 100
}
statements: 100,
},
},
restoreMocks: true,
resetMocks: true,
resetModules: true,
testEnvironment: 'node',
testPathIgnorePatterns: ['<rootDir>/node_modules/']
testPathIgnorePatterns: ['<rootDir>/node_modules/'],
};
40 changes: 20 additions & 20 deletions package-lock.json

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

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sentry-releases-action",
"version": "1.0.0",
"version": "1.1.0",
"description": "Sentry.io releases for GitHub Actions",
"keywords": [
"actions",
Expand Down Expand Up @@ -33,19 +33,19 @@
},
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-tc": "^11.0.0",
"eslint-config-tc": "^12.1.0",
"eslint-formatter-pretty": "^3.0.1",
"eslint-plugin-eslint-comments": "^3.1.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jest": "^23.8.2",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^25.3.0",
"npm-package-json-lint": "^5.0.0",
"npm-package-json-lint-config-tc": "^3.0.0",
"prettier": "^1.19.1"
"npm-package-json-lint-config-tc": "^4.0.0",
"prettier": "^2.0.4"
},
"engines": {
"node": ">=8.0.0",
"node": ">=10.0.0",
"npm": ">=6.0.0"
},
"license": "MIT"
Expand Down
24 changes: 17 additions & 7 deletions src/create-release.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,43 @@ const run = async () => {

// Get the inputs from the workflow file: https://github.com/actions/toolkit/tree/master/packages/core#inputsoutputs
const tagName = core.getInput('tagName', {
required: true
required: true,
});
const environment = core.getInput('environment', {
required: true
required: true,
});
const releaseNamePrefix = core.getInput('releaseNamePrefix', {
required: false,
});

// This removes the 'refs/tags' portion of the string, i.e. from 'refs/tags/v1.0.0' to 'v1.0.0'
const tag = tagName.replace('refs/tags/', '');
let releaseName = tag;

if (releaseNamePrefix) {
releaseName = `${releaseNamePrefix}${tag}`;
}

core.info(`Tag is: ${tag}`);
core.info(`Sentry release is: ${releaseName}`);

// Create a release
await cli.releases.new(tag);
await cli.releases.new(releaseName);

// Set commits
await cli.releases.setCommits(tag, {
await cli.releases.setCommits(releaseName, {
repo: 'repo',
auto: true
auto: true,
});

// Create a deployment (A node.js function isn't exposed for this operation.)
const sentryCliPath = SentryCli.getPath();

core.info(`sentryCliPath: ${sentryCliPath}`);
await runCommand(sentryCliPath, ['releases', 'deploys', tag, 'new', '-e', environment]);
await runCommand(sentryCliPath, ['releases', 'deploys', releaseName, 'new', '-e', environment]);

// Finalize the release
await cli.releases.finalize(tag);
await cli.releases.finalize(releaseName);
} catch (error) {
core.setFailed(error.message);
}
Expand Down
3 changes: 2 additions & 1 deletion src/runCommand.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const {execFile} = require('child_process');

// eslint-disable-next-line require-await
const runCommand = async (filePath, args) => {
return new Promise((resolve, reject) => {
execFile(filePath, args, (error, stdout) => {
Expand All @@ -13,5 +14,5 @@ const runCommand = async (filePath, args) => {
};

module.exports = {
runCommand
runCommand,
};
60 changes: 55 additions & 5 deletions test/create-release.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jest.mock('@sentry/cli', () => jest.fn());
jest.mock('../src/runCommand');

describe('create-release', () => {
test('happy path', async () => {
test('No releaseNamePrefix', async () => {
const finalize = jest.fn().mockResolvedValue('done');
const newMock = jest.fn().mockResolvedValue('done');
const setCommits = jest.fn().mockResolvedValue('done');
Expand All @@ -20,8 +20,8 @@ describe('create-release', () => {
releases: {
finalize,
new: newMock,
setCommits
}
setCommits,
},
};
});
SentryCli.getPath = getPath;
Expand All @@ -36,7 +36,7 @@ describe('create-release', () => {
expect(setCommits).toHaveBeenCalledTimes(1);
expect(setCommits).toHaveBeenCalledWith('v1.0.0', {
repo,
auto: true
auto: true,
});

expect(runCommand.runCommand).toHaveBeenCalledTimes(1);
Expand All @@ -46,7 +46,7 @@ describe('create-release', () => {
'v1.0.0',
'new',
'-e',
'qa'
'qa',
]);

expect(finalize).toHaveBeenCalledTimes(1);
Expand All @@ -55,6 +55,56 @@ describe('create-release', () => {
expect(core.setFailed).toHaveBeenCalledTimes(0);
});

test('releaseNamePrefix set', async () => {
const finalize = jest.fn().mockResolvedValue('done');
const newMock = jest.fn().mockResolvedValue('done');
const setCommits = jest.fn().mockResolvedValue('done');
const getPath = jest.fn().mockReturnValue('sentryCliPath');
const repo = 'repo';

SentryCli.mockImplementation(() => {
return {
releases: {
finalize,
new: newMock,
setCommits,
},
};
});
SentryCli.getPath = getPath;
core.getInput
.mockReturnValueOnce('refs/tags/v1.0.0')
.mockReturnValueOnce('qa')
.mockReturnValueOnce('myAwesomeProject-');
runCommand.runCommand.mockResolvedValue('done');

await run();

expect(newMock).toHaveBeenCalledTimes(1);
expect(newMock).toHaveBeenCalledWith('myAwesomeProject-v1.0.0');

expect(setCommits).toHaveBeenCalledTimes(1);
expect(setCommits).toHaveBeenCalledWith('myAwesomeProject-v1.0.0', {
repo,
auto: true,
});

expect(runCommand.runCommand).toHaveBeenCalledTimes(1);
expect(runCommand.runCommand).toHaveBeenCalledWith('sentryCliPath', [
'releases',
'deploys',
'myAwesomeProject-v1.0.0',
'new',
'-e',
'qa',
]);

expect(finalize).toHaveBeenCalledTimes(1);
expect(finalize).toHaveBeenCalledWith('myAwesomeProject-v1.0.0');

expect(core.setFailed).toHaveBeenCalledTimes(0);
});

test('Action fails', async () => {
SentryCli.mockImplementation(() => {
throw new Error('doh, something failed');
Expand Down

0 comments on commit b6c98a1

Please sign in to comment.