1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 18:00:18 +01:00

Automate the Flask release process (#13898)

* Automate the Flask release

A Flask release will now be published alongside each main extension
release. The version of each Flask release will be the same as the
extension version except it will have the suffix `-flask.0`.

* Programmatically remove build prefix

The create GH release Bash script derives the Flask version from the
Flask build filename by removing the build prefix, leaving just the
version. Rather than hard-coding the prefix size to remove, it is now
calculated programmatically so that it is easier to read and update.

* Fix tag publishing

The tab publishing step used the wrong credentials, and didn't properly
identify the commit author. This has now been fixed.
This commit is contained in:
Mark Stacey 2022-03-15 08:54:37 -02:30 committed by Erik Marks
parent 29e083c4c4
commit ce9dc12f75
5 changed files with 118 additions and 34 deletions

View File

@ -160,6 +160,7 @@ workflows:
requires: requires:
- prep-deps - prep-deps
- prep-build - prep-build
- prep-build-flask
- all-tests-pass - all-tests-pass
- job-publish-storybook: - job-publish-storybook:
filters: filters:
@ -718,8 +719,11 @@ jobs:
- attach_workspace: - attach_workspace:
at: . at: .
- run: - run:
name: sentry sourcemaps upload name: Publish main release to Sentry
command: SENTRY_ORG=metamask SENTRY_PROJECT=metamask yarn sentry:publish command: yarn sentry:publish
- run:
name: Publish Flask release to Sentry
command: yarn sentry:publish --build-type flask
- run: - run:
name: Create GitHub release name: Create GitHub release
command: | command: |

View File

@ -26,25 +26,53 @@ function install_github_cli ()
popd popd
} }
function print_flask_version ()
{
local flask_filename
flask_filename="$(find ./builds-flask -type f -name 'metamask-flask-chrome-*.zip' -exec basename {} .zip \;)"
local flask_build_filename_prefix
flask_build_filename_prefix='metamask-flask-chrome-'
local flask_build_filename_prefix_size
flask_build_filename_prefix_size="${#flask_build_filename_prefix}"
# Use substring parameter expansion to remove the filename prefix, leaving just the version
echo "${flask_filename:$flask_build_filename_prefix_size}"
}
function publish_flask_tag ()
{
local flask_version="${1}"; shift
git config user.email "metamaskbot@users.noreply.github.com"
git config user.name "MetaMask Bot"
git tag -a "v${flask_version}" -m "Flask version ${flask_version}"
repo_slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME"
git push "https://$GITHUB_TOKEN@github.com/$repo_slug" "v${flask_version}"
}
current_commit_msg=$(git show -s --format='%s' HEAD) current_commit_msg=$(git show -s --format='%s' HEAD)
if [[ $current_commit_msg =~ Version[-[:space:]](v[[:digit:]]+.[[:digit:]]+.[[:digit:]]+) ]] if [[ $current_commit_msg =~ Version[-[:space:]](v[[:digit:]]+.[[:digit:]]+.[[:digit:]]+) ]]
then then
tag="${BASH_REMATCH[1]}" tag="${BASH_REMATCH[1]}"
flask_version="$(print_flask_version)"
install_github_cli install_github_cli
printf '%s\n' 'Creating GitHub Release' printf '%s\n' 'Creating GitHub Release'
release_body="$(awk -v version="${tag##v}" -f .circleci/scripts/show-changelog.awk CHANGELOG.md)" release_body="$(awk -v version="${tag##v}" -f .circleci/scripts/show-changelog.awk CHANGELOG.md)"
pushd builds
hub release create \ hub release create \
--attach metamask-chrome-*.zip \ --attach builds/metamask-chrome-*.zip \
--attach metamask-firefox-*.zip \ --attach builds/metamask-firefox-*.zip \
--attach builds-flask/metamask-flask-chrome-*.zip \
--attach builds-flask/metamask-flask-firefox-*.zip \
--message "Version ${tag##v}" \ --message "Version ${tag##v}" \
--message "$release_body" \ --message "$release_body" \
--commitish "$CIRCLE_SHA1" \ --commitish "$CIRCLE_SHA1" \
"$tag" "$tag"
popd
publish_flask_tag "${flask_version}"
else else
printf '%s\n' 'Version not found in commit message; skipping GitHub Release' printf '%s\n' 'Version not found in commit message; skipping GitHub Release'
exit 0 exit 0

View File

@ -3,7 +3,7 @@ const { promises: fs } = require('fs');
const path = require('path'); const path = require('path');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const glob = require('fast-glob'); const glob = require('fast-glob');
const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved const VERSION = require('../package.json').version;
const { getHighlights } = require('./highlights'); const { getHighlights } = require('./highlights');
start().catch(console.error); start().catch(console.error);

View File

@ -1,6 +1,11 @@
#!/usr/bin/env node #!/usr/bin/env node
const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const { runCommand, runInShell } = require('./lib/run-command'); const { runCommand, runInShell } = require('./lib/run-command');
const { getVersion } = require('./lib/get-version');
const { BuildType } = require('./lib/build-type');
start().catch((error) => { start().catch((error) => {
console.error(error); console.error(error);
@ -8,34 +13,63 @@ start().catch((error) => {
}); });
async function start() { async function start() {
if (!process.env.SENTRY_ORG) { const { argv } = yargs(hideBin(process.argv)).usage(
throw new Error('Missing required "SENTRY_ORG" environment variable'); '$0 [options]',
} else if (!process.env.SENTRY_PROJECT) { 'Publish a release to Sentry',
throw new Error('Missing required "SENTRY_PROJECT" environment variable'); (_yargs) =>
} _yargs
.option('org', {
default: 'metamask',
description: 'The Sentry organization',
type: 'string',
})
.option('project', {
default: 'metamask',
description: 'The Sentry project to publish',
type: 'string',
})
.option('build-type', {
default: BuildType.main,
description: 'The MetaMask extension build type',
choices: Object.values(BuildType),
})
.option('build-version', {
default: 0,
description: 'The MetaMask extension build version',
type: 'number',
}),
);
const { buildType, buildVersion, org, project } = argv;
process.env.SENTRY_ORG = org;
process.env.SENTRY_PROJECT = project;
const authWorked = await checkIfAuthWorks(); const authWorked = await checkIfAuthWorks();
if (!authWorked) { if (!authWorked) {
throw new Error(`Sentry auth failed`); throw new Error(`Sentry auth failed`);
} }
const version = getVersion(buildType, buildVersion);
// check if version exists or not // check if version exists or not
const versionAlreadyExists = await checkIfVersionExists(); const versionAlreadyExists = await checkIfVersionExists(version);
// abort if versions exists // abort if versions exists
if (versionAlreadyExists) { if (versionAlreadyExists) {
console.log( console.log(
`Version "${VERSION}" already exists on Sentry, skipping version creation`, `Version "${version}" already exists on Sentry, skipping version creation`,
); );
} else { } else {
// create sentry release // create sentry release
console.log(`creating Sentry release for "${VERSION}"...`); console.log(`creating Sentry release for "${version}"...`);
await runCommand('sentry-cli', ['releases', 'new', VERSION]); await runCommand('sentry-cli', ['releases', 'new', version]);
console.log( console.log(
`removing any existing files from Sentry release "${VERSION}"...`, `removing any existing files from Sentry release "${version}"...`,
); );
await runCommand('sentry-cli', [ await runCommand('sentry-cli', [
'releases', 'releases',
'files', 'files',
VERSION, version,
'delete', 'delete',
'--all', '--all',
]); ]);
@ -43,18 +77,23 @@ async function start() {
// check if version has artifacts or not // check if version has artifacts or not
const versionHasArtifacts = const versionHasArtifacts =
versionAlreadyExists && (await checkIfVersionHasArtifacts()); versionAlreadyExists && (await checkIfVersionHasArtifacts(version));
if (versionHasArtifacts) { if (versionHasArtifacts) {
console.log( console.log(
`Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`, `Version "${version}" already has artifacts on Sentry, skipping sourcemap upload`,
); );
return; return;
} }
const additionalUploadArgs = [];
if (buildType !== BuildType.main) {
additionalUploadArgs.push('--dist-directory', `dist-${buildType}`);
}
// upload sentry source and sourcemaps // upload sentry source and sourcemaps
await runInShell('./development/sentry-upload-artifacts.sh', [ await runInShell('./development/sentry-upload-artifacts.sh', [
'--release', '--release',
VERSION, version,
...additionalUploadArgs,
]); ]);
} }
@ -64,17 +103,17 @@ async function checkIfAuthWorks() {
); );
} }
async function checkIfVersionExists() { async function checkIfVersionExists(version) {
return await doesNotFail(() => return await doesNotFail(() =>
runCommand('sentry-cli', ['releases', 'info', VERSION]), runCommand('sentry-cli', ['releases', 'info', version]),
); );
} }
async function checkIfVersionHasArtifacts() { async function checkIfVersionHasArtifacts(version) {
const [artifact] = await runCommand('sentry-cli', [ const [artifact] = await runCommand('sentry-cli', [
'releases', 'releases',
'files', 'files',
VERSION, version,
'list', 'list',
]); ]);
// When there's no artifacts, we get a response from the shell like this ['', ''] // When there's no artifacts, we get a response from the shell like this ['', '']

View File

@ -23,17 +23,20 @@ Upload JavaScript bundles and sourcemaps to Sentry
Options: Options:
-h, --help Show help text -h, --help Show help text
-r, --release <release> Sentry release to upload files to (defaults to 'VERSION' environment variable) -r, --release <release> Sentry release to upload files to (defaults to 'VERSION' environment variable)
--dist-directory <path> The 'dist' directory to use. Defaults to 'dist'.
EOF EOF
} }
function upload_sourcemaps { function upload_sourcemaps {
local release="${1}"; shift local release="${1}"; shift
local dist_directory="${1}"; shift
sentry-cli releases files "${release}" upload-sourcemaps ./dist/chrome/*.js ./dist/sourcemaps/ --rewrite --url-prefix 'metamask' sentry-cli releases files "${release}" upload-sourcemaps "${dist_directory}"/chrome/*.js "${dist_directory}"/sourcemaps/ --rewrite --url-prefix 'metamask'
} }
function main { function main {
local release=VERSION local release=VERSION
local dist_directory='dist'
while :; do while :; do
case "${1-default}" in case "${1-default}" in
@ -51,6 +54,16 @@ function main {
release="${2}" release="${2}"
shift shift
;; ;;
--dist-directory)
if [[ -z $2 ]]
then
printf "'dist-directory' option requires an argument.\\n" >&2
printf '%s\n' "${__SEE_HELP_MESSAGE__}" >&2
exit 1
fi
dist_directory="${2}"
shift
;;
*) *)
break break
esac esac
@ -70,7 +83,7 @@ function main {
fi fi
printf 'uploading source files and sourcemaps for Sentry release "%s"...\n' "${release}" printf 'uploading source files and sourcemaps for Sentry release "%s"...\n' "${release}"
upload_sourcemaps "${release}" upload_sourcemaps "${release}" "${dist_directory}"
printf 'all done!\n' printf 'all done!\n'
} }