Skip to content

Commit

Permalink
Migrate prepare-release-from-ci to new workflow (#20581)
Browse files Browse the repository at this point in the history
* Migrate prepare-release-from-ci to new workflow

I added a `--releaseChannel (-r)` argument to script. You must choose
either "stable" or "experimental", because every build job now includes
both channels.

The prepare-release-from-npm script is unchanged since those releases
are downloaded from npm, nt CI.

(As a side note, I think we should start preparing semver releases using
the prepare-release-from-ci script, too, and get rid of
prepare-release-from-npm. I think that was a neat idea originally but
because we already run `npm pack` before storing the artifacts in CI,
there's really not much additional safety; the only safeguard it adds is
the requirement that a "next" release must have already been published.)

* Move validation to parse-params module
  • Loading branch information
acdlite committed Jan 14, 2021
1 parent 42e04b4 commit 98313aa
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 56 deletions.
8 changes: 1 addition & 7 deletions scripts/release/prepare-release-from-ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
'use strict';

const {join} = require('path');
const {readJsonSync} = require('fs-extra');
const {getPublicPackages, handleError} = require('./utils');
const {handleError} = require('./utils');

const checkEnvironmentVariables = require('./shared-commands/check-environment-variables');
const downloadBuildArtifacts = require('./shared-commands/download-build-artifacts');
Expand All @@ -26,11 +25,6 @@ const run = async () => {
await checkEnvironmentVariables(params);
await downloadBuildArtifacts(params);

const version = readJsonSync('./build/node_modules/react/package.json')
.version;
const isExperimental = version.includes('experimental');
params.packages = await getPublicPackages(isExperimental);

if (!params.skipTests) {
await testPackagingFixture(params);
await testTracingFixture(params);
Expand Down
67 changes: 29 additions & 38 deletions scripts/release/shared-commands/download-build-artifacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,56 @@
'use strict';

const {exec} = require('child-process-promise');
const {existsSync, readdirSync} = require('fs');
const {readJsonSync} = require('fs-extra');
const {existsSync} = require('fs');
const {join} = require('path');
const {getArtifactsList, logPromise} = require('../utils');
const theme = require('../theme');

const run = async ({build, cwd}) => {
const run = async ({build, cwd, releaseChannel}) => {
const artifacts = await getArtifactsList(build);
const nodeModulesArtifact = artifacts.find(entry =>
entry.path.endsWith('node_modules.tgz')
const buildArtifacts = artifacts.find(entry =>
entry.path.endsWith('build2.tgz')
);

if (!nodeModulesArtifact) {
if (!buildArtifacts) {
console.log(
theme`{error The specified build (${build}) does not contain any build artifacts.}`
);
process.exit(1);
}

const nodeModulesURL = nodeModulesArtifact.url;
// Download and extract artifact
await exec(`rm -rf ./build2`, {cwd});
await exec(
`curl -L $(fwdproxy-config curl) ${buildArtifacts.url} | tar -xvz`,
{
cwd,
}
);

// Copy to staging directory
// TODO: Consider staging the release in a different directory from the CI
// build artifacts: `./build/node_modules` -> `./staged-releases`
if (!existsSync(join(cwd, 'build'))) {
await exec(`mkdir ./build`, {cwd});
} else {
await exec(`rm -rf ./build/node_modules`, {cwd});
}

// Download and extract artifact
await exec(`rm -rf ./build/node_modules*`, {cwd});
await exec(`curl -L ${nodeModulesURL} --output ./build/node_modules.tgz`, {
cwd,
});
await exec(`mkdir ./build/node_modules`, {cwd});
await exec(`tar zxvf ./build/node_modules.tgz -C ./build/node_modules/`, {
cwd,
});

// Unpack packages and prepare to publish
const compressedPackages = readdirSync(join(cwd, 'build/node_modules/'));
for (let i = 0; i < compressedPackages.length; i++) {
await exec(
`tar zxvf ./build/node_modules/${compressedPackages[i]} -C ./build/node_modules/`,
{cwd}
);
const packageJSON = readJsonSync(
join(cwd, `/build/node_modules/package/package.json`)
);
await exec(
`mv ./build/node_modules/package ./build/node_modules/${packageJSON.name}`,
{cwd}
);
let sourceDir;
if (releaseChannel === 'stable') {
sourceDir = 'oss-stable';
} else if (releaseChannel === 'experimental') {
sourceDir = 'oss-experimental';
} else {
console.error('Internal error: Invalid release channel: ' + releaseChannel);
process.exit(releaseChannel);
}

// Cleanup
await exec(`rm ./build/node_modules.tgz`, {cwd});
await exec(`rm ./build/node_modules/*.tgz`, {cwd});
await exec(`cp -r ./build2/${sourceDir} ./build/node_modules`, {cwd});
};

module.exports = async ({build, cwd}) => {
module.exports = async ({build, cwd, releaseChannel}) => {
return logPromise(
run({build, cwd}),
run({build, cwd, releaseChannel}),
theme`Downloading artifacts from Circle CI for build {build ${build}}`
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@
const http = require('request-promise-json');
const {logPromise} = require('../utils');

const run = async useExperimentalBuild => {
const targetJobName = useExperimentalBuild
? 'process_artifacts_experimental'
: 'process_artifacts';

const run = async () => {
// https://circleci.com/docs/api/#recent-builds-for-a-project-branch
const metadataURL = `https://circleci.com/api/v1.1/project/github/facebook/react/tree/master`;
const metadata = await http.get(metadataURL, true);
const build = metadata.find(
entry =>
entry.branch === 'master' &&
entry.status === 'success' &&
entry.workflows.job_name === targetJobName
entry.workflows.job_name === 'process_artifacts_combined'
).build_num;

return build;
Expand Down
14 changes: 14 additions & 0 deletions scripts/release/shared-commands/parse-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,24 @@ const paramDefinitions = [
description: 'Skip automated fixture tests.',
defaultValue: false,
},
{
name: 'releaseChannel',
alias: 'r',
type: String,
description: 'Release channel (stable or experimental)',
},
];

module.exports = () => {
const params = commandLineArgs(paramDefinitions);

const channel = params.releaseChannel;
if (channel !== 'experimental' && channel !== 'stable') {
console.error(
`Invalid release channel (-r) "${channel}". Must be "stable" or "experimental".`
);
process.exit(1);
}

return params;
};
6 changes: 1 addition & 5 deletions scripts/release/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ const getArtifactsList = async buildID => {
);
process.exit(1);
}
const artifactsJobName = buildMetadata.workflows.job_name.endsWith(
'_experimental'
)
? 'process_artifacts_experimental'
: 'process_artifacts';
const artifactsJobName = 'process_artifacts_combined';
const workflowID = buildMetadata.workflows.workflow_id;
const workflowMetadataURL = `https://circleci.com/api/v2/workflow/${workflowID}/job?circle-token=${process.env.CIRCLE_CI_API_TOKEN}`;
const workflowMetadata = await http.get(workflowMetadataURL, true);
Expand Down

0 comments on commit 98313aa

Please sign in to comment.