This repository has been archived by the owner on Dec 4, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
index.js
185 lines (162 loc) · 6.14 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
The Sentry Netlify build plugin:
- Notifies Sentry of new releases being deployed.
- Uploads source maps to Sentry.
- Sends Sentry the commit SHA of HEAD to enable commit features.
*/
const fs = require('fs');
const path = require('path');
const SentryCli = require('@sentry/cli');
const { promisify, inspect } = require('util');
const { version } = require('./package.json');
const rimraf = require('rimraf');
const writeFile = promisify(fs.writeFile);
const deleteFile = promisify(fs.unlink);
const CWD = path.resolve(process.cwd());
const SENTRY_CONFIG_PATH = path.resolve(CWD, '.sentryclirc');
const DEFAULT_SOURCE_MAP_URL_PREFIX = '~/';
module.exports = {
onPostBuild: async pluginApi => {
const { constants, inputs, utils } = pluginApi;
const { PUBLISH_DIR, IS_LOCAL } = constants;
const RUNNING_IN_NETLIFY = !IS_LOCAL;
const IS_PREVIEW = process.env.CONTEXT == 'deploy-preview';
/* Set the user input settings */
const sentryUrl = process.env.SENTRY_URL || inputs.sentryUrl;
const sentryOrg = process.env.SENTRY_ORG || inputs.sentryOrg;
const sentryProject = process.env.SENTRY_PROJECT || inputs.sentryProject;
const sentryAuthToken = process.env.SENTRY_AUTH_TOKEN || inputs.sentryAuthToken;
const sentryRelease = process.env.SENTRY_RELEASE || inputs.sentryRelease || process.env.COMMIT_REF;
const releasePrefix = process.env.SENTRY_RELEASE_PREFIX || inputs.releasePrefix || '';
const sentryEnvironment = process.env.SENTRY_ENVIRONMENT || process.env.CONTEXT;
const sentryRepository = process.env.SENTRY_REPOSITORY || inputs.sentryRepository;
const sourceMapPath = inputs.sourceMapPath || PUBLISH_DIR;
const sourceMapUrlPrefix = inputs.sourceMapUrlPrefix || DEFAULT_SOURCE_MAP_URL_PREFIX;
const shouldDeleteMaps = inputs.deleteSourceMaps || SENTRY_DELETE_SOURCEMAPS;
if (RUNNING_IN_NETLIFY) {
if (IS_PREVIEW && !inputs.deployPreviews) {
console.log('Skipping Sentry release creation - Deploy Preview');
return;
}
if (!sentryAuthToken) {
return utils.build.failBuild(
'SentryCLI needs an authentication token. Please set env variable SENTRY_AUTH_TOKEN',
);
} else if (!sentryOrg) {
return utils.build.failBuild(
'SentryCLI needs the organization slug. Please set env variable SENTRY_ORG or set sentryOrg as a plugin input',
);
} else if (!sentryProject) {
return utils.build.failBuild(
'SentryCLI needs the project slug. Please set env variable SENTRY_PROJECT or set sentryProject as a plugin input',
);
}
await createSentryConfig({
sentryOrg,
sentryProject,
sentryAuthToken,
sentryUrl,
});
/* Apply release prefix */
const release = `${releasePrefix}${sentryRelease}`;
/* Notify Sentry of release being deployed on Netlify */
await createSentryRelease({
pluginApi,
release,
sentryEnvironment,
sentryRepository,
sourceMapPath,
sourceMapUrlPrefix,
});
console.log();
console.log('Successfully notified Sentry of deployment!');
console.log();
await deleteSentryConfig();
if (shouldDeleteMaps) {
console.log('Removing source map files.');
await rimraf(sourceMapPath, {
filter: filepath => filepath.endsWith('.map'),
});
}
}
},
};
async function createSentryRelease({
pluginApi,
release,
sentryEnvironment,
sentryRepository,
sourceMapPath,
sourceMapUrlPrefix,
}) {
// default config file is read from ~/.sentryclirc
const { constants, inputs, utils } = pluginApi;
const cli = new SentryCli();
console.log('Creating new release with version: ', release);
// https://docs.sentry.io/cli/releases/#creating-releases
try {
await cli.releases.new(release);
} catch (error) {
if (error.message.includes('401')) {
return utils.build.failBuild(
'SentryCLI failed to create a new release. Invalid Sentry authentication token. (http status: 401)',
);
} else if (error.message.includes('403')) {
return utils.build.failBuild(
'SentryCLI failed to create a new release. You do not have permission to perform this action. (http status: 403)',
);
} else {
console.log(error);
return utils.build.failBuild('SentryCLI failed to create a new release.');
}
}
// https://docs.sentry.io/cli/releases/#managing-release-artifacts
if (!inputs.skipSourceMaps) {
await cli.releases.uploadSourceMaps(release, {
debug: false,
include: [sourceMapPath],
urlPrefix: sourceMapUrlPrefix,
rewrite: true,
ignore: ['node_modules'],
});
}
// https://docs.sentry.io/cli/releases/#sentry-cli-commit-integration
if (!inputs.skipSetCommits) {
const repository = sentryRepository || process.env.REPOSITORY_URL.split(/[:/]/).slice(-2).join('/');
try {
await cli.releases.setCommits(release, {
repo: repository,
commit: process.env.COMMIT_REF,
});
} catch (error) {
console.log(error);
return utils.build.failBuild(
`SentryCLI failed to set commits. You likely need to set up a repository or repository integration.
Read more: https://docs.sentry.io/workflow/releases/?platform=python#install-repo-integration`,
);
}
}
// https://docs.sentry.io/cli/releases/#finalizing-releases
await cli.releases.finalize(release);
// https://docs.sentry.io/cli/releases/#creating-deploys
await cli.releases.execute(['releases', 'deploys', release, 'new', '-e', sentryEnvironment]);
}
async function createSentryConfig({ sentryOrg, sentryProject, sentryAuthToken, sentryUrl }) {
const sentryConfigFile = `
[auth]
token=${sentryAuthToken}
[defaults]
${sentryUrl ? `url=${sentryUrl}` : ''}
project=${sentryProject}
org=${sentryOrg}
pipeline=netlify-build-plugin/${version}
`;
await writeFile(SENTRY_CONFIG_PATH, sentryConfigFile, { flag: 'w+' });
}
async function deleteSentryConfig() {
await deleteFile(SENTRY_CONFIG_PATH);
}
function fileExists(s) {
// eslint-disable-next-line
return new Promise(r => fs.access(s, fs.F_OK, e => r(!e)));
}