Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ The following are all _required_.
|---|---|---|
|`environment`|Set the environment for this release. E.g. "production" or "staging". Omit to skip adding deploy to release.|-|
|`finalize`|When false, omit marking the release as finalized and released.|`true`|
|`ignore_missing`|When the flag is set and the previous release commit was not found in the repository, will create a release with the default commits count instead of failing the command.|`false`|
|`ignore_empty`|When the flag is set, command will not fail and just exit silently if no new commits for a given release have been found.|`false`|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels bad to duplicate this between the README and action.yml, but I realized that there are slight differences between the readme and this (for ex, version defaults to {{github.sha}}, but there is not default field in yml for that key).

|`sourcemaps`|Space-separated list of paths to JavaScript sourcemaps. Omit to skip uploading sourcemaps.|-|
|`started_at`|Unix timestamp of the release start date. Omit for current time.|-|
|`version`|Identifier that uniquely identifies the releases. _Note: the `refs/tags/` prefix is automatically stripped when `version` is `github.ref`._|<code>${{&nbsp;github.sha&nbsp;}}</code>|
|`version_prefix`|Value prepended to auto-generated version. For example "v".|-|
|`set_commits`|Specify whether to set commits for the release. Either "auto" or "skip".|"auto"|
|`projects`|Space-separated list of paths of projects. When omitted, falls back to the environment variable `SENTRY_PROJECT` to determine the project.|-|
|`url_prefix`|Adds a prefix to source map urls after stripping them.|-|
|`strip_common_prefix`|Will remove a common prefix from uploaded filenames. Useful for removing a path that is build-machine-specific.|`false`|

### Examples
- Create a new Sentry release for the `production` environment and upload JavaScript source maps from the `./lib` directory.
Expand Down
43 changes: 30 additions & 13 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,52 @@ import {execSync} from 'child_process';
import * as path from 'path';
import * as process from 'process';
import {
getShouldFinalize,
getBooleanOption,
getSourcemaps,
getStartedAt,
getVersion,
getSetCommitsOption,
getProjects,
getUrlPrefixOption,
} from '../src/validate';
} from '../src/options';

describe('validate', () => {
describe('options', () => {
beforeAll(() => {
process.env['MOCK'] = 'true';
});

describe('getShouldFinalize', () => {
const errorMessage = 'finalize is not a boolean';
describe('getBooleanOption', () => {
const option = 'finalize';
const defaultValue = true;
const errorMessage = `${option} is not a boolean`;

afterEach(() => {
delete process.env['INPUT_FINALIZE'];
});

test('should throw an error when finalize is invalid', async () => {
test('should throw an error when option type is not a boolean', () => {
process.env['INPUT_FINALIZE'] = 'error';
expect(() => getShouldFinalize()).toThrow(errorMessage);
expect(() => getBooleanOption(option, defaultValue)).toThrow(
errorMessage
);
});

test('should return true when finalize is omitted', async () => {
expect(getShouldFinalize()).toBe(true);
test('should return defaultValue if option is omitted', () => {
expect(getBooleanOption(option, defaultValue)).toBe(true);
});

test('should return false when finalize is false', () => {
test('should return true when option is true or 1', () => {
process.env['INPUT_FINALIZE'] = 'true';
expect(getBooleanOption(option, defaultValue)).toBe(true);
process.env['INPUT_FINALIZE'] = '1';
expect(getBooleanOption(option, defaultValue)).toBe(true);
});

test('should return false when option is false or 0', () => {
process.env['INPUT_FINALIZE'] = 'false';
expect(getShouldFinalize()).toBe(false);
expect(getBooleanOption(option, defaultValue)).toBe(false);
process.env['INPUT_FINALIZE'] = '0';
expect(getBooleanOption(option, defaultValue)).toBe(false);
});
});

Expand Down Expand Up @@ -121,6 +135,7 @@ describe('validate', () => {
expect(await getVersion()).toBe(`prefix-v1.0.0`);
});
});

describe('getSetCommitsOption', () => {
afterEach(() => {
delete process.env['INPUT_SET_COMMITS'];
Expand All @@ -143,6 +158,7 @@ describe('validate', () => {
expect(() => getSetCommitsOption()).toThrow(errorMessage);
});
});

describe('getProjects', () => {
afterEach(() => {
delete process.env['SENTRY_PROJECT'];
Expand All @@ -167,15 +183,16 @@ describe('validate', () => {
);
});
});

describe('getUrlPrefixOption', () => {
afterEach(() => {
delete process.env['URL_PREFIX'];
});
it('get url prefix', () => {
process.env['INPUT_URL_PREFIX'] = 'build';
expect(getUrlPrefixOption()).toEqual('build');
})
})
});
});
});

// shows how the runner will run a javascript action with env / stdout protocol
Expand Down
9 changes: 9 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ inputs:
finalize:
description: 'When false, omit marking the release as finalized and released.'
default: true
ignore_missing:
description: 'When the flag is set and the previous release commit was not found in the repository, will create a release with the default commits count instead of failing the command.'
required: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignore_missing and ignore_empty default to false. Do we have to update the action.yml to add a default: true for these fields?

Copy link
Contributor Author

@kamilogorek kamilogorek Jul 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't, as we do that here https://github.com/getsentry/action-release/pull/63/files#diff-4fab5baaca5c14d2de62d8d2fceef376ddddcc8e9509d86cfa5643f51b89ce3dR15-R16
And when not specified in the action.yml, they'll be undefined, thus if (!option) branch will return defaultValue

ignore_empty:
description: 'When the flag is set, command will not fail and just exit silently if no new commits for a given release have been found.'
required: false
started_at:
description: 'Unix timestamp of the release start date. Omit for current time.'
required: false
Expand All @@ -29,6 +35,9 @@ inputs:
url_prefix:
description: 'Adds a prefix to source map urls after stripping them.'
required: false
strip_common_prefix:
description: 'Will remove a common prefix from uploaded filenames. Useful for removing a path that is build-machine-specific.'
required: false
runs:
using: 'docker'
image: 'docker://sentryintegrations/sentry-github-action-release:latest'
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.4",
"@sentry/cli": "^1.59.0",
"@sentry/types": "^5.17.0"
"@sentry/cli": "^1.67.2"
},
"devDependencies": {
"@types/jest": "^26.0.0",
Expand Down
6 changes: 3 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SentryCli, {Releases} from '@sentry/cli';
import SentryCli, {SentryCliReleases} from '@sentry/cli';
// @ts-ignore
import {version} from '../package.json';

Expand All @@ -7,8 +7,8 @@ import {version} from '../package.json';
*
* When the `MOCK` environment variable is set, stub out network calls.
*/
let cli: Releases;
export const getCLI = (): Releases => {
let cli: SentryCliReleases;
export const getCLI = (): SentryCliReleases => {
// Set the User-Agent string.
process.env['SENTRY_PIPELINE'] = `github-action-release/${version}`;

Expand Down
35 changes: 23 additions & 12 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import * as core from '@actions/core';
import {getCLI} from './cli';
import * as validate from './validate';
import * as options from './options';

(async () => {
try {
const cli = getCLI();

// Validate parameters first so we can fail early.
validate.checkEnvironmentVariables();
const environment = validate.getEnvironment();
const sourcemaps = validate.getSourcemaps();
const shouldFinalize = validate.getShouldFinalize();
const deployStartedAtOption = validate.getStartedAt();
const setCommitsOption = validate.getSetCommitsOption();
const projects = validate.getProjects();
const urlPrefix = validate.getUrlPrefixOption();
// Validate options first so we can fail early.
options.checkEnvironmentVariables();

const version = await validate.getVersion();
const environment = options.getEnvironment();
const sourcemaps = options.getSourcemaps();
const shouldFinalize = options.getBooleanOption('finalize', true);
const ignoreMissing = options.getBooleanOption('ignore_missing', false);
const ignoreEmpty = options.getBooleanOption('ignore_empty', false);
const deployStartedAtOption = options.getStartedAt();
const setCommitsOption = options.getSetCommitsOption();
const projects = options.getProjects();
const urlPrefix = options.getUrlPrefixOption();
const stripCommonPrefix = options.getBooleanOption(
'strip_common_prefix',
false
);
const version = await options.getVersion();

core.debug(`Version is ${version}`);
await cli.new(version, {projects});

if (setCommitsOption !== 'skip') {
core.debug(`Setting commits with option '${setCommitsOption}'`);
await cli.setCommits(version, {auto: true});
await cli.setCommits(version, {
auto: true,
ignoreMissing,
ignoreEmpty,
});
}

if (sourcemaps.length) {
Expand All @@ -36,6 +46,7 @@ import * as validate from './validate';
include: sourcemaps,
projects: localProjects,
urlPrefix,
stripCommonPrefix,
};
return cli.uploadSourceMaps(version, sourceMapOptions);
})
Expand Down
25 changes: 15 additions & 10 deletions src/validate.ts → src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {getCLI} from './cli';
export const getVersion = async (): Promise<string> => {
const versionOption: string = core.getInput('version');
const versionPrefixOption: string = core.getInput('version_prefix');
let version = ''
let version = '';
if (versionOption) {
// If the users passes in `${{github.ref}}, then it will have an unwanted prefix.
version = versionOption.replace(/^(refs\/tags\/)/, '');
Expand Down Expand Up @@ -82,17 +82,22 @@ export const getSourcemaps = (): string[] => {
};

/**
* Find out from input if we should finalize the release.
* Fetch boolean option from input. Throws error if option value is not a boolean.
* @param input string
* @param defaultValue boolean
* @returns boolean
*/
export const getShouldFinalize = (): boolean => {
const finalizeOption = core.getInput('finalize');
if (!finalizeOption) {
return true;
export const getBooleanOption = (
input: string,
defaultValue: boolean
): boolean => {
const option = core.getInput(input);
if (!option) {
return defaultValue;
}

const finalize = finalizeOption.trim().toLowerCase();
switch (finalize) {
const value = option.trim().toLowerCase();
switch (value) {
case 'true':
case '1':
return true;
Expand All @@ -102,7 +107,7 @@ export const getShouldFinalize = (): boolean => {
return false;
}

throw Error('finalize is not a boolean');
throw Error(`${input} is not a boolean`);
};

export const getSetCommitsOption = (): 'auto' | 'skip' => {
Expand Down Expand Up @@ -159,4 +164,4 @@ export const getProjects = (): string[] => {

export const getUrlPrefixOption = (): string => {
return core.getInput('url_prefix');
}
};
54 changes: 0 additions & 54 deletions src/sentry-cli.d.ts

This file was deleted.

Loading