Skip to content

Commit 84d9571

Browse files
authored
Refactor Publish Pipeline Take 4 (#1778)
1 parent d9ef3ac commit 84d9571

File tree

10 files changed

+149
-61
lines changed

10 files changed

+149
-61
lines changed

.ado/get-next-semver-version.js

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,7 @@
22
const fs = require("fs");
33
const path = require("path");
44
const semver = require('semver');
5-
const {execSync} = require('child_process');
6-
7-
const pkgJsonPath = path.resolve(__dirname, "../package.json");
8-
let publishBranchName = '';
9-
try {
10-
publishBranchName = process.env.BUILD_SOURCEBRANCH.match(/refs\/heads\/(.*)/)[1];
11-
} catch (error) {}
12-
13-
function gatherVersionInfo() {
14-
let pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
15-
16-
let releaseVersion = pkgJson.version;
17-
const branchVersionSuffix = (publishBranchName.match(/(fb.*merge)|(fabric)/) ? `-${publishBranchName}` : '');
18-
19-
return {pkgJson, releaseVersion, branchVersionSuffix};
20-
}
5+
const {gatherVersionInfo} = require('./versionUtils');
216

227
function getNextVersion(patchVersionPrefix) {
238

.ado/gitTagRelease.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// @ts-check
2+
// Used to apply the package updates: the git tag for the published release.
3+
4+
const execSync = require("child_process").execSync;
5+
const {publishBranchName, gatherVersionInfo} = require('./versionUtils');
6+
7+
function exec(command) {
8+
try {
9+
console.log(`Running command: ${command}`);
10+
return execSync(command, {
11+
stdio: "inherit"
12+
});
13+
} catch (err) {
14+
process.exitCode = 1;
15+
console.log(`Failure running: ${command}`);
16+
throw err;
17+
}
18+
}
19+
20+
function doPublish() {
21+
console.log(`Target branch to publish to: ${publishBranchName}`);
22+
23+
const {releaseVersion} = gatherVersionInfo()
24+
25+
const tempPublishBranch = `publish-temp-${Date.now()}`;
26+
exec(`git checkout -b ${tempPublishBranch}`);
27+
28+
exec(`git add .`);
29+
exec(`git commit -m "Applying package update to ${releaseVersion} ***NO_CI***"`);
30+
exec(`git tag v${releaseVersion}`);
31+
exec(`git push origin HEAD:${tempPublishBranch} --follow-tags --verbose`);
32+
exec(`git push origin tag v${releaseVersion}`);
33+
34+
exec(`git checkout ${publishBranchName}`);
35+
exec(`git pull origin ${publishBranchName}`);
36+
exec(`git merge ${tempPublishBranch} --no-edit`);
37+
exec(
38+
`git push origin HEAD:${publishBranchName} --follow-tags --verbose`
39+
);
40+
exec(`git branch -d ${tempPublishBranch}`);
41+
exec(`git push origin --delete -d ${tempPublishBranch}`);
42+
}
43+
44+
doPublish();

.ado/publish.yml

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
value: true
3131
timeoutInMinutes: 90 # how long to run the job before automatically cancelling
3232
cancelTimeoutInMinutes: 5 # how much time to give 'run always even if cancelled tasks' before killing them
33+
dependsOn:
34+
- Compliance
3335
steps:
3436
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
3537
clean: true # whether to fetch clean each time
@@ -38,11 +40,16 @@ jobs:
3840
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
3941
persistCredentials: true # set to 'true' to leave the OAuth token in the Git config after the initial fetch
4042

41-
- ${{ if eq(variables['isMain'], true) }}:
43+
# Setup the repo to be ready for release. This includes:
44+
# - Autogenerating the next version number
45+
# - Calling the approprate scripts that upstream React Native uses to prepare a release
46+
# - Skipping the actual `git tag`, `git push`, and `npm publish steps as we do that here instead
47+
48+
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
4249
- template: templates/apple-job-publish.yml
4350
parameters:
4451
build_type: nightly
45-
- ${{ elseif eq(variables['isReleaseBranch'], true) }}:
52+
- ${{ elseif endsWith(variables['Build.SourceBranchName'], '-stable') }}:
4653
- template: templates/apple-job-publish.yml
4754
parameters:
4855
build_type: release
@@ -54,6 +61,8 @@ jobs:
5461
echo "Skipping publish for branch $(Build.SourceBranchName)"
5562
exit 1
5663
64+
# Generate and publish the SBOM
65+
5766
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
5867
displayName: 📒 Generate Manifest
5968
inputs:
@@ -65,6 +74,42 @@ jobs:
6574
artifactName: SBom-RNGithubNpmJSPublish-$(System.JobAttempt)
6675
targetPath: $(System.DefaultWorkingDirectory)/_manifest
6776

77+
# Set the NPM dist-tag and do the actual NPM publish
78+
79+
- bash: echo "##vso[task.setvariable variable=npmDistTag]latest"
80+
displayName: Set dist-tag to latest
81+
condition: eq(variables['Build.SourceBranchName'], variables.latestStableBranch)
82+
83+
- bash: echo "##vso[task.setvariable variable=npmDistTag]canary"
84+
displayName: Set dist-tag to canary
85+
condition: eq(variables['Build.SourceBranchName'], 'main')
86+
87+
- bash: echo "##vso[task.setvariable variable=npmDistTag]v${{variables['Build.SourceBranchName']}}"
88+
displayName: Set dist-tag to v0.x-stable
89+
condition: and(ne(variables['Build.SourceBranchName'], 'main'), ne(variables['Build.SourceBranchName'], variables.latestStableBranch))
90+
91+
- task: CmdLine@2
92+
displayName: Actual NPM Publish
93+
inputs:
94+
script: |
95+
npm publish --tag $(npmDistTag) --registry https://registry.npmjs.org/ --//registry.npmjs.org/:_authToken=$(npmAuthToken)
96+
97+
# Set the git tag and push the version update back to Github
98+
99+
- template: templates/configure-git.yml
100+
101+
- task: CmdLine@2
102+
displayName: 'Tag and push to Github'
103+
inputs:
104+
script: node .ado/gitTagRelease.js
105+
env:
106+
BUILD_STAGINGDIRECTORY: $(Build.StagingDirectory)
107+
BUILD_SOURCEBRANCH: $(Build.SourceBranch)
108+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
109+
githubAuthToken: $(githubAuthToken)
110+
condition: and(succeeded(), ne(variables['Build.SourceBranchName'], 'main'))
111+
112+
68113
- job: RNMacOSInitNpmJSPublish
69114
displayName: NPM Publish react-native-macos-init
70115
pool: cxeiss-ubuntu-20-04-large
@@ -83,7 +128,7 @@ jobs:
83128

84129
- template: templates/apple-install-dependencies.yml
85130

86-
- template: templates/apple-release-setup.yml
131+
- template: templates/configure-git.yml
87132

88133
- task: CmdLine@2
89134
displayName: Build react-native-macos-init

.ado/templates/apple-job-publish.yml

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,36 @@ steps:
66

77
- template: apple-install-dependencies.yml
88

9-
# Only set up our release environment if we're not doing a dry run
10-
- ${{ if ne( parameters['build_type'], 'dry-run') }}:
11-
- template: apple-release-setup.yml
12-
13-
- task: CmdLine@2
14-
displayName: Set build type to ${{parameters.build_type}}
15-
inputs:
16-
script: |
17-
BUILD_TYPE=${{parameters.build_type}}
18-
echo "Set build type: $BUILD_TYPE"
19-
209
# Extra steps needed for *-stable releases
2110
- ${{ if eq( parameters['build_type'], 'release') }}:
22-
- task: CmdLine@2
23-
displayName: Set next version
24-
inputs:
25-
script: |
26-
VERSION=$(node .ado/get-next-semver-version.js)
27-
echo "Set version: $VERSION"
28-
29-
- task: CmdLine@2
30-
displayName: Set build type to ${{parameters.build_type}}
31-
inputs:
32-
script: |
33-
BUILD_TYPE=release
34-
echo "Set build type: $BUILD_TYPE"
35-
3611
- task: CmdLine@2
3712
displayName: Set latest tag
3813
inputs:
3914
script: |
4015
LATEST=true
4116
echo "Set latest to: $LATEST"
17+
condition: eq(variables['Build.SourceBranchName'], variables.latestStableBranch)
4218

19+
# Note, This won't do the actual `git tag` and `git push` as we're doing a dry run.
20+
# We do that as a separate step in `.ado/publish.yml`.
4321
- task: CmdLine@2
44-
displayName: Prepare and tag package for release
22+
displayName: Prepare package for release
4523
inputs:
4624
script: |
25+
VERSION=$(node .ado/get-next-semver-version.js)
4726
if [[ -z "$VERSION" ]]; then
4827
VERSION=$(grep '"version"' package.json | cut -d '"' -f 4 | head -1)
4928
echo "Using the version from the package.json: $VERSION"
5029
fi
51-
node ./scripts/prepare-package-for-release.js -v "$VERSION" -l $LATEST
30+
node ./scripts/prepare-package-for-release.js -v "$VERSION" --dry-run
31+
env:
32+
# Map the corresponding variable since `prepare-package-for-release.js` depends on it.
33+
CIRCLE_BRANCH: $(Build.SourceBranchName)
5234

35+
# Note: This won't actually publish to NPM as we've commented that bit out.
36+
# We do that as a separate step in `.ado/publish.yml`.
5337
- task: CmdLine@2
54-
displayName: NPM Publish
38+
displayName: Run publish-npm.js
5539
inputs:
5640
script: |
5741
node ./scripts/publish-npm.js --${{ parameters.build_type }}

.ado/templates/apple-release-setup.yml renamed to .ado/templates/configure-git.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,5 @@ steps:
66
git config --global user.email "[email protected]"
77
git config --global user.name "React-Native Bot"
88
9-
- task: CmdLine@2
10-
displayName: Set NPM Auth Token
11-
inputs:
12-
script: |
13-
echo "//registry.npmjs.org/:_authToken=${npmAuthToken}" > ~/.npmrc
9+
- script: git remote set-url origin https://rnbot:$(githubAuthToken)@github.com/microsoft/react-native-macos
10+
displayName: Set Permissions to push

.ado/variables/vars.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@ variables:
22
VmImageApple: internal-macos12
33
slice_name: 'Xcode_14.2'
44
xcode_version: '/Applications/Xcode_14.2.app'
5-
isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
6-
isReleaseBranch: $[endsWith(variables['Build.SourceBranchName'], '-stable')]
5+
latestStableBranch: '0.71-stable'

.ado/versionUtils.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @ts-check
2+
const fs = require("fs");
3+
const path = require("path");
4+
const semver = require('semver');
5+
const {execSync} = require('child_process');
6+
7+
const pkgJsonPath = path.resolve(__dirname, "../package.json");
8+
let publishBranchName = '';
9+
try {
10+
publishBranchName = process.env.BUILD_SOURCEBRANCH.match(/refs\/heads\/(.*)/)[1];
11+
} catch (error) {}
12+
13+
function gatherVersionInfo() {
14+
let pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
15+
16+
let releaseVersion = pkgJson.version;
17+
const branchVersionSuffix = (publishBranchName.match(/(fb.*merge)|(fabric)/) ? `-${publishBranchName}` : '');
18+
19+
return {pkgJson, releaseVersion, branchVersionSuffix};
20+
}
21+
22+
module.exports = {
23+
gatherVersionInfo,
24+
publishBranchName,
25+
pkgJsonPath,
26+
}

scripts/prepare-package-for-release.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const {echo, exec, exit} = require('shelljs');
2222
const yargs = require('yargs');
2323
const {isReleaseBranch, parseVersion} = require('./version-utils');
2424
const {failIfTagExists} = require('./release-utils');
25-
const {getBranchName} = require('./scm-utils'); // [macOS]
2625

2726
const argv = yargs
2827
.option('r', {
@@ -45,7 +44,7 @@ const argv = yargs
4544
default: false,
4645
}).argv;
4746

48-
const branch = getBranchName(); // [macOS] Don't rely on CircleCI environment variables.
47+
const branch = process.env.CIRCLE_BRANCH;
4948
const remote = argv.remote;
5049
const releaseVersion = argv.toVersion;
5150
const isLatest = argv.latest;

scripts/publish-npm.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const os = require('os');
5252
const path = require('path');
5353
const yargs = require('yargs');
5454

55-
const buildTag = exec('git tag --points-at HEAD'); // [macOS] Don't rely on CircleCI environment variables.
55+
// const buildTag = process.env.CIRCLE_TAG; // [macOS] We can't use the CircleCI build tag.
5656
const otp = process.env.NPM_CONFIG_OTP;
5757
const tmpPublishingFolder = fs.mkdtempSync(
5858
path.join(os.tmpdir(), 'rn-publish-'),
@@ -96,6 +96,15 @@ saveFilesToRestore(tmpPublishingFolder);
9696
const currentCommit = getCurrentCommit();
9797
const shortCommit = currentCommit.slice(0, 9);
9898

99+
// [macOS] Function to get our version from package.json instead of the CircleCI build tag.
100+
function getPkgJsonVersion() {
101+
const pkgJsonPath = path.resolve(__dirname, '../package.json');
102+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
103+
const pkgJsonVersion = pkgJson.version;
104+
return pkgJsonVersion;
105+
}
106+
// macOS]
107+
99108
const rawVersion =
100109
// 0.0.0 triggers issues with cocoapods for codegen when building template project.
101110
dryRunBuild
@@ -104,7 +113,7 @@ const rawVersion =
104113
nightlyBuild
105114
? '0.0.0'
106115
: // For pre-release and stable releases, we use the git tag of the version we're releasing (set in set-rn-version)
107-
buildTag.substring(0, buildTag.indexOf('-microsft')); // [macOS] Strip off the "-microsoft" suffix from the tag name.
116+
getPkgJsonVersion(); // [macOS] We can't use the CircleCI build tag, so we use the version argument instead.
108117

109118
let version,
110119
major,
@@ -170,6 +179,7 @@ const isLatest = exitIfNotOnGit(
170179
publishAndroidArtifactsToMaven(releaseVersion, nightlyBuild);
171180
macOS] */
172181

182+
/* [macOS Comment the NPM publish out as we do this separately
173183
const releaseBranch = `${major}.${minor}-stable`;
174184
175185
// Set the right tag for nightly and prerelease builds
@@ -186,10 +196,11 @@ const tagFlag = nightlyBuild
186196
// use otp from envvars if available
187197
const otpFlag = otp ? `--otp ${otp}` : '';
188198
189-
if (exec(`npm publish ${tagFlag} ${otpFlag}`).code) {
199+
if (exec(`npm publish ${tagFlag} ${otpFlag}`, {cwd: RN_PACKAGE_DIR}).code) {
190200
echo('Failed to publish package to npm');
191201
exit(1);
192202
} else {
193203
echo(`Published to npm ${releaseVersion}`);
194204
exit(0);
195205
}
206+
macOS] */

scripts/release-utils.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ const {createHermesPrebuiltArtifactsTarball} = require('./hermes/hermes-utils');
1717
function saveFilesToRestore(tmpPublishingFolder) {
1818
const filesToSaveAndRestore = [
1919
'template/Gemfile',
20-
'template/_ruby-version',
2120
'template/package.json',
22-
'.ruby-version',
2321
'Gemfile.lock',
2422
'Gemfile',
2523
'package.json',

0 commit comments

Comments
 (0)