diff --git a/action.yml b/action.yml index de7702a..be280f2 100644 --- a/action.yml +++ b/action.yml @@ -17,3 +17,26 @@ inputs: description: "Indicates if the same workflow published a new release to npm, required for 'sync' action" version: description: "The current verison of the package. Required for 'release'" + working-directory: + description: "Subdirectory to operate in (for monorepos). Paths are relative to this directory." + default: "." + version-files: + description: "JSON array of package.json paths to update when creating release PRs. All files will be updated to the same version." + default: '["package.json"]' + publish-packages: + description: "JSON array of package paths to check for publishing. If not set, scans packages/* directory." + prerelease-type: + description: "Prerelease identifier to use (e.g., 'canary', 'beta')" + default: "canary" + base-branch: + description: "Base branch for PRs and releases" + default: "main" + max-changelog-commits: + description: "Maximum commits to scan for changelog generation (0 = unlimited)" + default: "100" + pr-title-prefix: + description: "Prefix for release PR titles (e.g., '[Embedded SDK]')" + default: "" + pr-labels: + description: "JSON array of additional labels to add to release PRs" + default: "[]" diff --git a/packages/action/out/174.index.js b/packages/action/out/174.index.js index c05bdd7..356b883 100644 --- a/packages/action/out/174.index.js +++ b/packages/action/out/174.index.js @@ -15,8 +15,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(semver_functions_inc__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7501); /* harmony import */ var _util_get_message__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(767); -/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1514); -/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8089); +/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1514); +/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8089); function _array_like_to_array(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; @@ -251,12 +251,12 @@ function _ts_generator(thisArg, body) { var runAction = function() { return _async_to_generator(function() { - var stale, staleCanary, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err, _ref, canaryPull, fullPull; + var stale, stalePrerelease, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err, _ref, prereleasePull, fullPull; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: stale = []; - staleCanary = []; + stalePrerelease = []; _iteratorAbruptCompletion = false, _didIteratorError = false; _state.label = 1; case 1: @@ -291,9 +291,13 @@ var runAction = function() { try { for(_iterator1 = pulls[Symbol.iterator](); !(_iteratorNormalCompletion = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion = true){ pull = _step1.value; - if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(pull.user)) { - if (_shared__WEBPACK_IMPORTED_MODULE_4__/* .fullReleaseTitle */ .o === pull.title) stale.push(pull); - else if (_shared__WEBPACK_IMPORTED_MODULE_4__/* .canaryReleaseTitle */ .G === pull.title) staleCanary.push(pull); + // Match by branch pattern instead of title (titles now include versions) + if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z)(pull.user) && pull.head.ref.startsWith('turbo-module/release-')) { + if (pull.head.ref.includes("-".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD))) { + stalePrerelease.push(pull); + } else { + stale.push(pull); + } } } } catch (err) { @@ -368,7 +372,7 @@ var runAction = function() { // close stale PRs and delete the branches return [ 4, - Promise.all(_to_consumable_array(stale).concat(_to_consumable_array(staleCanary)).map(function(stalePull) { + Promise.all(_to_consumable_array(stale).concat(_to_consumable_array(stalePrerelease)).map(function(stalePull) { return _async_to_generator(function() { return _ts_generator(this, function(_state) { switch(_state.label){ @@ -415,13 +419,13 @@ var runAction = function() { _ref = _sliced_to_array.apply(void 0, [ _state.sent(), 2 - ]), canaryPull = _ref[0], fullPull = _ref[1]; + ]), prereleasePull = _ref[0], fullPull = _ref[1]; // add comments to closed PRs that link to the newly created PRs return [ 4, Promise.all([ - Promise.all(staleCanary.map(function(pull) { - return addCommentToClosed(pull.number, canaryPull.number); + Promise.all(stalePrerelease.map(function(pull) { + return addCommentToClosed(pull.number, prereleasePull.number); })), Promise.all(stale.map(function(pull) { return addCommentToClosed(pull.number, fullPull.number); @@ -463,21 +467,22 @@ var addCommentToClosed = function(number, replacement) { var pull_labels = [ 'auto-release-pr', 'keep up-to-date' -]; +].concat(_to_consumable_array(_context__WEBPACK_IMPORTED_MODULE_1__/* .prLabels */ .Zh)); var createPull = function(prerelease) { return _async_to_generator(function() { - var title, releaseLabel, _ref, content, packageJson, newVersion, _ref1, _ref_data, sha, shortSha, branch, message, _ref2, pull, err, e; + var releaseLabel, primaryVersionFile, _ref, content, packageJson, newVersion, title, _ref1, _ref_data, sha, shortSha, branch, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, versionFile, filePath, _ref2, fileContent, filePackageJson, err, message, _ref3, pull, _$err, e; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: - title = prerelease ? _shared__WEBPACK_IMPORTED_MODULE_4__/* .canaryReleaseTitle */ .G : _shared__WEBPACK_IMPORTED_MODULE_4__/* .fullReleaseTitle */ .o; - releaseLabel = prerelease ? 'releases: canary' : 'releases: patch'; + releaseLabel = prerelease ? "releases: ".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : 'releases: patch'; + // Get the first version file to determine current version + primaryVersionFile = (0,_context__WEBPACK_IMPORTED_MODULE_1__/* .withWorkingDir */ .QV)(_context__WEBPACK_IMPORTED_MODULE_1__/* .versionFiles[0] */ .dm[0]); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.getContent */ .NR.rest.repos.getContent({ repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, - path: 'package.json' + path: primaryVersionFile }) ]; case 1: @@ -485,24 +490,24 @@ var createPull = function(prerelease) { if (!('content' in content)) throw new Error('Could not get package.json contents'); packageJson = JSON.parse(Buffer.from(content.content, 'base64').toString()); if (!packageJson.version || packageJson.version.startsWith('0.0.0')) { - newVersion = prerelease ? '0.0.1-canary.0' : '0.0.1'; + newVersion = prerelease ? "0.0.1-".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD, ".0") : '0.0.1'; } else { - newVersion = prerelease ? semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'prerelease', 'canary') : semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'patch'); + newVersion = prerelease ? semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'prerelease', _context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'patch'); } if (!newVersion) throw new Error('Could not increase version'); - packageJson.version = newVersion; + title = prerelease ? (0,_shared__WEBPACK_IMPORTED_MODULE_3__/* .getPrereleaseTitle */ .e)(newVersion) : (0,_shared__WEBPACK_IMPORTED_MODULE_3__/* .getFullReleaseTitle */ .n)(newVersion); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.git.getRef */ .NR.rest.git.getRef({ owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, - ref: "heads/main" + ref: "heads/".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .baseBranch */ .a2) }) ]; case 2: _ref1 = _state.sent(), _ref_data = _ref1.data, sha = _ref_data.object.sha; shortSha = sha.slice(0, 6) + sha.slice(-6); - branch = prerelease ? "turbo-module/release-".concat(shortSha, "-canary") : "turbo-module/release-".concat(shortSha); + branch = prerelease ? "turbo-module/release-".concat(shortSha, "-").concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : "turbo-module/release-".concat(shortSha); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.git.createRef */ .NR.rest.git.createRef({ @@ -514,25 +519,92 @@ var createPull = function(prerelease) { ]; case 3: _state.sent(); + _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; + _state.label = 4; + case 4: + _state.trys.push([ + 4, + 10, + 11, + 12 + ]); + _iterator = _context__WEBPACK_IMPORTED_MODULE_1__/* .versionFiles */ .dm[Symbol.iterator](); + _state.label = 5; + case 5: + if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [ + 3, + 9 + ]; + versionFile = _step.value; + filePath = (0,_context__WEBPACK_IMPORTED_MODULE_1__/* .withWorkingDir */ .QV)(versionFile); + console.log("Updating version in ".concat(filePath, " to ").concat(newVersion)); + return [ + 4, + _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.getContent */ .NR.rest.repos.getContent({ + repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, + owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, + path: filePath, + ref: branch + }) + ]; + case 6: + _ref2 = _state.sent(), fileContent = _ref2.data; + if (!('content' in fileContent)) throw new Error("Could not get ".concat(filePath, " contents")); + filePackageJson = JSON.parse(Buffer.from(fileContent.content, 'base64').toString()); + filePackageJson.version = newVersion; return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.createOrUpdateFileContents */ .NR.rest.repos.createOrUpdateFileContents({ repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, - path: 'package.json', - message: "release patch ".concat(packageJson.version), - content: Buffer.from(JSON.stringify(packageJson, null, 2) + '\n').toString('base64'), - sha: content.sha, + path: filePath, + message: "release: ".concat(newVersion), + content: Buffer.from(JSON.stringify(filePackageJson, null, 2) + '\n').toString('base64'), + sha: fileContent.sha, branch: branch }) ]; - case 4: + case 7: _state.sent(); + _state.label = 8; + case 8: + _iteratorNormalCompletion = true; + return [ + 3, + 5 + ]; + case 9: + return [ + 3, + 12 + ]; + case 10: + err = _state.sent(); + _didIteratorError = true; + _iteratorError = err; + return [ + 3, + 12 + ]; + case 11: + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally{ + if (_didIteratorError) { + throw _iteratorError; + } + } + return [ + 7 + ]; + case 12: return [ 4, (0,_util_get_message__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(prerelease) ]; - case 5: + case 13: message = _state.sent().message; return [ 4, @@ -542,25 +614,26 @@ var createPull = function(prerelease) { title: title, body: message, head: branch, - base: 'main' + base: _context__WEBPACK_IMPORTED_MODULE_1__/* .baseBranch */ .a2, + draft: true }) ]; - case 6: - _ref2 = _state.sent(), pull = _ref2.data; - err = 0; - _state.label = 7; - case 7: - if (!(err < 5)) return [ + case 14: + _ref3 = _state.sent(), pull = _ref3.data; + _$err = 0; + _state.label = 15; + case 15: + if (!(_$err < 5)) return [ 3, - 13 + 21 ]; - _state.label = 8; - case 8: + _state.label = 16; + case 16: _state.trys.push([ - 8, - 10, + 16, + 18, , - 12 + 20 ]); return [ 4, @@ -573,34 +646,34 @@ var createPull = function(prerelease) { ]) }) ]; - case 9: + case 17: _state.sent(); return [ 2, pull ]; - case 10: + case 18: e = _state.sent(); console.error(e); - err++; + _$err++; return [ 4, new Promise(function(resolve) { return setTimeout(resolve, 300); }) ]; - case 11: + case 19: _state.sent(); return [ 3, - 12 + 20 ]; - case 12: + case 20: return [ 3, - 7 + 15 ]; - case 13: + case 21: throw new Error('Could not add labels to PR'); } }); @@ -615,11 +688,23 @@ var createPull = function(prerelease) { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "G": () => (/* binding */ canaryReleaseTitle), -/* harmony export */ "o": () => (/* binding */ fullReleaseTitle) +/* harmony export */ "e": () => (/* binding */ getPrereleaseTitle), +/* harmony export */ "n": () => (/* binding */ getFullReleaseTitle) /* harmony export */ }); -var fullReleaseTitle = '(turbo-module): release next version'; -var canaryReleaseTitle = '(turbo-module): release next canary version'; +/* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7501); + +var formatTitle = function(releaseType, version) { + var prefix = _context__WEBPACK_IMPORTED_MODULE_0__/* .prTitlePrefix */ .hJ ? "".concat(_context__WEBPACK_IMPORTED_MODULE_0__/* .prTitlePrefix */ .hJ, " ") : ''; + var versionSuffix = version ? " v".concat(version) : ''; + return "".concat(prefix).concat(releaseType).concat(versionSuffix).trim(); +}; +var getFullReleaseTitle = function(version) { + return formatTitle('Stable Release', version); +}; +var getPrereleaseTitle = function(version) { + var releaseType = _context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType.charAt */ .kD.charAt(0).toUpperCase() + _context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType.slice */ .kD.slice(1); + return formatTitle("".concat(releaseType, " Release"), version); +}; /***/ }), @@ -631,11 +716,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); -/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1514); +/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1514); /* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7501); /* harmony import */ var _util_get_message__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(767); -/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8089); -/* harmony import */ var _create__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3607); +/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8089); +/* harmony import */ var _create__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3607); function _async_iterator(iterable) { var method, async, sync, retry = 2; for("undefined" != typeof Symbol && (async = Symbol.asyncIterator, sync = Symbol.iterator); retry--;){ @@ -849,10 +934,12 @@ var syncPull = function(pull, prerelease) { }; var runAction = function() { return _async_to_generator(function() { - var full, canary, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err; + var fullReleaseTitle, prereleaseTitle, full, prerelease, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: + fullReleaseTitle = (0,_shared__WEBPACK_IMPORTED_MODULE_2__/* .getFullReleaseTitle */ .n)(); + prereleaseTitle = (0,_shared__WEBPACK_IMPORTED_MODULE_2__/* .getPrereleaseTitle */ .e)(); _iteratorAbruptCompletion = false, _didIteratorError = false; _state.label = 1; case 1: @@ -887,21 +974,21 @@ var runAction = function() { try { for(_iterator1 = pulls[Symbol.iterator](); !(_iteratorNormalCompletion = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion = true){ pull = _step1.value; - if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(pull.user)) { + if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z)(pull.user)) { switch(pull.title){ - case _shared__WEBPACK_IMPORTED_MODULE_4__/* .fullReleaseTitle */ .o: + case fullReleaseTitle: { if (!full) full = syncPull(pull, false); break; } - case _shared__WEBPACK_IMPORTED_MODULE_4__/* .canaryReleaseTitle */ .G: + case prereleaseTitle: { - if (!canary) canary = syncPull(pull, true); + if (!prerelease) prerelease = syncPull(pull, true); break; } } } - if (full && canary) break; + if (full && prerelease) break; } } catch (err) { _didIteratorError1 = true; @@ -917,7 +1004,7 @@ var runAction = function() { } } } - if (full && canary) return [ + if (full && prerelease) return [ 3, 5 ]; @@ -976,13 +1063,13 @@ var runAction = function() { 7 ]; case 12: - if (!full) full = (0,_create__WEBPACK_IMPORTED_MODULE_2__.createPull)(false); - if (!canary) canary = (0,_create__WEBPACK_IMPORTED_MODULE_2__.createPull)(true); + if (!full) full = (0,_create__WEBPACK_IMPORTED_MODULE_3__.createPull)(false); + if (!prerelease) prerelease = (0,_create__WEBPACK_IMPORTED_MODULE_3__.createPull)(true); return [ 4, Promise.all([ full, - canary + prerelease ]) ]; case 13: diff --git a/packages/action/out/212.index.js b/packages/action/out/212.index.js index 767c4a4..37c8b36 100644 --- a/packages/action/out/212.index.js +++ b/packages/action/out/212.index.js @@ -554,6 +554,8 @@ var is_canary = __webpack_require__(9911); var semver = __webpack_require__(4122); // EXTERNAL MODULE: ./dist/util/get-file.js var get_file = __webpack_require__(2703); +// EXTERNAL MODULE: ./dist/context.js +var context = __webpack_require__(7501); ;// CONCATENATED MODULE: ./dist/check/index.js function check_array_like_to_array(arr, len) { if (len == null || len > arr.length) len = arr.length; @@ -753,7 +755,7 @@ function check_ts_generator(thisArg, body) { } function _templateObject() { var data = _tagged_template_literal([ - "\n npm view \n ", + "\n npm view\n ", "@", "\n " ]); @@ -777,10 +779,14 @@ function _templateObject1() { -var versionParserRegexp = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*@(\d+\.\d+\.\d+(?:-canary\.\d+)?)/; + +// Dynamic regex that supports the configured prerelease type +var createVersionParserRegexp = function() { + return new RegExp("^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*@(\\d+\\.\\d+\\.\\d+(?:-".concat(context/* prereleaseType */.kD, "\\.\\d+)?)")); +}; var checkPackage = function(pkg, rootVersion) { return check_async_to_generator(function() { - var _ref, packageJson, log, _ref1, res, _ref2, currentVersion, _e, unused; + var _ref, packageJson, log, _ref1, res, versionParserRegexp, _ref2, currentVersion, _e, unused; return check_ts_generator(this, function(_state) { switch(_state.label){ case 0: @@ -821,7 +827,7 @@ var checkPackage = function(pkg, rootVersion) { ]); return [ 4, - bash(_templateObject1(), command(_templateObject(), packageJson.name, (0,is_canary/* default */.Z)(rootVersion) ? 'canary' : 'latest')) + bash(_templateObject1(), command(_templateObject(), packageJson.name, (0,is_canary/* default */.Z)(rootVersion) ? context/* prereleaseType */.kD : 'latest')) ]; case 3: _ref1 = _sliced_to_array.apply(void 0, [ @@ -829,6 +835,7 @@ var checkPackage = function(pkg, rootVersion) { 1 ]), res = _ref1[0]; if (!res) throw new Error('Ăšnexpected error'); + versionParserRegexp = createVersionParserRegexp(); _ref2 = _sliced_to_array(versionParserRegexp.exec(res.stdout.trim()) || [], 3), currentVersion = _ref2[2]; if (!currentVersion) throw new Error('Could not parse version from npm view response'); if ((0,semver.gt)(rootVersion, currentVersion)) { @@ -871,15 +878,45 @@ var checkPackage = function(pkg, rootVersion) { }; var checkPackages = function(rootVersion) { return check_async_to_generator(function() { - var folders; + var packagesDir, folders; return check_ts_generator(this, function(_state) { switch(_state.label){ case 0: + if (!(context/* publishPackages */.RP && context/* publishPackages.length */.RP.length > 0)) return [ + 3, + 2 + ]; + console.log('checking configured packages: ' + context/* publishPackages.join */.RP.join(', ')); return [ 4, - (0,get_file/* getFolder */.zZ)('packages') + Promise.all(context/* publishPackages.map */.RP.map(function(pkgPath) { + return check_async_to_generator(function() { + var fullPath, jsonPath; + return check_ts_generator(this, function(_state) { + fullPath = (0,context/* withWorkingDir */.QV)(pkgPath); + // If path doesn't end with package.json, append it + jsonPath = fullPath.endsWith('package.json') ? fullPath : "".concat(fullPath, "/package.json"); + return [ + 2, + checkPackage(jsonPath, rootVersion) + ]; + }); + })(); + })) ]; case 1: + return [ + 2, + _state.sent().filter(Boolean) + ]; + case 2: + // Otherwise, scan packages/* directory (legacy behavior) + packagesDir = (0,context/* withWorkingDir */.QV)('packages'); + return [ + 4, + (0,get_file/* getFolder */.zZ)(packagesDir) + ]; + case 3: folders = _state.sent(); console.log('checking ' + folders.map(function(param) { var path = param.path; @@ -899,7 +936,7 @@ var checkPackages = function(rootVersion) { })(); })) ]; - case 2: + case 4: return [ 2, _state.sent().filter(Boolean) @@ -916,17 +953,19 @@ var checkPackages = function(rootVersion) { * inteded to be ran as part of a workflow */ var canPublish = function() { return check_async_to_generator(function() { - var _ref, version, publishable; + var versionFilePath, _ref, version, publishable; return check_ts_generator(this, function(_state) { switch(_state.label){ case 0: + // Use the first version file as the source of truth for the version + versionFilePath = (0,context/* withWorkingDir */.QV)(context/* versionFiles.0 */.dm[0]); return [ 4, - (0,get_file/* getJsonFile */.n0)('package.json') + (0,get_file/* getJsonFile */.n0)(versionFilePath) ]; case 1: _ref = _state.sent(), version = _ref.content.version; - console.log('version:', version, 'is canary:', (0,is_canary/* default */.Z)(version)); + console.log('version:', version, "is ".concat(context/* prereleaseType */.kD, ":"), (0,is_canary/* default */.Z)(version)); if (!version.startsWith('0.0.0')) return [ 3, 2 @@ -970,9 +1009,18 @@ var checkPackages = function(rootVersion) { /* harmony export */ "NR": () => (/* binding */ octo), /* harmony export */ "O9": () => (/* binding */ repo), /* harmony export */ "PX": () => (/* binding */ target_issue), +/* harmony export */ "QV": () => (/* binding */ withWorkingDir), /* harmony export */ "RL": () => (/* binding */ target_comment), +/* harmony export */ "RP": () => (/* binding */ publishPackages), +/* harmony export */ "Tf": () => (/* binding */ workingDirectory), +/* harmony export */ "Zh": () => (/* binding */ prLabels), +/* harmony export */ "a2": () => (/* binding */ baseBranch), /* harmony export */ "cR": () => (/* binding */ owner), +/* harmony export */ "dm": () => (/* binding */ versionFiles), +/* harmony export */ "hJ": () => (/* binding */ prTitlePrefix), /* harmony export */ "hl": () => (/* binding */ commit_hash), +/* harmony export */ "kD": () => (/* binding */ prereleaseType), +/* harmony export */ "pE": () => (/* binding */ maxChangelogCommits), /* harmony export */ "sS": () => (/* binding */ initial_commit) /* harmony export */ }); /* unused harmony export target_pull */ @@ -989,6 +1037,20 @@ var octo = (0,_actions_github__WEBPACK_IMPORTED_MODULE_1__.getOctokit)(GITHUB_TO var _context_repo = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.repo, _context_payload = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.payload; var owner = _context_repo.owner, repo = _context_repo.repo, commit_hash = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.sha, target_issue = _context_payload.issue, target_comment = _context_payload.comment, target_pull = _context_payload.pull_request; var initial_commit = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('initial-commit'); +// Monorepo support configuration +var workingDirectory = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('working-directory') || '.'; +var versionFiles = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('version-files') || '["package.json"]'); +var publishPackages = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages') ? JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages')) : undefined; +var prereleaseType = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('prerelease-type') || 'canary'; +var baseBranch = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('base-branch') || 'main'; +var maxChangelogCommits = parseInt((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('max-changelog-commits') || '100', 10); +var prTitlePrefix = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-title-prefix') || ''; +var prLabels = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-labels') || '[]'); +// Helper to join working directory with a path +var withWorkingDir = function(path) { + if (workingDirectory === '.') return path; + return "".concat(workingDirectory, "/").concat(path); +}; /***/ }), @@ -1228,12 +1290,20 @@ var getJsonFile = function(path, ref) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); -var isCanary = function(test) { - return /^\d+\.\d+\.\d+-canary\.\d+$/.test(test); +/* unused harmony export isPrerelease */ +/* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7501); + +// Check if version matches the configured prerelease type (e.g., canary, beta) +var isPrerelease = function(test) { + var pattern = new RegExp("^\\d+\\.\\d+\\.\\d+-".concat(_context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType */ .kD, "\\.\\d+$")); + return pattern.test(test); }; +// Legacy export for backwards compatibility +var isCanary = isPrerelease; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isCanary); + /***/ }) }; diff --git a/packages/action/out/587.index.js b/packages/action/out/587.index.js index 2bbc620..704e34a 100644 --- a/packages/action/out/587.index.js +++ b/packages/action/out/587.index.js @@ -10,9 +10,18 @@ exports.modules = { /* harmony export */ "NR": () => (/* binding */ octo), /* harmony export */ "O9": () => (/* binding */ repo), /* harmony export */ "PX": () => (/* binding */ target_issue), +/* harmony export */ "QV": () => (/* binding */ withWorkingDir), /* harmony export */ "RL": () => (/* binding */ target_comment), +/* harmony export */ "RP": () => (/* binding */ publishPackages), +/* harmony export */ "Tf": () => (/* binding */ workingDirectory), +/* harmony export */ "Zh": () => (/* binding */ prLabels), +/* harmony export */ "a2": () => (/* binding */ baseBranch), /* harmony export */ "cR": () => (/* binding */ owner), +/* harmony export */ "dm": () => (/* binding */ versionFiles), +/* harmony export */ "hJ": () => (/* binding */ prTitlePrefix), /* harmony export */ "hl": () => (/* binding */ commit_hash), +/* harmony export */ "kD": () => (/* binding */ prereleaseType), +/* harmony export */ "pE": () => (/* binding */ maxChangelogCommits), /* harmony export */ "sS": () => (/* binding */ initial_commit) /* harmony export */ }); /* unused harmony export target_pull */ @@ -29,6 +38,20 @@ var octo = (0,_actions_github__WEBPACK_IMPORTED_MODULE_1__.getOctokit)(GITHUB_TO var _context_repo = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.repo, _context_payload = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.payload; var owner = _context_repo.owner, repo = _context_repo.repo, commit_hash = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.sha, target_issue = _context_payload.issue, target_comment = _context_payload.comment, target_pull = _context_payload.pull_request; var initial_commit = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('initial-commit'); +// Monorepo support configuration +var workingDirectory = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('working-directory') || '.'; +var versionFiles = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('version-files') || '["package.json"]'); +var publishPackages = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages') ? JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages')) : undefined; +var prereleaseType = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('prerelease-type') || 'canary'; +var baseBranch = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('base-branch') || 'main'; +var maxChangelogCommits = parseInt((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('max-changelog-commits') || '100', 10); +var prTitlePrefix = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-title-prefix') || ''; +var prLabels = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-labels') || '[]'); +// Helper to join working directory with a path +var withWorkingDir = function(path) { + if (workingDirectory === '.') return path; + return "".concat(workingDirectory, "/").concat(path); +}; /***/ }), @@ -462,7 +485,7 @@ var types = [ 'minor', 'major' ]; -var getPackageJson = function(ref) { +var getPackageJson = function(path, ref) { return type_async_to_generator(function() { var _ref, content; return type_ts_generator(this, function(_state) { @@ -473,7 +496,7 @@ var getPackageJson = function(ref) { context/* octo.rest.repos.getContent */.NR.rest.repos.getContent({ repo: context/* repo */.O9, owner: context/* owner */.cR, - path: 'package.json', + path: path, ref: ref }) ]; @@ -488,14 +511,14 @@ var getPackageJson = function(ref) { } ]; } - throw new Error('Could not load main package.json'); + throw new Error("Could not load ".concat(path)); } }); })(); }; var performUpdate = function(type) { return type_async_to_generator(function() { - var _ref, _ref_data, labels, _ref_data_head, branch, releaseTypeLabel, current_type, _ref1, mainPackageJson, _ref2, currentPackageJson, packageSha, currentVersion, newVersion, promises; + var _ref, _ref_data, labels, _ref_data_head, branch, releaseTypeLabel, current_type, primaryVersionFile, _ref1, mainPackageJson, currentVersion, newVersion, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, versionFile, filePath, _ref2, currentPackageJson, packageSha, err, promises; return type_ts_generator(this, function(_state) { switch(_state.label){ case 0: @@ -510,36 +533,52 @@ var performUpdate = function(type) { ]; case 1: _ref = _state.sent(), _ref_data = _ref.data, labels = _ref_data.labels, _ref_data_head = _ref_data.head, branch = _ref_data_head.ref; - /* await octo.rest.pulls.updateBranch({ - repo, - owner, - pull_number: target_issue.number, - }); */ releaseTypeLabel = labels.find(function(param) { + releaseTypeLabel = labels.find(function(param) { var name = param.name; return name.startsWith('releases: '); }); current_type = releaseTypeLabel === null || releaseTypeLabel === void 0 ? void 0 : releaseTypeLabel.name.replace('releases: ', ''); - if (current_type === 'canary' || type === current_type) return [ + // Skip if it's a prerelease PR or already the requested type + if (current_type === context/* prereleaseType */.kD || type === current_type) return [ 2 ]; + primaryVersionFile = (0,context/* withWorkingDir */.QV)(context/* versionFiles.0 */.dm[0]); return [ 4, - getPackageJson('main') + getPackageJson(primaryVersionFile, context/* baseBranch */.a2) ]; case 2: _ref1 = _state.sent(), mainPackageJson = _ref1.content; + currentVersion = mainPackageJson.version.startsWith('0.0.0') ? '0.0.0' : mainPackageJson.version; + newVersion = (0,semver.inc)(currentVersion, type); + if (!newVersion) throw new Error("Could not increase ".concat(type, " for ").concat(currentVersion)); + _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; + _state.label = 3; + case 3: + _state.trys.push([ + 3, + 9, + 10, + 11 + ]); + _iterator = context/* versionFiles */.dm[Symbol.iterator](); + _state.label = 4; + case 4: + if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [ + 3, + 8 + ]; + versionFile = _step.value; + filePath = (0,context/* withWorkingDir */.QV)(versionFile); return [ 4, - getPackageJson(branch) + getPackageJson(filePath, branch) ]; - case 3: + case 5: _ref2 = _state.sent(), currentPackageJson = _ref2.content, packageSha = _ref2.sha; - currentVersion = mainPackageJson.version.startsWith('0.0.0') ? '0.0.0' : mainPackageJson.version; - newVersion = (0,semver.inc)(currentVersion, type); - if (!newVersion) throw new Error("Could not increase ".concat(type, " for ").concat(currentVersion)); if (!(currentPackageJson.version !== newVersion)) return [ 3, - 5 + 7 ]; currentPackageJson.version = newVersion; return [ @@ -547,17 +586,49 @@ var performUpdate = function(type) { context/* octo.rest.repos.createOrUpdateFileContents */.NR.rest.repos.createOrUpdateFileContents({ repo: context/* repo */.O9, owner: context/* owner */.cR, - path: 'package.json', + path: filePath, message: "release ".concat(type, " ").concat(newVersion), content: Buffer.from(JSON.stringify(currentPackageJson, null, 2) + '\n').toString('base64'), sha: packageSha, branch: branch }) ]; - case 4: + case 6: _state.sent(); - _state.label = 5; - case 5: + _state.label = 7; + case 7: + _iteratorNormalCompletion = true; + return [ + 3, + 4 + ]; + case 8: + return [ + 3, + 11 + ]; + case 9: + err = _state.sent(); + _didIteratorError = true; + _iteratorError = err; + return [ + 3, + 11 + ]; + case 10: + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally{ + if (_didIteratorError) { + throw _iteratorError; + } + } + return [ + 7 + ]; + case 11: promises = [ context/* octo.rest.issues.addLabels */.NR.rest.issues.addLabels({ repo: context/* repo */.O9, @@ -578,7 +649,7 @@ var performUpdate = function(type) { 4, Promise.all(promises) ]; - case 6: + case 12: _state.sent(); return [ 2 diff --git a/packages/action/out/607.index.js b/packages/action/out/607.index.js index 5e0441f..49dc9f9 100644 --- a/packages/action/out/607.index.js +++ b/packages/action/out/607.index.js @@ -15,8 +15,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(semver_functions_inc__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7501); /* harmony import */ var _util_get_message__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(767); -/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1514); -/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8089); +/* harmony import */ var _util_is_action_user__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1514); +/* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8089); function _array_like_to_array(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; @@ -251,12 +251,12 @@ function _ts_generator(thisArg, body) { var runAction = function() { return _async_to_generator(function() { - var stale, staleCanary, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err, _ref, canaryPull, fullPull; + var stale, stalePrerelease, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, pulls, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, pull, err, _ref, prereleasePull, fullPull; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: stale = []; - staleCanary = []; + stalePrerelease = []; _iteratorAbruptCompletion = false, _didIteratorError = false; _state.label = 1; case 1: @@ -291,9 +291,13 @@ var runAction = function() { try { for(_iterator1 = pulls[Symbol.iterator](); !(_iteratorNormalCompletion = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion = true){ pull = _step1.value; - if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(pull.user)) { - if (_shared__WEBPACK_IMPORTED_MODULE_4__/* .fullReleaseTitle */ .o === pull.title) stale.push(pull); - else if (_shared__WEBPACK_IMPORTED_MODULE_4__/* .canaryReleaseTitle */ .G === pull.title) staleCanary.push(pull); + // Match by branch pattern instead of title (titles now include versions) + if ((0,_util_is_action_user__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z)(pull.user) && pull.head.ref.startsWith('turbo-module/release-')) { + if (pull.head.ref.includes("-".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD))) { + stalePrerelease.push(pull); + } else { + stale.push(pull); + } } } } catch (err) { @@ -368,7 +372,7 @@ var runAction = function() { // close stale PRs and delete the branches return [ 4, - Promise.all(_to_consumable_array(stale).concat(_to_consumable_array(staleCanary)).map(function(stalePull) { + Promise.all(_to_consumable_array(stale).concat(_to_consumable_array(stalePrerelease)).map(function(stalePull) { return _async_to_generator(function() { return _ts_generator(this, function(_state) { switch(_state.label){ @@ -415,13 +419,13 @@ var runAction = function() { _ref = _sliced_to_array.apply(void 0, [ _state.sent(), 2 - ]), canaryPull = _ref[0], fullPull = _ref[1]; + ]), prereleasePull = _ref[0], fullPull = _ref[1]; // add comments to closed PRs that link to the newly created PRs return [ 4, Promise.all([ - Promise.all(staleCanary.map(function(pull) { - return addCommentToClosed(pull.number, canaryPull.number); + Promise.all(stalePrerelease.map(function(pull) { + return addCommentToClosed(pull.number, prereleasePull.number); })), Promise.all(stale.map(function(pull) { return addCommentToClosed(pull.number, fullPull.number); @@ -463,21 +467,22 @@ var addCommentToClosed = function(number, replacement) { var pull_labels = [ 'auto-release-pr', 'keep up-to-date' -]; +].concat(_to_consumable_array(_context__WEBPACK_IMPORTED_MODULE_1__/* .prLabels */ .Zh)); var createPull = function(prerelease) { return _async_to_generator(function() { - var title, releaseLabel, _ref, content, packageJson, newVersion, _ref1, _ref_data, sha, shortSha, branch, message, _ref2, pull, err, e; + var releaseLabel, primaryVersionFile, _ref, content, packageJson, newVersion, title, _ref1, _ref_data, sha, shortSha, branch, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, versionFile, filePath, _ref2, fileContent, filePackageJson, err, message, _ref3, pull, _$err, e; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: - title = prerelease ? _shared__WEBPACK_IMPORTED_MODULE_4__/* .canaryReleaseTitle */ .G : _shared__WEBPACK_IMPORTED_MODULE_4__/* .fullReleaseTitle */ .o; - releaseLabel = prerelease ? 'releases: canary' : 'releases: patch'; + releaseLabel = prerelease ? "releases: ".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : 'releases: patch'; + // Get the first version file to determine current version + primaryVersionFile = (0,_context__WEBPACK_IMPORTED_MODULE_1__/* .withWorkingDir */ .QV)(_context__WEBPACK_IMPORTED_MODULE_1__/* .versionFiles[0] */ .dm[0]); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.getContent */ .NR.rest.repos.getContent({ repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, - path: 'package.json' + path: primaryVersionFile }) ]; case 1: @@ -485,24 +490,24 @@ var createPull = function(prerelease) { if (!('content' in content)) throw new Error('Could not get package.json contents'); packageJson = JSON.parse(Buffer.from(content.content, 'base64').toString()); if (!packageJson.version || packageJson.version.startsWith('0.0.0')) { - newVersion = prerelease ? '0.0.1-canary.0' : '0.0.1'; + newVersion = prerelease ? "0.0.1-".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD, ".0") : '0.0.1'; } else { - newVersion = prerelease ? semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'prerelease', 'canary') : semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'patch'); + newVersion = prerelease ? semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'prerelease', _context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : semver_functions_inc__WEBPACK_IMPORTED_MODULE_0___default()(packageJson.version, 'patch'); } if (!newVersion) throw new Error('Could not increase version'); - packageJson.version = newVersion; + title = prerelease ? (0,_shared__WEBPACK_IMPORTED_MODULE_3__/* .getPrereleaseTitle */ .e)(newVersion) : (0,_shared__WEBPACK_IMPORTED_MODULE_3__/* .getFullReleaseTitle */ .n)(newVersion); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.git.getRef */ .NR.rest.git.getRef({ owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, - ref: "heads/main" + ref: "heads/".concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .baseBranch */ .a2) }) ]; case 2: _ref1 = _state.sent(), _ref_data = _ref1.data, sha = _ref_data.object.sha; shortSha = sha.slice(0, 6) + sha.slice(-6); - branch = prerelease ? "turbo-module/release-".concat(shortSha, "-canary") : "turbo-module/release-".concat(shortSha); + branch = prerelease ? "turbo-module/release-".concat(shortSha, "-").concat(_context__WEBPACK_IMPORTED_MODULE_1__/* .prereleaseType */ .kD) : "turbo-module/release-".concat(shortSha); return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.git.createRef */ .NR.rest.git.createRef({ @@ -514,25 +519,92 @@ var createPull = function(prerelease) { ]; case 3: _state.sent(); + _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; + _state.label = 4; + case 4: + _state.trys.push([ + 4, + 10, + 11, + 12 + ]); + _iterator = _context__WEBPACK_IMPORTED_MODULE_1__/* .versionFiles */ .dm[Symbol.iterator](); + _state.label = 5; + case 5: + if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [ + 3, + 9 + ]; + versionFile = _step.value; + filePath = (0,_context__WEBPACK_IMPORTED_MODULE_1__/* .withWorkingDir */ .QV)(versionFile); + console.log("Updating version in ".concat(filePath, " to ").concat(newVersion)); + return [ + 4, + _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.getContent */ .NR.rest.repos.getContent({ + repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, + owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, + path: filePath, + ref: branch + }) + ]; + case 6: + _ref2 = _state.sent(), fileContent = _ref2.data; + if (!('content' in fileContent)) throw new Error("Could not get ".concat(filePath, " contents")); + filePackageJson = JSON.parse(Buffer.from(fileContent.content, 'base64').toString()); + filePackageJson.version = newVersion; return [ 4, _context__WEBPACK_IMPORTED_MODULE_1__/* .octo.rest.repos.createOrUpdateFileContents */ .NR.rest.repos.createOrUpdateFileContents({ repo: _context__WEBPACK_IMPORTED_MODULE_1__/* .repo */ .O9, owner: _context__WEBPACK_IMPORTED_MODULE_1__/* .owner */ .cR, - path: 'package.json', - message: "release patch ".concat(packageJson.version), - content: Buffer.from(JSON.stringify(packageJson, null, 2) + '\n').toString('base64'), - sha: content.sha, + path: filePath, + message: "release: ".concat(newVersion), + content: Buffer.from(JSON.stringify(filePackageJson, null, 2) + '\n').toString('base64'), + sha: fileContent.sha, branch: branch }) ]; - case 4: + case 7: _state.sent(); + _state.label = 8; + case 8: + _iteratorNormalCompletion = true; + return [ + 3, + 5 + ]; + case 9: + return [ + 3, + 12 + ]; + case 10: + err = _state.sent(); + _didIteratorError = true; + _iteratorError = err; + return [ + 3, + 12 + ]; + case 11: + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally{ + if (_didIteratorError) { + throw _iteratorError; + } + } + return [ + 7 + ]; + case 12: return [ 4, (0,_util_get_message__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(prerelease) ]; - case 5: + case 13: message = _state.sent().message; return [ 4, @@ -542,25 +614,26 @@ var createPull = function(prerelease) { title: title, body: message, head: branch, - base: 'main' + base: _context__WEBPACK_IMPORTED_MODULE_1__/* .baseBranch */ .a2, + draft: true }) ]; - case 6: - _ref2 = _state.sent(), pull = _ref2.data; - err = 0; - _state.label = 7; - case 7: - if (!(err < 5)) return [ + case 14: + _ref3 = _state.sent(), pull = _ref3.data; + _$err = 0; + _state.label = 15; + case 15: + if (!(_$err < 5)) return [ 3, - 13 + 21 ]; - _state.label = 8; - case 8: + _state.label = 16; + case 16: _state.trys.push([ - 8, - 10, + 16, + 18, , - 12 + 20 ]); return [ 4, @@ -573,34 +646,34 @@ var createPull = function(prerelease) { ]) }) ]; - case 9: + case 17: _state.sent(); return [ 2, pull ]; - case 10: + case 18: e = _state.sent(); console.error(e); - err++; + _$err++; return [ 4, new Promise(function(resolve) { return setTimeout(resolve, 300); }) ]; - case 11: + case 19: _state.sent(); return [ 3, - 12 + 20 ]; - case 12: + case 20: return [ 3, - 7 + 15 ]; - case 13: + case 21: throw new Error('Could not add labels to PR'); } }); @@ -615,11 +688,23 @@ var createPull = function(prerelease) { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "G": () => (/* binding */ canaryReleaseTitle), -/* harmony export */ "o": () => (/* binding */ fullReleaseTitle) +/* harmony export */ "e": () => (/* binding */ getPrereleaseTitle), +/* harmony export */ "n": () => (/* binding */ getFullReleaseTitle) /* harmony export */ }); -var fullReleaseTitle = '(turbo-module): release next version'; -var canaryReleaseTitle = '(turbo-module): release next canary version'; +/* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7501); + +var formatTitle = function(releaseType, version) { + var prefix = _context__WEBPACK_IMPORTED_MODULE_0__/* .prTitlePrefix */ .hJ ? "".concat(_context__WEBPACK_IMPORTED_MODULE_0__/* .prTitlePrefix */ .hJ, " ") : ''; + var versionSuffix = version ? " v".concat(version) : ''; + return "".concat(prefix).concat(releaseType).concat(versionSuffix).trim(); +}; +var getFullReleaseTitle = function(version) { + return formatTitle('Stable Release', version); +}; +var getPrereleaseTitle = function(version) { + var releaseType = _context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType.charAt */ .kD.charAt(0).toUpperCase() + _context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType.slice */ .kD.slice(1); + return formatTitle("".concat(releaseType, " Release"), version); +}; /***/ }) diff --git a/packages/action/out/767.index.js b/packages/action/out/767.index.js index aadb4ff..75ebff9 100644 --- a/packages/action/out/767.index.js +++ b/packages/action/out/767.index.js @@ -10,9 +10,18 @@ exports.modules = { /* harmony export */ "NR": () => (/* binding */ octo), /* harmony export */ "O9": () => (/* binding */ repo), /* harmony export */ "PX": () => (/* binding */ target_issue), +/* harmony export */ "QV": () => (/* binding */ withWorkingDir), /* harmony export */ "RL": () => (/* binding */ target_comment), +/* harmony export */ "RP": () => (/* binding */ publishPackages), +/* harmony export */ "Tf": () => (/* binding */ workingDirectory), +/* harmony export */ "Zh": () => (/* binding */ prLabels), +/* harmony export */ "a2": () => (/* binding */ baseBranch), /* harmony export */ "cR": () => (/* binding */ owner), +/* harmony export */ "dm": () => (/* binding */ versionFiles), +/* harmony export */ "hJ": () => (/* binding */ prTitlePrefix), /* harmony export */ "hl": () => (/* binding */ commit_hash), +/* harmony export */ "kD": () => (/* binding */ prereleaseType), +/* harmony export */ "pE": () => (/* binding */ maxChangelogCommits), /* harmony export */ "sS": () => (/* binding */ initial_commit) /* harmony export */ }); /* unused harmony export target_pull */ @@ -29,6 +38,20 @@ var octo = (0,_actions_github__WEBPACK_IMPORTED_MODULE_1__.getOctokit)(GITHUB_TO var _context_repo = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.repo, _context_payload = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.payload; var owner = _context_repo.owner, repo = _context_repo.repo, commit_hash = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.sha, target_issue = _context_payload.issue, target_comment = _context_payload.comment, target_pull = _context_payload.pull_request; var initial_commit = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('initial-commit'); +// Monorepo support configuration +var workingDirectory = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('working-directory') || '.'; +var versionFiles = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('version-files') || '["package.json"]'); +var publishPackages = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages') ? JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('publish-packages')) : undefined; +var prereleaseType = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('prerelease-type') || 'canary'; +var baseBranch = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('base-branch') || 'main'; +var maxChangelogCommits = parseInt((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('max-changelog-commits') || '100', 10); +var prTitlePrefix = (0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-title-prefix') || ''; +var prLabels = JSON.parse((0,_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput)('pr-labels') || '[]'); +// Helper to join working directory with a path +var withWorkingDir = function(path) { + if (workingDirectory === '.') return path; + return "".concat(workingDirectory, "/").concat(path); +}; /***/ }), @@ -119,6 +142,34 @@ function _async_to_generator(fn) { }); }; } +function _define_property(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; +} +function _object_spread(target) { + for(var i = 1; i < arguments.length; i++){ + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + if (typeof Object.getOwnPropertySymbols === "function") { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + ownKeys.forEach(function(key) { + _define_property(target, key, source[key]); + }); + } + return target; +} function _ts_generator(thisArg, body) { var f, y, t, _ = { label: 0, @@ -229,7 +280,7 @@ var addPull = function(pulls, type, number, title) { }; var collectCommits = function(head, base) { return _async_to_generator(function() { - var stats, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, commits, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, commit, _exec, _commit_author, message, PR, pull_number, _ref, pr, areas, _iteratorNormalCompletion1, _didIteratorError2, _iteratorError2, _iterator2, _step2, area, err, err1; + var stats, commitCount, listOptions, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, commits, _iteratorNormalCompletion, _didIteratorError1, _iteratorError1, _iterator1, _step1, commit, _exec, _commit_author, message, PR, pull_number, _ref, pr, areas, _iteratorNormalCompletion1, _didIteratorError2, _iteratorError2, _iterator2, _step2, area, e, err, err1; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: @@ -237,22 +288,27 @@ var collectCommits = function(head, base) { authors: new Set(), pulls: {} }; + commitCount = 0; + // Use listCommits with path filter for efficiency (only fetches commits touching working dir) + // This is much faster than comparing all commits and checking each one individually + listOptions = _object_spread({ + owner: context/* owner */.cR, + repo: context/* repo */.O9, + sha: head, + per_page: 100 + }, context/* workingDirectory */.Tf !== '.' && { + path: context/* workingDirectory */.Tf + }); _iteratorAbruptCompletion = false, _didIteratorError = false; _state.label = 1; case 1: _state.trys.push([ 1, - 13, - 14, - 19 + 15, + 16, + 21 ]); - _iterator = _async_iterator(context/* octo.paginate.iterator */.NR.paginate.iterator(context/* octo.rest.repos.compareCommits */.NR.rest.repos.compareCommits, { - owner: context/* owner */.cR, - repo: context/* repo */.O9, - base: base, - head: head, - per_page: 100 - })); + _iterator = _async_iterator(context/* octo.paginate.iterator */.NR.paginate.iterator(context/* octo.rest.repos.listCommits */.NR.rest.repos.listCommits, listOptions)); _state.label = 2; case 2: return [ @@ -262,45 +318,69 @@ var collectCommits = function(head, base) { case 3: if (!(_iteratorAbruptCompletion = !(_step = _state.sent()).done)) return [ 3, - 12 + 14 ]; _value = _step.value; - commits = _value.data.commits; + commits = _value.data; _iteratorNormalCompletion = true, _didIteratorError1 = false, _iteratorError1 = undefined; _state.label = 4; case 4: _state.trys.push([ 4, - 9, - 10, - 11 + 11, + 12, + 13 ]); _iterator1 = commits[Symbol.iterator](); _state.label = 5; case 5: if (!!(_iteratorNormalCompletion = (_step1 = _iterator1.next()).done)) return [ 3, - 8 + 10 ]; commit = _step1.value; + // Stop when we reach the base commit + if (commit.sha === base || commit.sha.startsWith(base) || base.startsWith(commit.sha)) { + console.log("Reached base commit ".concat(base, ", stopping changelog scan")); + return [ + 2, + stats + ]; + } + if (context/* maxChangelogCommits */.pE > 0 && commitCount >= context/* maxChangelogCommits */.pE) { + console.log("Reached max commit limit (".concat(context/* maxChangelogCommits */.pE, "), stopping changelog scan")); + return [ + 2, + stats + ]; + } + commitCount++; message = commit.commit.message.split('\n')[0]; PR = (_exec = /\(#(\d+)\)$/.exec(message)) === null || _exec === void 0 ? void 0 : _exec[1]; if (!PR) return [ 3, - 7 + 9 ]; pull_number = parseInt(PR); if ((_commit_author = commit.author) === null || _commit_author === void 0 ? void 0 : _commit_author.login) { if ((0,is_action_user/* default */.Z)(commit.author) && message.startsWith('release ')) return [ 3, - 7 + 9 ]; if (message.startsWith('(turbo-module): ')) return [ 3, - 7 + 9 ]; stats.authors.add(commit.author.login); } + _state.label = 6; + case 6: + _state.trys.push([ + 6, + 8, + , + 9 + ]); return [ 4, context/* octo.rest.pulls.get */.NR.rest.pulls.get({ @@ -309,7 +389,7 @@ var collectCommits = function(head, base) { pull_number: pull_number }) ]; - case 6: + case 7: _ref = _state.sent(), pr = _ref.data; areas = pr.labels.filter(function(param) { var name = param.name; @@ -340,27 +420,39 @@ var collectCommits = function(head, base) { } } } - _state.label = 7; - case 7: - _iteratorNormalCompletion = true; return [ 3, - 5 + 9 ]; case 8: + e = _state.sent(); + // PR might not exist in this repo (e.g., monorepo with commits from other repos) + console.log("Skipping PR #".concat(pull_number, " - not found in this repo")); + addPull(stats.pulls, 'general', pull_number, message); return [ 3, - 11 + 9 ]; case 9: + _iteratorNormalCompletion = true; + return [ + 3, + 5 + ]; + case 10: + return [ + 3, + 13 + ]; + case 11: err = _state.sent(); _didIteratorError1 = true; _iteratorError1 = err; return [ 3, - 11 + 13 ]; - case 10: + case 12: try { if (!_iteratorNormalCompletion && _iterator1.return != null) { _iterator1.return(); @@ -373,60 +465,60 @@ var collectCommits = function(head, base) { return [ 7 ]; - case 11: + case 13: _iteratorAbruptCompletion = false; return [ 3, 2 ]; - case 12: + case 14: return [ 3, - 19 + 21 ]; - case 13: + case 15: err1 = _state.sent(); _didIteratorError = true; _iteratorError = err1; return [ 3, - 19 + 21 ]; - case 14: + case 16: _state.trys.push([ - 14, + 16, , - 17, - 18 + 19, + 20 ]); if (!(_iteratorAbruptCompletion && _iterator.return != null)) return [ 3, - 16 + 18 ]; return [ 4, _iterator.return() ]; - case 15: + case 17: _state.sent(); - _state.label = 16; - case 16: + _state.label = 18; + case 18: return [ 3, - 18 + 20 ]; - case 17: + case 19: if (_didIteratorError) { throw _iteratorError; } return [ 7 ]; - case 18: + case 20: return [ 7 ]; - case 19: + case 21: return [ 2, stats @@ -1299,7 +1391,7 @@ var lengthBuffer = 1000; var makeGithubReleaseMessage = function(stats) { var message = "\n".concat(Object.entries(stats.pulls).map(function(param) { var _param = get_message_sliced_to_array(param, 2), key = _param[0], pulls = _param[1]; - return "\n### ".concat(capitalise(key), " Changes\n\n").concat(pulls.map(function(param) { + return "\n### ".concat(capitalise(key), " Changes\n\n").concat(pulls.slice().reverse().map(function(param) { var title = param.title; return "- ".concat(title); }).join('\n'), "\n"); diff --git a/packages/action/out/967.index.js b/packages/action/out/967.index.js index 4921f90..6d06d71 100644 --- a/packages/action/out/967.index.js +++ b/packages/action/out/967.index.js @@ -390,12 +390,20 @@ var release = function() { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Z": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); -var isCanary = function(test) { - return /^\d+\.\d+\.\d+-canary\.\d+$/.test(test); +/* unused harmony export isPrerelease */ +/* harmony import */ var _context__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7501); + +// Check if version matches the configured prerelease type (e.g., canary, beta) +var isPrerelease = function(test) { + var pattern = new RegExp("^\\d+\\.\\d+\\.\\d+-".concat(_context__WEBPACK_IMPORTED_MODULE_0__/* .prereleaseType */ .kD, "\\.\\d+$")); + return pattern.test(test); }; +// Legacy export for backwards compatibility +var isCanary = isPrerelease; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isCanary); + /***/ }) }; diff --git a/packages/action/src/check/index.ts b/packages/action/src/check/index.ts index df38ca8..3f4d672 100644 --- a/packages/action/src/check/index.ts +++ b/packages/action/src/check/index.ts @@ -3,9 +3,18 @@ import { bash, command } from '../util/exec'; import isCanary from '../util/is-canary'; import { gt } from 'semver'; import { getFolder, getJsonFile, JSONFile } from '../util/get-file'; +import { + publishPackages, + prereleaseType, + versionFiles, + withWorkingDir, +} from '../context'; -const versionParserRegexp = - /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*@(\d+\.\d+\.\d+(?:-canary\.\d+)?)/; +// Dynamic regex that supports the configured prerelease type +const createVersionParserRegexp = () => + new RegExp( + `^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*@(\\d+\\.\\d+\\.\\d+(?:-${prereleaseType}\\.\\d+)?)`, + ); const checkPackage = async (pkg: JSONFile, rootVersion: string) => { try { @@ -23,11 +32,12 @@ const checkPackage = async (pkg: JSONFile, rootVersion: string) => { try { const [res] = await bash` ${command` - npm view - ${packageJson.name}@${isCanary(rootVersion) ? 'canary' : 'latest'} + npm view + ${packageJson.name}@${isCanary(rootVersion) ? prereleaseType : 'latest'} `} `; if (!res) throw new Error('Ăšnexpected error'); + const versionParserRegexp = createVersionParserRegexp(); const [, , currentVersion] = versionParserRegexp.exec(res.stdout.trim()) || []; if (!currentVersion) @@ -50,12 +60,31 @@ const checkPackage = async (pkg: JSONFile, rootVersion: string) => { }; const checkPackages = async (rootVersion: string) => { - const folders = await getFolder('packages'); + // If publish-packages is configured, use those specific paths + if (publishPackages && publishPackages.length > 0) { + console.log('checking configured packages: ' + publishPackages.join(', ')); + return ( + await Promise.all( + publishPackages.map(async (pkgPath) => { + const fullPath = withWorkingDir(pkgPath); + // If path doesn't end with package.json, append it + const jsonPath = fullPath.endsWith('package.json') + ? fullPath + : `${fullPath}/package.json`; + return checkPackage(jsonPath as JSONFile, rootVersion); + }), + ) + ).filter(Boolean) as string[]; + } + + // Otherwise, scan packages/* directory (legacy behavior) + const packagesDir = withWorkingDir('packages'); + const folders = await getFolder(packagesDir); console.log('checking ' + folders.map(({ path }) => path).join()); return ( await Promise.all( folders.map(async ({ path }) => - checkPackage(`${path}/package.json`, rootVersion), + checkPackage(`${path}/package.json` as JSONFile, rootVersion), ), ) ).filter(Boolean) as string[]; @@ -69,10 +98,17 @@ const checkPackages = async (rootVersion: string) => { * inteded to be ran as part of a workflow */ const canPublish = async () => { + // Use the first version file as the source of truth for the version + const versionFilePath = withWorkingDir(versionFiles[0]); const { content: { version }, - } = await getJsonFile<{ version: string }>('package.json'); - console.log('version:', version, 'is canary:', isCanary(version)); + } = await getJsonFile<{ version: string }>(versionFilePath as JSONFile); + console.log( + 'version:', + version, + `is ${prereleaseType}:`, + isCanary(version), + ); // any version starting with 0.0.0 is considered a initial dev // version and will not be published if (version.startsWith('0.0.0')) { diff --git a/packages/action/src/context.ts b/packages/action/src/context.ts index 0effb9f..90df871 100644 --- a/packages/action/src/context.ts +++ b/packages/action/src/context.ts @@ -16,3 +16,23 @@ export const { } = context; export const initial_commit: string | undefined = getInput('initial-commit'); + +// Monorepo support configuration +export const workingDirectory: string = getInput('working-directory') || '.'; +export const versionFiles: string[] = JSON.parse( + getInput('version-files') || '["package.json"]', +); +export const publishPackages: string[] | undefined = getInput('publish-packages') + ? JSON.parse(getInput('publish-packages')) + : undefined; +export const prereleaseType: string = getInput('prerelease-type') || 'canary'; +export const baseBranch: string = getInput('base-branch') || 'main'; +export const maxChangelogCommits: number = parseInt(getInput('max-changelog-commits') || '100', 10); +export const prTitlePrefix: string = getInput('pr-title-prefix') || ''; +export const prLabels: string[] = JSON.parse(getInput('pr-labels') || '[]'); + +// Helper to join working directory with a path +export const withWorkingDir = (path: string): string => { + if (workingDirectory === '.') return path; + return `${workingDirectory}/${path}`; +}; diff --git a/packages/action/src/release-pull/create.ts b/packages/action/src/release-pull/create.ts index ffe2fdd..a2d7e3d 100644 --- a/packages/action/src/release-pull/create.ts +++ b/packages/action/src/release-pull/create.ts @@ -1,13 +1,22 @@ import inc from 'semver/functions/inc'; -import { octo, owner, repo } from '../context'; +import { + octo, + owner, + repo, + versionFiles, + prereleaseType, + baseBranch, + withWorkingDir, + prLabels, +} from '../context'; import getReleaseMessage from '../util/get-message'; import isActionUser from '../util/is-action-user'; import { Pull } from '../util/types'; -import { canaryReleaseTitle, fullReleaseTitle } from './shared'; +import { getPrereleaseTitle, getFullReleaseTitle } from './shared'; const runAction = async () => { const stale: Pull[] = []; - const staleCanary: Pull[] = []; + const stalePrerelease: Pull[] = []; for await (const { data: pulls } of octo.paginate.iterator( octo.rest.pulls.list, { @@ -20,14 +29,18 @@ const runAction = async () => { }, )) for (const pull of pulls) { - if (isActionUser(pull.user)) { - if (fullReleaseTitle === pull.title) stale.push(pull); - else if (canaryReleaseTitle === pull.title) staleCanary.push(pull); + // Match by branch pattern instead of title (titles now include versions) + if (isActionUser(pull.user) && pull.head.ref.startsWith('turbo-module/release-')) { + if (pull.head.ref.includes(`-${prereleaseType}`)) { + stalePrerelease.push(pull); + } else { + stale.push(pull); + } } } // close stale PRs and delete the branches await Promise.all( - [...stale, ...staleCanary].map(async (stalePull) => { + [...stale, ...stalePrerelease].map(async (stalePull) => { await octo.rest.pulls.update({ repo, owner, @@ -42,15 +55,15 @@ const runAction = async () => { }), ); - const [canaryPull, fullPull] = await Promise.all([ + const [prereleasePull, fullPull] = await Promise.all([ createPull(true), createPull(false), ]); // add comments to closed PRs that link to the newly created PRs await Promise.all([ Promise.all( - staleCanary.map((pull) => - addCommentToClosed(pull.number, canaryPull.number), + stalePrerelease.map((pull) => + addCommentToClosed(pull.number, prereleasePull.number), ), ), Promise.all( @@ -68,31 +81,40 @@ const addCommentToClosed = async (number: number, replacement: number) => { }); }; -const pull_labels = ['auto-release-pr', 'keep up-to-date']; +const pull_labels = ['auto-release-pr', 'keep up-to-date', ...prLabels]; export const createPull = async (prerelease: boolean) => { - const title = prerelease ? canaryReleaseTitle : fullReleaseTitle; - const releaseLabel = prerelease ? 'releases: canary' : 'releases: patch'; + const releaseLabel = prerelease + ? `releases: ${prereleaseType}` + : 'releases: patch'; + + // Get the first version file to determine current version + const primaryVersionFile = withWorkingDir(versionFiles[0]); const { data: content } = await octo.rest.repos.getContent({ repo, owner, - path: 'package.json', + path: primaryVersionFile, }); if (!('content' in content)) throw new Error('Could not get package.json contents'); const packageJson = JSON.parse( Buffer.from(content.content, 'base64').toString(), ) as { version?: string }; + let newVersion: string | null; if (!packageJson.version || packageJson.version.startsWith('0.0.0')) { - newVersion = prerelease ? '0.0.1-canary.0' : '0.0.1'; + newVersion = prerelease ? `0.0.1-${prereleaseType}.0` : '0.0.1'; } else { newVersion = prerelease - ? inc(packageJson.version, 'prerelease', 'canary') + ? inc(packageJson.version, 'prerelease', prereleaseType) : inc(packageJson.version, 'patch'); } if (!newVersion) throw new Error('Could not increase version'); - packageJson.version = newVersion; + + const title = prerelease + ? getPrereleaseTitle(newVersion) + : getFullReleaseTitle(newVersion); + const { data: { object: { sha }, @@ -100,29 +122,52 @@ export const createPull = async (prerelease: boolean) => { } = await octo.rest.git.getRef({ owner, repo, - ref: `heads/main`, + ref: `heads/${baseBranch}`, }); const shortSha = sha.slice(0, 6) + sha.slice(-6); const branch = prerelease - ? `turbo-module/release-${shortSha}-canary` + ? `turbo-module/release-${shortSha}-${prereleaseType}` : `turbo-module/release-${shortSha}`; + await octo.rest.git.createRef({ owner, repo, sha, ref: `refs/heads/${branch}`, }); - await octo.rest.repos.createOrUpdateFileContents({ - repo, - owner, - path: 'package.json', - message: `release patch ${packageJson.version}`, - content: Buffer.from(JSON.stringify(packageJson, null, 2) + '\n').toString( - 'base64', - ), - sha: content.sha, - branch, - }); + + // Update all version files with the new version + for (const versionFile of versionFiles) { + const filePath = withWorkingDir(versionFile); + console.log(`Updating version in ${filePath} to ${newVersion}`); + + const { data: fileContent } = await octo.rest.repos.getContent({ + repo, + owner, + path: filePath, + ref: branch, + }); + if (!('content' in fileContent)) + throw new Error(`Could not get ${filePath} contents`); + + const filePackageJson = JSON.parse( + Buffer.from(fileContent.content, 'base64').toString(), + ) as { version?: string }; + filePackageJson.version = newVersion; + + await octo.rest.repos.createOrUpdateFileContents({ + repo, + owner, + path: filePath, + message: `release: ${newVersion}`, + content: Buffer.from( + JSON.stringify(filePackageJson, null, 2) + '\n', + ).toString('base64'), + sha: fileContent.sha, + branch, + }); + } + const { message } = await getReleaseMessage(prerelease); const { data: pull } = await octo.rest.pulls.create({ repo, @@ -130,7 +175,8 @@ export const createPull = async (prerelease: boolean) => { title, body: message, head: branch, - base: 'main', + base: baseBranch, + draft: true, }); let err = 0; while (err < 5) { diff --git a/packages/action/src/release-pull/shared.ts b/packages/action/src/release-pull/shared.ts index d0f0ff2..f710275 100644 --- a/packages/action/src/release-pull/shared.ts +++ b/packages/action/src/release-pull/shared.ts @@ -1,2 +1,15 @@ -export const fullReleaseTitle = '(turbo-module): release next version'; -export const canaryReleaseTitle = '(turbo-module): release next canary version'; +import { prereleaseType, prTitlePrefix } from '../context'; + +const formatTitle = (releaseType: string, version?: string) => { + const prefix = prTitlePrefix ? `${prTitlePrefix} ` : ''; + const versionSuffix = version ? ` v${version}` : ''; + return `${prefix}${releaseType}${versionSuffix}`.trim(); +}; + +export const getFullReleaseTitle = (version?: string) => + formatTitle('Stable Release', version); + +export const getPrereleaseTitle = (version?: string) => { + const releaseType = prereleaseType.charAt(0).toUpperCase() + prereleaseType.slice(1); + return formatTitle(`${releaseType} Release`, version); +}; diff --git a/packages/action/src/release-pull/sync.ts b/packages/action/src/release-pull/sync.ts index 71f75e0..1347f53 100644 --- a/packages/action/src/release-pull/sync.ts +++ b/packages/action/src/release-pull/sync.ts @@ -2,7 +2,7 @@ import isActionUser from '../util/is-action-user'; import { octo, owner, repo } from '../context'; import getReleaseMessage from '../util/get-message'; import { Pull } from '../util/types'; -import { canaryReleaseTitle, fullReleaseTitle } from './shared'; +import { getFullReleaseTitle, getPrereleaseTitle } from './shared'; import { createPull } from './create'; const syncPull = async (pull: Pull, prerelease: boolean) => { @@ -19,8 +19,11 @@ const syncPull = async (pull: Pull, prerelease: boolean) => { }; const runAction = async () => { + const fullReleaseTitle = getFullReleaseTitle(); + const prereleaseTitle = getPrereleaseTitle(); + let full: Promise | undefined; - let canary: Promise | undefined; + let prerelease: Promise | undefined; for await (const { data: pulls } of octo.paginate.iterator( octo.rest.pulls.list, { @@ -39,21 +42,21 @@ const runAction = async () => { if (!full) full = syncPull(pull, false); break; } - case canaryReleaseTitle: { - if (!canary) canary = syncPull(pull, true); + case prereleaseTitle: { + if (!prerelease) prerelease = syncPull(pull, true); break; } } } - if (full && canary) break; + if (full && prerelease) break; } - if (full && canary) break; + if (full && prerelease) break; } if (!full) full = createPull(false); - if (!canary) canary = createPull(true); + if (!prerelease) prerelease = createPull(true); - await Promise.all([full, canary]); + await Promise.all([full, prerelease]); }; export default runAction; diff --git a/packages/action/src/release-pull/type.ts b/packages/action/src/release-pull/type.ts index fcc6c39..85e2ff4 100644 --- a/packages/action/src/release-pull/type.ts +++ b/packages/action/src/release-pull/type.ts @@ -1,16 +1,26 @@ import { inc } from 'semver'; -import { octo, owner, repo, target_comment, target_issue } from '../context'; +import { + octo, + owner, + repo, + target_comment, + target_issue, + versionFiles, + prereleaseType, + baseBranch, + withWorkingDir, +} from '../context'; import getCodeOwners from '../util/get-codeowners'; const types = ['patch', 'minor', 'major'] as const; type ReleaseTypes = (typeof types)[number]; -const getPackageJson = async (ref?: string) => { +const getPackageJson = async (path: string, ref?: string) => { const { data: content } = await octo.rest.repos.getContent({ repo, owner, - path: 'package.json', + path, ref, }); if ('content' in content) { @@ -23,7 +33,7 @@ const getPackageJson = async (ref?: string) => { sha: content.sha, }; } - throw new Error('Could not load main package.json'); + throw new Error(`Could not load ${path}`); }; const performUpdate = async (type: ReleaseTypes) => { @@ -39,19 +49,18 @@ const performUpdate = async (type: ReleaseTypes) => { owner, pull_number: target_issue.number, }); - /* await octo.rest.pulls.updateBranch({ - repo, - owner, - pull_number: target_issue.number, - }); */ + const releaseTypeLabel = labels.find(({ name }) => name.startsWith('releases: '), ); const current_type = releaseTypeLabel?.name.replace('releases: ', ''); - if (current_type === 'canary' || type === current_type) return; - const { content: mainPackageJson } = await getPackageJson('main'); - const { content: currentPackageJson, sha: packageSha } = await getPackageJson( - branch, + // Skip if it's a prerelease PR or already the requested type + if (current_type === prereleaseType || type === current_type) return; + + const primaryVersionFile = withWorkingDir(versionFiles[0]); + const { content: mainPackageJson } = await getPackageJson( + primaryVersionFile, + baseBranch, ); const currentVersion = mainPackageJson.version.startsWith('0.0.0') ? '0.0.0' @@ -60,20 +69,27 @@ const performUpdate = async (type: ReleaseTypes) => { if (!newVersion) throw new Error(`Could not increase ${type} for ${currentVersion}`); - if (currentPackageJson.version !== newVersion) { - currentPackageJson.version = newVersion; + // Update all version files + for (const versionFile of versionFiles) { + const filePath = withWorkingDir(versionFile); + const { content: currentPackageJson, sha: packageSha } = + await getPackageJson(filePath, branch); - await octo.rest.repos.createOrUpdateFileContents({ - repo, - owner, - path: 'package.json', - message: `release ${type} ${newVersion}`, - content: Buffer.from( - JSON.stringify(currentPackageJson, null, 2) + '\n', - ).toString('base64'), - sha: packageSha, - branch, - }); + if (currentPackageJson.version !== newVersion) { + currentPackageJson.version = newVersion; + + await octo.rest.repos.createOrUpdateFileContents({ + repo, + owner, + path: filePath, + message: `release ${type} ${newVersion}`, + content: Buffer.from( + JSON.stringify(currentPackageJson, null, 2) + '\n', + ).toString('base64'), + sha: packageSha, + branch, + }); + } } const promises: Promise[] = [ diff --git a/packages/action/src/util/collect-commits.ts b/packages/action/src/util/collect-commits.ts index a0ddd59..e913d0c 100644 --- a/packages/action/src/util/collect-commits.ts +++ b/packages/action/src/util/collect-commits.ts @@ -1,4 +1,4 @@ -import { octo, owner, repo } from '../context'; +import { octo, owner, repo, maxChangelogCommits, workingDirectory } from '../context'; import isActionUser from './is-action-user'; import { ReleasePulls, ReleaseStats } from './types'; @@ -17,16 +17,35 @@ const collectCommits = async (head: string, base: string) => { authors: new Set(), pulls: {}, }; - for await (const { - data: { commits }, - } of octo.paginate.iterator(octo.rest.repos.compareCommits, { + let commitCount = 0; + + // Use listCommits with path filter for efficiency (only fetches commits touching working dir) + // This is much faster than comparing all commits and checking each one individually + const listOptions: Parameters[0] = { owner, repo, - base, - head, + sha: head, per_page: 100, - })) + ...(workingDirectory !== '.' && { path: workingDirectory }), + }; + + for await (const { data: commits } of octo.paginate.iterator( + octo.rest.repos.listCommits, + listOptions, + )) { for (const commit of commits) { + // Stop when we reach the base commit + if (commit.sha === base || commit.sha.startsWith(base) || base.startsWith(commit.sha)) { + console.log(`Reached base commit ${base}, stopping changelog scan`); + return stats; + } + + if (maxChangelogCommits > 0 && commitCount >= maxChangelogCommits) { + console.log(`Reached max commit limit (${maxChangelogCommits}), stopping changelog scan`); + return stats; + } + commitCount++; + const message = commit.commit.message.split('\n')[0]; const PR = /\(#(\d+)\)$/.exec(message)?.[1]; if (!PR) continue; @@ -37,21 +56,28 @@ const collectCommits = async (head: string, base: string) => { if (message.startsWith('(turbo-module): ')) continue; stats.authors.add(commit.author.login); } - const { data: pr } = await octo.rest.pulls.get({ - repo, - owner, - pull_number, - }); - const areas = pr.labels - .filter(({ name }) => /^area: /.test(name)) - .map(({ name }) => name.replace(/^area: /, '')); - - if (!areas.length) { + try { + const { data: pr } = await octo.rest.pulls.get({ + repo, + owner, + pull_number, + }); + const areas = pr.labels + .filter(({ name }) => /^area: /.test(name)) + .map(({ name }) => name.replace(/^area: /, '')); + + if (!areas.length) { + addPull(stats.pulls, 'general', pull_number, message); + } else + for (const area of areas) + addPull(stats.pulls, area, pull_number, message); + } catch (e) { + // PR might not exist in this repo (e.g., monorepo with commits from other repos) + console.log(`Skipping PR #${pull_number} - not found in this repo`); addPull(stats.pulls, 'general', pull_number, message); - } else - for (const area of areas) - addPull(stats.pulls, area, pull_number, message); + } } + } return stats; }; diff --git a/packages/action/src/util/get-message.ts b/packages/action/src/util/get-message.ts index 5208765..5b5004b 100644 --- a/packages/action/src/util/get-message.ts +++ b/packages/action/src/util/get-message.ts @@ -18,7 +18,11 @@ ${Object.entries(stats.pulls) ([key, pulls]) => ` ### ${capitalise(key)} Changes -${pulls.map(({ title }) => `- ${title}`).join('\n')} +${pulls + .slice() + .reverse() + .map(({ title }) => `- ${title}`) + .join('\n')} `, ) .join('')} diff --git a/packages/action/src/util/is-canary.ts b/packages/action/src/util/is-canary.ts index bfdf7c0..91fbdcb 100644 --- a/packages/action/src/util/is-canary.ts +++ b/packages/action/src/util/is-canary.ts @@ -1,3 +1,13 @@ -const isCanary = (test: string) => /^\d+\.\d+\.\d+-canary\.\d+$/.test(test); +import { prereleaseType } from '../context'; + +// Check if version matches the configured prerelease type (e.g., canary, beta) +const isPrerelease = (test: string) => { + const pattern = new RegExp(`^\\d+\\.\\d+\\.\\d+-${prereleaseType}\\.\\d+$`); + return pattern.test(test); +}; + +// Legacy export for backwards compatibility +const isCanary = isPrerelease; export default isCanary; +export { isPrerelease };