From bddd3c57d94e83f8a40b8735fbf3004e2f838c45 Mon Sep 17 00:00:00 2001 From: Joe Gambino <jgambino96@gmail.com> Date: Mon, 6 Dec 2021 18:37:19 -0800 Subject: [PATCH 1/6] Revert "Revert "[No QA] Ensure bundle version strings are compatible before auto-merging CP PR"" --- .../checkBundleVersionStringMatch/action.yml | 8 + .../checkBundleVersionStringMatch.js | 16 + .../checkBundleVersionStringMatch/index.js | 1248 +++++++++++++++++ .github/scripts/buildActions.sh | 1 + .github/workflows/cherryPick.yml | 19 +- 5 files changed, 1290 insertions(+), 2 deletions(-) create mode 100644 .github/actions/checkBundleVersionStringMatch/action.yml create mode 100644 .github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js create mode 100644 .github/actions/checkBundleVersionStringMatch/index.js diff --git a/.github/actions/checkBundleVersionStringMatch/action.yml b/.github/actions/checkBundleVersionStringMatch/action.yml new file mode 100644 index 000000000000..62258adc62b5 --- /dev/null +++ b/.github/actions/checkBundleVersionStringMatch/action.yml @@ -0,0 +1,8 @@ +name: 'Check if Bundle Versions Match' +description: "Check if the CFBundleVersion string is compatible with the CFBundleShortVersionString" +outputs: + BUNDLE_VERSIONS_MATCH: + description: Whether or not the bundle versions match +runs: + using: 'node12' + main: './index.js' diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js new file mode 100644 index 000000000000..f601976a2f2a --- /dev/null +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -0,0 +1,16 @@ +const core = require('@actions/core'); +const {execSync} = require('child_process'); +const {PLIST_PATH} = require('../../libs/nativeVersionUpdater'); + +const bundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" ${PLIST_PATH}`); +const shortBundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${PLIST_PATH}`); + +console.log(`Bundle Version: ${bundleVersion}`); +console.log(`Short Bundle Version: ${shortBundleVersion}`); +if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { + console.log('Bundle Versions do not match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); +} else { + console.log('Bundle Versions match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', true); +} diff --git a/.github/actions/checkBundleVersionStringMatch/index.js b/.github/actions/checkBundleVersionStringMatch/index.js new file mode 100644 index 000000000000..960ac54b3fbf --- /dev/null +++ b/.github/actions/checkBundleVersionStringMatch/index.js @@ -0,0 +1,1248 @@ +/** + * NOTE: This is a compiled file. DO NOT directly edit this file. + */ +module.exports = +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 330: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __nccwpck_require__) => { + +const core = __nccwpck_require__(186); +const {execSync} = __nccwpck_require__(129); +const {PLIST_PATH} = __nccwpck_require__(322); + +const bundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" ${PLIST_PATH}`); +const shortBundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${PLIST_PATH}`); + +console.log(`Bundle Version: ${bundleVersion}`); +console.log(`Short Bundle Version: ${shortBundleVersion}`); +if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { + console.log('Bundle Versions do not match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); +} else { + console.log('Bundle Versions match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', true); +} + + +/***/ }), + +/***/ 322: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +const {execSync} = __nccwpck_require__(129); +const fs = __nccwpck_require__(747).promises; +const path = __nccwpck_require__(622); +const getMajorVersion = __nccwpck_require__(688); +const getMinorVersion = __nccwpck_require__(447); +const getPatchVersion = __nccwpck_require__(866); +const getBuildVersion = __nccwpck_require__(16); + +// Filepath constants +const BUILD_GRADLE_PATH = process.env.NODE_ENV === 'test' + ? path.resolve(__dirname, '../../android/app/build.gradle') + : './android/app/build.gradle'; +const PLIST_PATH = './ios/NewExpensify/Info.plist'; +const PLIST_PATH_TEST = './ios/NewExpensifyTests/Info.plist'; + +exports.BUILD_GRADLE_PATH = BUILD_GRADLE_PATH; +exports.PLIST_PATH = PLIST_PATH; +exports.PLIST_PATH_TEST = PLIST_PATH_TEST; + +/** + * Pad a number to be two digits (with leading zeros if necessary). + * + * @param {Number} number - Must be an integer. + * @returns {String} - A string representation of the number with length 2. + */ +function padToTwoDigits(number) { + if (number >= 10) { + return number.toString(); + } + return `0${number.toString()}`; +} + +/** + * Generate the 10-digit versionCode for android. + * This version code allocates two digits each for PREFIX, MAJOR, MINOR, PATCH, and BUILD versions. + * As a result, our max version is 99.99.99-99. + * + * @param {String} npmVersion + * @returns {String} + */ +exports.generateAndroidVersionCode = function generateAndroidVersionCode(npmVersion) { + // All Android versions will be prefixed with '10' due to previous versioning + const prefix = '10'; + return ''.concat( + prefix, + padToTwoDigits(getMajorVersion(npmVersion) || 0), + padToTwoDigits(getMinorVersion(npmVersion) || 0), + padToTwoDigits(getPatchVersion(npmVersion) || 0), + padToTwoDigits(getBuildVersion(npmVersion) || 0), + ); +}; + + +/** + * Update the Android app versionName and versionCode. + * + * @param {String} versionName + * @param {String} versionCode + * @returns {Promise} + */ +exports.updateAndroidVersion = function updateAndroidVersion(versionName, versionCode) { + console.log('Updating android:', `versionName: ${versionName}`, `versionCode: ${versionCode}`); + return fs.readFile(BUILD_GRADLE_PATH, {encoding: 'utf8'}) + .then((content) => { + let updatedContent = content.toString().replace(/versionName "([0-9.-]*)"/, `versionName "${versionName}"`); + return updatedContent = updatedContent.replace(/versionCode ([0-9]*)/, `versionCode ${versionCode}`); + }) + .then(updatedContent => fs.writeFile(BUILD_GRADLE_PATH, updatedContent, {encoding: 'utf8'})); +}; + +/** + * Update the iOS app version. + * Updates the CFBundleShortVersionString and the CFBundleVersion. + * + * @param {String} version + * @returns {String} + */ +exports.updateiOSVersion = function updateiOSVersion(version) { + const shortVersion = version.split('-')[0]; + const cfVersion = version.includes('-') ? version.replace('-', '.') : `${version}.0`; + console.log('Updating iOS', `CFBundleShortVersionString: ${shortVersion}`, `CFBundleVersion: ${cfVersion}`); + + // Update Plists + execSync(`/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${shortVersion}" ${PLIST_PATH}`); + execSync(`/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${shortVersion}" ${PLIST_PATH_TEST}`); + execSync(`/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${cfVersion}" ${PLIST_PATH}`); + execSync(`/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${cfVersion}" ${PLIST_PATH_TEST}`); + + // Return the cfVersion so we can set the NEW_IOS_VERSION in ios.yml + return cfVersion; +}; + + +/***/ }), + +/***/ 351: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const os = __importStar(__nccwpck_require__(87)); +const utils_1 = __nccwpck_require__(278); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 186: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const command_1 = __nccwpck_require__(351); +const file_command_1 = __nccwpck_require__(717); +const utils_1 = __nccwpck_require__(278); +const os = __importStar(__nccwpck_require__(87)); +const path = __importStar(__nccwpck_require__(622)); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + const delimiter = '_GitHubActionsFileCommandDelimeter_'; + const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; + file_command_1.issueCommand('ENV', commandValue); + } + else { + command_1.issueCommand('set-env', { name }, convertedVal); + } +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueCommand('PATH', inputPath); + } + else { + command_1.issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. The value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + command_1.issueCommand('set-output', { name }, value); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + */ +function error(message) { + command_1.issue('error', message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds an warning issue + * @param message warning issue message. Errors will be converted to string via toString() + */ +function warning(message) { + command_1.issue('warning', message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + command_1.issueCommand('save-state', { name }, value); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 717: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fs = __importStar(__nccwpck_require__(747)); +const os = __importStar(__nccwpck_require__(87)); +const utils_1 = __nccwpck_require__(278); +function issueCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueCommand = issueCommand; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 278: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 88: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const debug = __nccwpck_require__(427) +const { MAX_LENGTH, MAX_SAFE_INTEGER } = __nccwpck_require__(293) +const { re, t } = __nccwpck_require__(523) + +const parseOptions = __nccwpck_require__(785) +const { compareIdentifiers } = __nccwpck_require__(463) +class SemVer { + constructor (version, options) { + options = parseOptions(options) + + if (version instanceof SemVer) { + if (version.loose === !!options.loose && + version.includePrerelease === !!options.includePrerelease) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError(`Invalid Version: ${version}`) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + // this isn't actually relevant for versions, but keep it so that we + // don't run into trouble passing this.options around. + this.includePrerelease = !!options.includePrerelease + + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) + + if (!m) { + throw new TypeError(`Invalid Version: ${version}`) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() + } + + format () { + this.version = `${this.major}.${this.minor}.${this.patch}` + if (this.prerelease.length) { + this.version += `-${this.prerelease.join('.')}` + } + return this.version + } + + toString () { + return this.version + } + + compare (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + if (typeof other === 'string' && other === this.version) { + return 0 + } + other = new SemVer(other, this.options) + } + + if (other.version === this.version) { + return 0 + } + + return this.compareMain(other) || this.comparePre(other) + } + + compareMain (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return ( + compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) + ) + } + + comparePre (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + let i = 0 + do { + const a = this.prerelease[i] + const b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + compareBuild (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + let i = 0 + do { + const a = this.build[i] + const b = other.build[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if ( + this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0 + ) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + let i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error(`invalid increment argument: ${release}`) + } + this.format() + this.raw = this.version + return this + } +} + +module.exports = SemVer + + +/***/ }), + +/***/ 688: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const SemVer = __nccwpck_require__(88) +const major = (a, loose) => new SemVer(a, loose).major +module.exports = major + + +/***/ }), + +/***/ 447: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const SemVer = __nccwpck_require__(88) +const minor = (a, loose) => new SemVer(a, loose).minor +module.exports = minor + + +/***/ }), + +/***/ 925: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const {MAX_LENGTH} = __nccwpck_require__(293) +const { re, t } = __nccwpck_require__(523) +const SemVer = __nccwpck_require__(88) + +const parseOptions = __nccwpck_require__(785) +const parse = (version, options) => { + options = parseOptions(options) + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + const r = options.loose ? re[t.LOOSE] : re[t.FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +module.exports = parse + + +/***/ }), + +/***/ 866: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const SemVer = __nccwpck_require__(88) +const patch = (a, loose) => new SemVer(a, loose).patch +module.exports = patch + + +/***/ }), + +/***/ 16: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const parse = __nccwpck_require__(925) +const prerelease = (version, options) => { + const parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} +module.exports = prerelease + + +/***/ }), + +/***/ 293: +/***/ ((module) => { + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +const SEMVER_SPEC_VERSION = '2.0.0' + +const MAX_LENGTH = 256 +const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +const MAX_SAFE_COMPONENT_LENGTH = 16 + +module.exports = { + SEMVER_SPEC_VERSION, + MAX_LENGTH, + MAX_SAFE_INTEGER, + MAX_SAFE_COMPONENT_LENGTH +} + + +/***/ }), + +/***/ 427: +/***/ ((module) => { + +const debug = ( + typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG) +) ? (...args) => console.error('SEMVER', ...args) + : () => {} + +module.exports = debug + + +/***/ }), + +/***/ 463: +/***/ ((module) => { + +const numeric = /^[0-9]+$/ +const compareIdentifiers = (a, b) => { + const anum = numeric.test(a) + const bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) + +module.exports = { + compareIdentifiers, + rcompareIdentifiers +} + + +/***/ }), + +/***/ 785: +/***/ ((module) => { + +// parse out just the options we care about so we always get a consistent +// obj with keys in a consistent order. +const opts = ['includePrerelease', 'loose', 'rtl'] +const parseOptions = options => + !options ? {} + : typeof options !== 'object' ? { loose: true } + : opts.filter(k => options[k]).reduce((options, k) => { + options[k] = true + return options + }, {}) +module.exports = parseOptions + + +/***/ }), + +/***/ 523: +/***/ ((module, exports, __nccwpck_require__) => { + +const { MAX_SAFE_COMPONENT_LENGTH } = __nccwpck_require__(293) +const debug = __nccwpck_require__(427) +exports = module.exports = {} + +// The actual regexps go on exports.re +const re = exports.re = [] +const src = exports.src = [] +const t = exports.t = {} +let R = 0 + +const createToken = (name, value, isGlobal) => { + const index = R++ + debug(index, value) + t[name] = index + src[index] = value + re[index] = new RegExp(value, isGlobal ? 'g' : undefined) +} + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') +createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+') + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*') + +// ## Main Version +// Three dot-separated numeric identifiers. + +createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})`) + +createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})`) + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] +}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) + +createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] +}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+') + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] +}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +createToken('FULLPLAIN', `v?${src[t.MAINVERSION] +}${src[t.PRERELEASE]}?${ + src[t.BUILD]}?`) + +createToken('FULL', `^${src[t.FULLPLAIN]}$`) + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] +}${src[t.PRERELEASELOOSE]}?${ + src[t.BUILD]}?`) + +createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) + +createToken('GTLT', '((?:<|>)?=?)') + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) +createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) + +createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:${src[t.PRERELEASE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:${src[t.PRERELEASELOOSE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) +createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +createToken('COERCE', `${'(^|[^\\d])' + + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:$|[^\\d])`) +createToken('COERCERTL', src[t.COERCE], true) + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +createToken('LONETILDE', '(?:~>?)') + +createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) +exports.tildeTrimReplace = '$1~' + +createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) +createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +createToken('LONECARET', '(?:\\^)') + +createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) +exports.caretTrimReplace = '$1^' + +createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) +createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) +createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] +}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) +exports.comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAIN]})` + + `\\s*$`) + +createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAINLOOSE]})` + + `\\s*$`) + +// Star ranges basically just allow anything at all. +createToken('STAR', '(<|>)?=?\\s*\\*') +// >=0.0.0 is like a star +createToken('GTE0', '^\\s*>=\\s*0\.0\.0\\s*$') +createToken('GTE0PRE', '^\\s*>=\\s*0\.0\.0-0\\s*$') + + +/***/ }), + +/***/ 129: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process");; + +/***/ }), + +/***/ 747: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs");; + +/***/ }), + +/***/ 87: +/***/ ((module) => { + +"use strict"; +module.exports = require("os");; + +/***/ }), + +/***/ 622: +/***/ ((module) => { + +"use strict"; +module.exports = require("path");; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ if(__webpack_module_cache__[moduleId]) { +/******/ return __webpack_module_cache__[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ __nccwpck_require__.ab = __dirname + "/";/************************************************************************/ +/******/ // module exports must be returned from runtime so entry inlining is disabled +/******/ // startup +/******/ // Load entry module and return exports +/******/ return __nccwpck_require__(330); +/******/ })() +; diff --git a/.github/scripts/buildActions.sh b/.github/scripts/buildActions.sh index 79b80c0704c6..36d8790070c3 100755 --- a/.github/scripts/buildActions.sh +++ b/.github/scripts/buildActions.sh @@ -10,6 +10,7 @@ ACTIONS_DIR="$(dirname "$(dirname "$0")")/actions" # List of paths to all JS files that implement our GH Actions declare -r GITHUB_ACTIONS=( "$ACTIONS_DIR/bumpVersion/bumpVersion.js" + "$ACTIONS_DIR/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js" "$ACTIONS_DIR/checkDeployBlockers/checkDeployBlockers.js" "$ACTIONS_DIR/createOrUpdateStagingDeploy/createOrUpdateStagingDeploy.js" "$ACTIONS_DIR/getDeployPullRequestList/getDeployPullRequestList.js" diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 712d3304eb5a..9636f9351331 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -143,8 +143,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PULL_REQUEST_NUMBER: ${{ steps.createPullRequest.outputs.pr_number }} - - name: Auto-assign PR if there are merge conflicts - if: ${{ !fromJSON(steps.cherryPick.outputs.SHOULD_AUTOMERGE) || !fromJSON(steps.isPullRequestMergeable.outputs.IS_MERGEABLE) }} + - name: Check if ShortVersionString is up to date + id: isShortVersionStringUpdated + uses: Expensify/App/.github/actions/checkBundleVersionStringMatch@main + + - name: Auto-assign PR if there are merge conflicts or if the bundle versions are mismatched + if: ${{ !fromJSON(steps.cherryPick.outputs.SHOULD_AUTOMERGE) || !fromJSON(steps.isPullRequestMergeable.outputs.IS_MERGEABLE) || !fromJSON(steps.isShortVersionStringUpdated.outputs.BUNDLE_VERSIONS_MATCH) }} uses: actions-ecosystem/action-add-labels@a8ae047fee0ca28235f9764e1c478d2136dc15c1 with: number: ${{ steps.createPullRequest.outputs.pr_number }} @@ -171,6 +175,17 @@ jobs: Please manually resolve the conflicts, push your changes, and then request another reviewer to review and merge. **Important:** There may be conflicts that GitHub is not able to detect, so please _carefully_ review this pull request before approving. + - name: If PR has a bundle version mismatch, comment with the instructions for assignee + if: ${{ !fromJSON(steps.isShortVersionStringUpdated.outputs.BUNDLE_VERSIONS_MATCH) }} + uses: actions-ecosystem/action-create-comment@cd098164398331c50e7dfdd0dfa1b564a1873fac + with: + github_token: ${{ secrets.OS_BOTIFY_TOKEN }} + number: ${{ steps.createPullRequest.outputs.pr_number }} + body: | + The CFBundleShortVersionString value in this PR is not compatible with the CFBundleVersion, so cherry picking it will result in an iOS deploy failure. + Please manually resolve the mismatch, push your changes, and then request another reviewer to review and merge. + **Important:** This mismatch can be caused by a failed Update Protected Branch workflow followed by a manual CP, but please confirm the cause of the mismatch before updating any version numbers. + - name: Check for an auto approve # Important: only auto-approve if there was no merge conflict! if: ${{ fromJSON(steps.cherryPick.outputs.SHOULD_AUTOMERGE) && fromJSON(steps.isPullRequestMergeable.outputs.IS_MERGEABLE) }} From 25a7f3db1b844be52d601bb75f88a2c1b542abda Mon Sep 17 00:00:00 2001 From: Joe Gambino <joe@expensify.com> Date: Mon, 6 Dec 2021 19:21:28 -0800 Subject: [PATCH 2/6] use grep/sed --- .../checkBundleVersionStringMatch.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js index f601976a2f2a..47f5331759d9 100644 --- a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -2,12 +2,14 @@ const core = require('@actions/core'); const {execSync} = require('child_process'); const {PLIST_PATH} = require('../../libs/nativeVersionUpdater'); -const bundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" ${PLIST_PATH}`); -const shortBundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${PLIST_PATH}`); +const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g')`).toString().trim(); +const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g')`).toString().trim(); console.log(`Bundle Version: ${bundleVersion}`); console.log(`Short Bundle Version: ${shortBundleVersion}`); -if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { + +const hasValue = shortBundleVersion && bundleVersion; +if (!hasValue || (shortBundleVersion !== (bundleVersion.split('-') || [''])[0])) { console.log('Bundle Versions do not match'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } else { From d88a86d309d7a450380ee5eff497d748bf46ab5d Mon Sep 17 00:00:00 2001 From: Joe Gambino <joe@expensify.com> Date: Tue, 7 Dec 2021 15:59:39 -0800 Subject: [PATCH 3/6] build actions --- .../checkBundleVersionStringMatch.js | 5 ++++- .../actions/checkBundleVersionStringMatch/index.js | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js index 47f5331759d9..4a44df103758 100644 --- a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -9,7 +9,10 @@ console.log(`Bundle Version: ${bundleVersion}`); console.log(`Short Bundle Version: ${shortBundleVersion}`); const hasValue = shortBundleVersion && bundleVersion; -if (!hasValue || (shortBundleVersion !== (bundleVersion.split('-') || [''])[0])) { +if (!hasValue) { + console.log('Failed to get Bundle Versions from plist'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); +} else if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { console.log('Bundle Versions do not match'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } else { diff --git a/.github/actions/checkBundleVersionStringMatch/index.js b/.github/actions/checkBundleVersionStringMatch/index.js index 960ac54b3fbf..6bb879167a54 100644 --- a/.github/actions/checkBundleVersionStringMatch/index.js +++ b/.github/actions/checkBundleVersionStringMatch/index.js @@ -12,12 +12,17 @@ const core = __nccwpck_require__(186); const {execSync} = __nccwpck_require__(129); const {PLIST_PATH} = __nccwpck_require__(322); -const bundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" ${PLIST_PATH}`); -const shortBundleVersion = execSync(`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${PLIST_PATH}`); +const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g')`).toString().trim(); +const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g')`).toString().trim(); console.log(`Bundle Version: ${bundleVersion}`); console.log(`Short Bundle Version: ${shortBundleVersion}`); -if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { + +const hasValue = shortBundleVersion && bundleVersion; +if (!hasValue) { + console.log('Failed to get Bundle Versions from plist'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); +} else if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { console.log('Bundle Versions do not match'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } else { From 03b41f98717a0f6f90fe5550db983f9ca8e82d7d Mon Sep 17 00:00:00 2001 From: Joe Gambino <joe@expensify.com> Date: Wed, 8 Dec 2021 14:28:03 -0800 Subject: [PATCH 4/6] remove extra parens --- .../checkBundleVersionStringMatch.js | 4 ++-- .github/actions/checkBundleVersionStringMatch/index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js index 4a44df103758..0dc080d38922 100644 --- a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -2,8 +2,8 @@ const core = require('@actions/core'); const {execSync} = require('child_process'); const {PLIST_PATH} = require('../../libs/nativeVersionUpdater'); -const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g')`).toString().trim(); -const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g')`).toString().trim(); +const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g'`).toString().trim(); +const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g'`).toString().trim(); console.log(`Bundle Version: ${bundleVersion}`); console.log(`Short Bundle Version: ${shortBundleVersion}`); diff --git a/.github/actions/checkBundleVersionStringMatch/index.js b/.github/actions/checkBundleVersionStringMatch/index.js index 6bb879167a54..05ee8a465cc8 100644 --- a/.github/actions/checkBundleVersionStringMatch/index.js +++ b/.github/actions/checkBundleVersionStringMatch/index.js @@ -12,8 +12,8 @@ const core = __nccwpck_require__(186); const {execSync} = __nccwpck_require__(129); const {PLIST_PATH} = __nccwpck_require__(322); -const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g')`).toString().trim(); -const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g')`).toString().trim(); +const bundleVersion = execSync(`grep -A1 'CFBundleVersion' ${PLIST_PATH} | grep -v 'CFBundleVersion' | sed 's|[</string>,]||g'`).toString().trim(); +const shortBundleVersion = execSync(`grep -A1 'CFBundleShortVersionString' ${PLIST_PATH} | grep -v 'CFBundleShortVersionString' | sed 's|[</string>,]||g'`).toString().trim(); console.log(`Bundle Version: ${bundleVersion}`); console.log(`Short Bundle Version: ${shortBundleVersion}`); From 6bbd4cdfd461e0e9670aefc0cd1aa66679fbc9da Mon Sep 17 00:00:00 2001 From: Joe Gambino <joe@expensify.com> Date: Wed, 8 Dec 2021 16:01:18 -0800 Subject: [PATCH 5/6] fix grep logic --- .../checkBundleVersionStringMatch.js | 8 ++++---- .github/actions/checkBundleVersionStringMatch/index.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js index 0dc080d38922..c06c1a23c1cf 100644 --- a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -12,10 +12,10 @@ const hasValue = shortBundleVersion && bundleVersion; if (!hasValue) { console.log('Failed to get Bundle Versions from plist'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); -} else if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { - console.log('Bundle Versions do not match'); - core.setOutput('BUNDLE_VERSIONS_MATCH', false); -} else { +} else if (bundleVersion.includes(shortBundleVersion)) { console.log('Bundle Versions match'); core.setOutput('BUNDLE_VERSIONS_MATCH', true); +} else { + console.log('Bundle Versions do not match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); } diff --git a/.github/actions/checkBundleVersionStringMatch/index.js b/.github/actions/checkBundleVersionStringMatch/index.js index 05ee8a465cc8..c78acd53a96b 100644 --- a/.github/actions/checkBundleVersionStringMatch/index.js +++ b/.github/actions/checkBundleVersionStringMatch/index.js @@ -22,12 +22,12 @@ const hasValue = shortBundleVersion && bundleVersion; if (!hasValue) { console.log('Failed to get Bundle Versions from plist'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); -} else if (shortBundleVersion !== (bundleVersion.split('-') || [''])[0]) { - console.log('Bundle Versions do not match'); - core.setOutput('BUNDLE_VERSIONS_MATCH', false); -} else { +} else if (bundleVersion.includes(shortBundleVersion)) { console.log('Bundle Versions match'); core.setOutput('BUNDLE_VERSIONS_MATCH', true); +} else { + console.log('Bundle Versions do not match'); + core.setOutput('BUNDLE_VERSIONS_MATCH', false); } From c1da6e98db55fa4038e236a6e15b908b8237fc2a Mon Sep 17 00:00:00 2001 From: Joe Gambino <joe@expensify.com> Date: Wed, 8 Dec 2021 16:06:19 -0800 Subject: [PATCH 6/6] clearer logs --- .../checkBundleVersionStringMatch.js | 4 ++-- .github/actions/checkBundleVersionStringMatch/index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js index c06c1a23c1cf..68d42427481e 100644 --- a/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js +++ b/.github/actions/checkBundleVersionStringMatch/checkBundleVersionStringMatch.js @@ -13,9 +13,9 @@ if (!hasValue) { console.log('Failed to get Bundle Versions from plist'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } else if (bundleVersion.includes(shortBundleVersion)) { - console.log('Bundle Versions match'); + console.log('Bundle Versions are compatible'); core.setOutput('BUNDLE_VERSIONS_MATCH', true); } else { - console.log('Bundle Versions do not match'); + console.log('Bundle Versions are not compatible'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } diff --git a/.github/actions/checkBundleVersionStringMatch/index.js b/.github/actions/checkBundleVersionStringMatch/index.js index c78acd53a96b..bedf06208d4c 100644 --- a/.github/actions/checkBundleVersionStringMatch/index.js +++ b/.github/actions/checkBundleVersionStringMatch/index.js @@ -23,10 +23,10 @@ if (!hasValue) { console.log('Failed to get Bundle Versions from plist'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); } else if (bundleVersion.includes(shortBundleVersion)) { - console.log('Bundle Versions match'); + console.log('Bundle Versions are compatible'); core.setOutput('BUNDLE_VERSIONS_MATCH', true); } else { - console.log('Bundle Versions do not match'); + console.log('Bundle Versions are not compatible'); core.setOutput('BUNDLE_VERSIONS_MATCH', false); }