UNPKG

@cdwr/nx-migrate-action

Version:

The Nx Migrate GitHub Action will keep your workspace up to date.

1,028 lines (984 loc) 34.5 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // packages/nx-migrate-action/src/lib/main.ts var core21 = __toESM(require("@actions/core"), 1); // packages/nx-migrate-action/src/lib/nx-migrate.ts var core20 = __toESM(require("@actions/core"), 1); // packages/core/src/lib/actions/add-pull-request-comment.ts var github = __toESM(require("@actions/github"), 1); // packages/core/src/lib/actions/with-github.ts var import_request_error = require("@octokit/request-error"); var import_http_status_codes = require("http-status-codes"); async function withGitHub(operation, option) { try { return await operation(); } catch (error2) { if (error2 instanceof import_request_error.RequestError) { switch (error2.status) { case import_http_status_codes.StatusCodes.UNAUTHORIZED: throw new Error( `Authentication failed. Please check your GitHub token. ${error2.message}` ); case import_http_status_codes.StatusCodes.FORBIDDEN: throw new Error( `Permission to the operation was denied. Please check your GitHub token. ${error2.message}` ); case import_http_status_codes.StatusCodes.NOT_FOUND: if (option === "not-found-returns-null") { return null; } throw new Error( `Requested information was not found. ${error2.message}` ); default: throw new Error( `Request failed with ${error2.status} - ${(0, import_http_status_codes.getReasonPhrase)(error2.status)}. ${error2.message}` ); } } throw error2; } } // packages/core/src/lib/actions/add-pull-request-comment.ts var addPullRequestComment = async (token, pullRequest, comment) => { const octokit = github.getOctokit(token); const { data: { id } } = await withGitHub( () => octokit.rest.issues.createComment({ ...github.context.repo, issue_number: pullRequest, body: comment }) ); return id; }; // packages/core/src/lib/actions/get-repository-default-branch.ts var github2 = __toESM(require("@actions/github"), 1); var getRepositoryDefaultBranch = async (token) => { const octokit = github2.getOctokit(token); const { data: { default_branch } } = await withGitHub( async () => octokit.rest.repos.get({ ...github2.context.repo }) ); return default_branch; }; // packages/core/src/lib/actions/get-deploy-env.ts var import_zod = require("zod"); var EnvironmentSchema = import_zod.z.enum(["preview", "production"]); // packages/core/src/lib/actions/get-pull-request.ts var core = __toESM(require("@actions/core"), 1); var github3 = __toESM(require("@actions/github"), 1); var getPullRequest = async (token, pullRequest) => { const octokit = github3.getOctokit(token); core.debug(`Get pull request from number #${pullRequest}`); const pr = await withGitHub( () => octokit.rest.pulls.get({ ...github3.context.repo, pull_number: pullRequest }), "not-found-returns-null" ); if (!pr) { core.debug(`Pull request #${pullRequest} could not be found`); return void 0; } return pr.data; }; // packages/core/src/lib/actions/print-github-context.ts var core2 = __toESM(require("@actions/core"), 1); var github4 = __toESM(require("@actions/github"), 1); var printGitHubContext = () => { core2.info("== Repo =="); core2.info(`- owner: ${github4.context.repo.owner}`); core2.info(`- repo: ${github4.context.repo.repo}`); core2.info("== Misc =="); for (const [key, value] of Object.entries(github4.context)) { if (typeof value === "string") { core2.info(`- ${key}: ${value}`); } } }; // packages/nx-migrate-action/src/lib/utils/add-pull-request-assignees.ts var core3 = __toESM(require("@actions/core"), 1); var github5 = __toESM(require("@actions/github"), 1); var addPullRequestAssignees = async (config, pullRequest) => { const { prAssignees, token } = config; if (!prAssignees.length) { return; } const assignees = Array.isArray(prAssignees) ? prAssignees : [prAssignees]; const octokit = github5.getOctokit(token); await withGitHub( () => octokit.rest.issues.addAssignees({ ...github5.context.repo, issue_number: pullRequest, assignees }) ); core3.info( `Added assignees '${assignees.join(",")}' to pull request #${pullRequest}` ); }; // packages/nx-migrate-action/src/lib/utils/add-pull-request-label.ts var core4 = __toESM(require("@actions/core"), 1); var github6 = __toESM(require("@actions/github"), 1); // packages/nx-migrate-action/src/lib/utils/definitions.ts var PULL_REQUEST_LABEL = "nx migrate"; // packages/nx-migrate-action/src/lib/utils/add-pull-request-label.ts var addPullRequestLabel = async (config, pullRequest) => { const { token } = config; const labels = [PULL_REQUEST_LABEL]; const octokit = github6.getOctokit(token); await withGitHub( () => octokit.rest.issues.addLabels({ ...github6.context.repo, issue_number: pullRequest, labels }) ); core4.info( `Added labels '${labels.join(",")}' to pull request #${pullRequest}` ); }; // packages/nx-migrate-action/src/lib/utils/cleanup-pull-requests.ts var core5 = __toESM(require("@actions/core"), 1); var github7 = __toESM(require("@actions/github"), 1); var cleanupPullRequests = async (config, pullRequest) => { core5.info("Cleaning up deprecated open pull requests"); const { token } = config; const octokit = github7.getOctokit(token); const { data: openPullRequests } = await withGitHub( () => octokit.rest.pulls.list({ ...github7.context.repo, state: "open" }) ); if (!openPullRequests.length) { core5.info("No open pull requests found"); return; } for (const openPR of openPullRequests) { if (openPR.labels.find((label) => label.name === PULL_REQUEST_LABEL) && openPR.number !== pullRequest) { await withGitHub( () => octokit.rest.pulls.update({ ...github7.context.repo, pull_number: openPR.number, state: "closed" }) ); core5.info(`Closed deprecated pull request #${openPR.number}`); await withGitHub( () => octokit.rest.issues.createComment({ ...github7.context.repo, issue_number: openPR.number, body: `Auto-closed - replaced by new pull request #${pullRequest}` }) ); core5.info(`Added comment to deprecated pull request #${openPR.number}`); await withGitHub( () => octokit.rest.git.deleteRef({ ...github7.context.repo, ref: `heads/${openPR.head.ref}` }) ); core5.info( `Deleted branch ${openPR.head.ref} of pull request #${openPR.number}` ); } } }; // packages/nx-migrate-action/src/lib/utils/create-and-push-commit.ts var exec = __toESM(require("@actions/exec"), 1); // packages/nx-migrate-action/src/lib/utils/get-feature-branch-name.ts var getFeatureBranchName = (version) => `update-nx-workspace-${version}`; // packages/nx-migrate-action/src/lib/utils/create-and-push-commit.ts var createAndPushCommit = async (config, latestVersion) => { const { author } = config; const commitMessage = `build(repo): update nx workspace to ${latestVersion}`; const authorOption = author ? `--author="${author.name} <${author.email}>"` : ""; const commitOptions = [ authorOption, "-m", commitMessage, "--no-verify" ].filter(Boolean); const { stdout: fileChanges } = await exec.getExecOutput( "git", ["status", "--porcelain"], { silent: true } ); if (fileChanges.trim() === "") { throw new Error("Expected to find file changes to commit"); } await exec.exec("git", ["add", "."]); await exec.exec("git", ["commit", ...commitOptions]); await exec.exec("git", [ "push", "-u", "origin", getFeatureBranchName(latestVersion) ]); }; // packages/nx-migrate-action/src/lib/utils/create-local-branch.ts var core6 = __toESM(require("@actions/core"), 1); var exec3 = __toESM(require("@actions/exec"), 1); var createLocalBranch = async (config, latestVersion) => { const { mainBranch } = config; const featureBranch = getFeatureBranchName(latestVersion); await exec3.exec("git", [ "checkout", "--no-track", "-B", featureBranch, `origin/${mainBranch}` ]); core6.info(`Created local branch '${featureBranch}'`); }; // packages/nx-migrate-action/src/lib/utils/create-pull-request.ts var core7 = __toESM(require("@actions/core"), 1); var github8 = __toESM(require("@actions/github"), 1); var createPullRequest = async (config, versionInfo, status) => { const { mainBranch, skipE2E, skipTests, token } = config; const octokit = github8.getOctokit(token); const { currentVersion, latestVersion } = versionInfo; const { e2ePass, testsPass } = status; const branchName = getFeatureBranchName(latestVersion); const prTitle = `Update @nx/workspace to ${latestVersion}`; const prBody = [`Update Nx from ${currentVersion} to ${latestVersion}`, ""]; if (!skipTests) { prBody.push(testsPass ? "\u2705 Tests passed" : "\u26A0\uFE0F Tests failed", ""); } if (!skipE2E) { prBody.push(e2ePass ? "\u2705 E2E tests passed" : "\u26A0\uFE0F E2E tests failed", ""); } prBody.push( "", "> Auto-generated by [@cdwr/nx-migrate-action][1]", "", "[1]: https://github.com/codeware-sthlm/codeware/packages/nx-migrate-action" ); const { data: { number } } = await withGitHub( () => octokit.rest.pulls.create({ ...github8.context.repo, title: prTitle, body: prBody.join("\n"), head: branchName, base: mainBranch, draft: false }) ); core7.info(`Created pull request #${number}`); return number; }; // packages/nx-migrate-action/src/lib/utils/discard-unstaged-changes.ts var core8 = __toESM(require("@actions/core"), 1); var exec5 = __toESM(require("@actions/exec"), 1); var discardUnstagedChanges = async () => { await exec5.exec("git", ["checkout", "--", "."]); core8.info("All unstaged changes were discarded"); }; // packages/nx-migrate-action/src/lib/utils/enable-pull-request-auto-merge.ts var core9 = __toESM(require("@actions/core"), 1); var github9 = __toESM(require("@actions/github"), 1); var enablePullRequestAutoMerge = async (token, pullRequest, mergeMethod = "REBASE") => { const octokit = github9.getOctokit(token); const pullRequestData = await getPullRequest(token, pullRequest); if (!pullRequestData) { core9.error( `Pull request #${pullRequest} could not be found, aborting auto-merge` ); return; } await octokit.graphql( /* GraphQL */ ` mutation EnablePullRequestAutoMerge( $pullRequestId: ID! $mergeMethod: PullRequestMergeMethod! ) { enablePullRequestAutoMerge( input: { pullRequestId: $pullRequestId, mergeMethod: $mergeMethod } ) { pullRequest { autoMergeRequest { enabledAt } } } } `, { pullRequestId: pullRequestData.node_id, mergeMethod } ); core9.info( `Auto-merge is enabled for pull request #${pullRequest} with '${mergeMethod}'` ); }; // packages/nx-migrate-action/src/lib/utils/exists-feature-branch-on-remote.ts var core10 = __toESM(require("@actions/core"), 1); var exec7 = __toESM(require("@actions/exec"), 1); var existsFeatureBranchOnRemote = async (latestVersion) => { const branchName = getFeatureBranchName(latestVersion); const { stdout: prBranch } = await exec7.getExecOutput("git", [ "ls-remote", "--heads", "origin", branchName ]); if (prBranch.trim() !== "") { core10.info(`Feature branch '${branchName}' exists on remote`); return true; } return false; }; // packages/nx-migrate-action/src/lib/utils/fetch-remote-changes.ts var exec8 = __toESM(require("@actions/exec"), 1); var fetchRemoteChanges = async () => await exec8.exec("git", ["fetch", "origin"]); // packages/nx-migrate-action/src/lib/utils/get-migrate-config.ts var core12 = __toESM(require("@actions/core"), 1); var github11 = __toESM(require("@actions/github"), 1); // packages/nx-migrate-action/src/lib/utils/get-actor-id.ts var core11 = __toESM(require("@actions/core"), 1); var github10 = __toESM(require("@actions/github"), 1); var getActorId = async (token) => { const octokit = github10.getOctokit(token); const username = github10.context.actor; core11.debug(`Get user from actor '${username}'`); const actor = await withGitHub( async () => await octokit.rest.users.getByUsername({ username }), "not-found-returns-null" ); if (!actor) { core11.debug(`User '${username}' could not be found`); return void 0; } return actor.data.id; }; // packages/nx-migrate-action/src/lib/utils/parse-name-email.ts var parseNameEmail = (text) => { if (!text) { return { name: "", email: "" }; } let name = ""; let email = ""; const nameEmailPattern = /^([^;<\s][^<]{0,254})(?:\s{0,10})<([^>]{1,256})>$/; const match = text.match(nameEmailPattern); if (match) { name = match[1].trim(); email = match[2].trim(); } if (!name || !email) { throw new Error( `'${text}' is not following the pattern 'Name <user@domain.io>'` ); } return { name, email }; }; // packages/nx-migrate-action/src/lib/utils/schema.ts var import_zod2 = require("zod"); var EmailValidation = { standardEmail: import_zod2.z.string().email(), githubBotEmail: import_zod2.z.string().regex( /^\d+\+[\w-]+\[bot\]@users\.noreply\.github\.com$/, "Invalid GitHub bot email" ), anyBotEmail: import_zod2.z.string().refine( (email) => { const githubBotPattern = /^\d+\+[\w-]+\[bot\]@users\.noreply\.github\.com$/; const regularEmailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return githubBotPattern.test(email) || regularEmailPattern.test(email); }, { message: "Invalid email address" } ) }; var ActionInputsSchema = import_zod2.z.object({ author: import_zod2.z.string(), autoMerge: import_zod2.z.boolean(), checkToken: import_zod2.z.boolean(), committer: import_zod2.z.string(), dryRun: import_zod2.z.boolean(), mainBranch: import_zod2.z.string(), packagePatterns: import_zod2.z.array(import_zod2.z.string()), prAssignees: import_zod2.z.string(), skipTests: import_zod2.z.boolean(), skipE2E: import_zod2.z.boolean(), token: import_zod2.z.string().min(1, "token is required") }); var MigrateConfigSchema = ActionInputsSchema.merge( import_zod2.z.object({ author: import_zod2.z.object({ name: import_zod2.z.string(), email: EmailValidation.anyBotEmail }).optional(), committer: import_zod2.z.object({ name: import_zod2.z.string().min(1, "committer name is required"), email: EmailValidation.anyBotEmail }), mainBranch: import_zod2.z.string().min(1, "main branch is required"), packagePatterns: import_zod2.z.array(import_zod2.z.string().min(1)).min(1, "at least one package pattern is required"), prAssignees: import_zod2.z.array(import_zod2.z.string().min(1)) }) ); // packages/nx-migrate-action/src/lib/utils/get-migrate-config.ts var getMigrateConfig = async (inputs) => { const { author: authorInput, autoMerge: autoMergeInput, checkToken, committer: committerInput, dryRun, mainBranch: mainBranchInput, packagePatterns, prAssignees: prAssigneesInput, skipTests, skipE2E, token } = inputs; const octokit = github11.getOctokit(token); const mainBranch = mainBranchInput || await getRepositoryDefaultBranch(token); const { data: { allow_auto_merge } } = await withGitHub( () => octokit.rest.repos.get({ ...github11.context.repo }) ); if (!allow_auto_merge && autoMergeInput) { core12.warning( "Auto-merge is not enabled for this repository, ignoring auto-merge option" ); } const autoMerge = !!allow_auto_merge && autoMergeInput; let author = parseNameEmail(authorInput); if (!author.email) { const id = await getActorId(token); if (id) { author = { name: github11.context.actor, email: `${id}+${github11.context.actor}@users.noreply.github.com` }; } } let committer = parseNameEmail(committerInput); if (!committer.email) { committer = { name: "github-actions[bot]", email: "41898282+github-actions[bot]@users.noreply.github.com" }; } if (!packagePatterns.length) { packagePatterns.push("packages/**/package.json"); } const prAssignees = prAssigneesInput.split(",").filter(Boolean); const config = { author: author.email ? author : void 0, autoMerge, checkToken, committer, dryRun, mainBranch, packagePatterns, prAssignees, skipTests, skipE2E, token }; core12.info(JSON.stringify(config, null, 2)); return MigrateConfigSchema.parse(config); }; // packages/nx-migrate-action/src/lib/utils/get-nx-version-info.ts var core13 = __toESM(require("@actions/core"), 1); var exec10 = __toESM(require("@actions/exec"), 1); async function getNxVersionInfo() { core13.info("Resolve nx versions"); const output = await exec10.getExecOutput( "npm", ["list", "@nx/workspace", "--depth=0", "--json"], { silent: true } ); const currentVersion = JSON.parse(output.stdout).dependencies["@nx/workspace"].version; core13.info(`Current version: ${currentVersion}`); const currentMajor = parseInt(currentVersion.split(".")[0]); core13.info(`Current major: ${currentMajor}`); const latestOutput = await exec10.getExecOutput( "npm", ["view", "@nx/workspace", "version"], { silent: true } ); const latestVersion = latestOutput.stdout.trim(); core13.info(`Latest version: ${latestVersion}`); const latestMajor = parseInt(latestVersion.split(".")[0]); core13.info(`Latest major: ${latestMajor}`); const isMajorUpdate = latestMajor > currentMajor; core13.info(`Major update: ${isMajorUpdate}`); const isOutdated = currentVersion !== latestVersion; core13.info(`Outdated: ${isOutdated}`); return { currentVersion, latestVersion, isMajorUpdate, isOutdated }; } // packages/nx-migrate-action/src/lib/utils/get-token-permissions.ts var core14 = __toESM(require("@actions/core"), 1); var github12 = __toESM(require("@actions/github"), 1); var getTokenPermissions = async (token) => { const octokit = github12.getOctokit(token); core14.debug("Get token permissions"); const { data: { login: username }, headers } = await withGitHub(async () => await octokit.rest.users.getAuthenticated()); const expirationHeader = headers["github-authentication-token-expiration"]; const expiration = expirationHeader ? new Date(expirationHeader) : null; const isValid = expiration ? expiration > /* @__PURE__ */ new Date() : true; const { data: repos } = await octokit.rest.repos.listForAuthenticatedUser(); const permissions = repos.find( (repo) => repo.name === github12.context.repo.repo )?.permissions; if (!permissions) { throw new Error("Repository permissions not found"); } const scopesHeader = headers["x-oauth-scopes"]; const scopes = scopesHeader ? scopesHeader.split(",").map((scope) => scope.trim()).filter(Boolean) : void 0; return { type: "x-oauth-scopes" in headers ? "classic" : "fine-grained", isValid, username, expiration, scopes, repoPermissions: permissions, resolvedPermissions: { pullRequest: scopes?.includes("repo") ?? permissions.pull_requests === "write", repo: scopes?.includes("repo") ?? permissions.contents === "write", workflow: scopes?.includes("workflow") ?? permissions.workflows === "write" } }; }; // packages/nx-migrate-action/src/lib/utils/lookup-pull-request.ts var github13 = __toESM(require("@actions/github"), 1); var lookupPullRequest = async (config, latestVersion) => { const { token } = config; const branchName = getFeatureBranchName(latestVersion); const octokit = github13.getOctokit(token); const { data: pullRequests } = await withGitHub( () => octokit.rest.pulls.list({ ...github13.context.repo, state: "open", head: `${github13.context.repo.owner}:${branchName}` }) ); if (pullRequests.length > 1) { throw new Error(`Multiple pull requests found for branch ${branchName}`); } return pullRequests.length === 1 ? pullRequests[0].number : void 0; }; // packages/nx-migrate-action/src/lib/utils/print-commit-signature-details.ts var core15 = __toESM(require("@actions/core"), 1); var github14 = __toESM(require("@actions/github"), 1); // packages/nx-migrate-action/src/lib/utils/get-current-commit-sha.ts var exec11 = __toESM(require("@actions/exec"), 1); var getCurrentCommitSha = async () => { let sha = ""; const options = { listeners: { stdout: (data) => { sha += data.toString(); } } }; await exec11.exec("git", ["rev-parse", "HEAD"], options); return sha.trim(); }; // packages/nx-migrate-action/src/lib/utils/print-commit-signature-details.ts var printCommitSignatureDetails = async (config) => { const { token } = config; const octokit = github14.getOctokit(token); const ref = await getCurrentCommitSha(); const { data: { commit, committer, sha } } = await withGitHub( () => octokit.rest.repos.getCommit({ ...github14.context.repo, ref }) ); core15.info(`Verification status for commit ${sha}`); core15.info(`- Verified: ${commit.verification?.verified}`); core15.info(`- Reason: ${commit.verification?.reason}`); core15.info(`- Committer: ${committer?.name}`); }; // packages/nx-migrate-action/src/lib/utils/print-token-permissions.ts var core16 = __toESM(require("@actions/core"), 1); var printTokenPermissions = (token) => { core16.info("== Token =="); core16.info(`- type: ${token.type}`); core16.info(`- isValid: ${token.isValid}`); core16.info(`- username: ${token.username}`); core16.info(`- expiration: ${token.expiration}`); core16.info(`- scopes: ${token.scopes?.join(", ")}`); core16.info("== Repo permissions =="); for (const [key, value] of Object.entries(token.repoPermissions)) { core16.info(`- ${key}: ${value}`); } core16.info("== Resolved permissions =="); for (const [key, value] of Object.entries(token.resolvedPermissions)) { core16.info(`- ${key}: ${value}`); } }; // packages/nx-migrate-action/src/lib/utils/run-migration.ts var core17 = __toESM(require("@actions/core"), 1); var exec13 = __toESM(require("@actions/exec"), 1); var import_devkit = require("@nx/devkit"); var import_replace_in_file = require("replace-in-file"); var runMigration = async (config, latestVersion) => { const pmc = (0, import_devkit.getPackageManagerCommand)(); core17.info("Running Nx migrate"); await exec13.exec(pmc.exec, ["nx", "migrate", latestVersion]); core17.info("Adding create-nx-workspace dependency"); await exec13.exec(pmc.exec, [ "nx", "add", `create-nx-workspace@${latestVersion}` ]); core17.info("Installing dependencies"); await exec13.exec(pmc.install); const migrationsExist = await exec13.exec("test", ["-f", "migrations.json"], { ignoreReturnCode: true }) === 0; if (migrationsExist) { core17.info("Running migrations"); await exec13.exec(pmc.exec, ["nx", "migrate", "--run-migrations"]); } else { core17.info("No migrations found"); } core17.info("Update version references in package.json files"); core17.debug("Find and update semantic versions"); await (0, import_replace_in_file.replaceInFile)({ files: config.packagePatterns, from: /"(?:create-nx-workspace|nx|@nx\/[^"]*)": "\d+\.\d+\.\d+"/g, to: (match) => { const packageName = match.split(":")[0]; const newValue = `${packageName}: "${latestVersion}"`; core17.debug(`Found semver version '${match}' -> '${newValue}'`); return newValue; }, allowEmptyPaths: true }); core17.debug("Find and update major versions"); await (0, import_replace_in_file.replaceInFile)({ files: config.packagePatterns, from: /"(?:create-nx-workspace|nx|@nx\/[^"]*)": "(\d+)\.x"/g, to: (match) => { const packageName = match.split(":")[0]; const major = latestVersion.split(".")[0]; const newValue = `${packageName}: "${major}.x"`; core17.debug(`Found dynamic version '${match}' -> '${newValue}'`); return newValue; }, allowEmptyPaths: true }); core17.info("Migration completed"); }; // packages/nx-migrate-action/src/lib/utils/run-nx-e2e.ts var exec15 = __toESM(require("@actions/exec"), 1); var import_devkit2 = require("@nx/devkit"); async function runNxE2e() { const pmc = (0, import_devkit2.getPackageManagerCommand)(); try { await exec15.exec(pmc.exec, ["nx", "run-many", "-t", "e2e", "-c", "ci"]); return true; } catch (error2) { return false; } } // packages/nx-migrate-action/src/lib/utils/run-nx-tests.ts var exec17 = __toESM(require("@actions/exec"), 1); var import_devkit3 = require("@nx/devkit"); async function runNxTests() { const pmc = (0, import_devkit3.getPackageManagerCommand)(); try { await exec17.exec(pmc.exec, [ "nx", "run-many", "-t", "lint,test,build", "-c", "ci" ]); return true; } catch (error2) { return false; } } // packages/nx-migrate-action/src/lib/utils/set-git-credentials.ts var core18 = __toESM(require("@actions/core"), 1); var exec19 = __toESM(require("@actions/exec"), 1); var github15 = __toESM(require("@actions/github"), 1); var setGitCredentials = async (config) => { const { committer, token } = config; const { repo, owner } = github15.context.repo; await exec19.exec("git", ["config", "user.name", committer.name]); await exec19.exec("git", ["config", "user.email", committer.email]); core18.info(`Git committer name set to '${committer.name}'`); core18.info(`Git committer email set to '${committer.email}'`); const remoteUrl = `https://x-access-token:${token}@github.com/${owner}/${repo}.git`; await exec19.exec("git", ["remote", "set-url", "origin", remoteUrl]); core18.info(`Git remote URL set to '${remoteUrl}'`); }; // packages/nx-migrate-action/src/lib/utils/stage-all-changes.ts var core19 = __toESM(require("@actions/core"), 1); var exec21 = __toESM(require("@actions/exec"), 1); var stageAllChanges = async () => { await exec21.exec("git", ["add", "."]); core19.info("All changes was staged"); }; // packages/nx-migrate-action/src/lib/nx-migrate.ts async function nxMigrate(inputs, throwOnError = false) { try { core20.info("Starting nx migration process"); core20.startGroup("GitHub context details"); printGitHubContext(); core20.endGroup(); core20.startGroup("Get migration configuration"); const config = await getMigrateConfig(inputs); core20.endGroup(); core20.startGroup("Set git credentials"); await setGitCredentials(config); core20.endGroup(); core20.startGroup("Check token is valid and has proper permissions"); if (config.checkToken) { try { const response = await getTokenPermissions(config.token); const { isValid, resolvedPermissions } = response; printTokenPermissions(response); if (!isValid) { throw new Error("Token is invalid or expired"); } if (Object.values(resolvedPermissions).some((value) => value === false)) { throw new Error("Token is missing some required permissions"); } } catch (error2) { if (error2 instanceof Error) { core20.warning(`Token check failed: ${error2.message}`); } else { core20.warning("Token check failed"); core20.warning(error2); } core20.warning( "Could not determine token permissions, continue migration anyway" ); } } else { core20.info("Disabled by configuration"); } core20.endGroup(); core20.startGroup("Analyze current migration state"); const { currentVersion, isMajorUpdate, isOutdated, latestVersion } = await getNxVersionInfo(); if (!isOutdated) { core20.info("Nx workspace is up to date, skipping migration"); return { currentVersion, latestVersion, isMajorUpdate, isMigrated: false, pullRequest: void 0 }; } if (await existsFeatureBranchOnRemote(latestVersion)) { const existingPullRequest = await lookupPullRequest( config, latestVersion ); if (!existingPullRequest) { throw new Error( `Expected to find a pull request for branch '${latestVersion}'` ); } core20.info( `Active pull request #${existingPullRequest} exists, skipping migration` ); return { currentVersion, isMajorUpdate, isMigrated: false, latestVersion, pullRequest: existingPullRequest }; } core20.endGroup(); if (!config.dryRun) { core20.startGroup("Fetch remote changes"); await fetchRemoteChanges(); core20.endGroup(); core20.startGroup("Create local branch"); await createLocalBranch(config, latestVersion); core20.endGroup(); core20.startGroup("Run migration"); await runMigration(config, latestVersion); await stageAllChanges(); core20.endGroup(); let testsPass; if (!config.skipTests) { core20.startGroup("Run tests on migration changes"); testsPass = await runNxTests(); core20.endGroup(); } let e2ePass; if ((config.skipTests || testsPass) && !config.skipE2E) { core20.startGroup("Run e2e on migration changes"); e2ePass = await runNxE2e(); core20.endGroup(); } core20.startGroup("Cleanup changes affected by tests"); await discardUnstagedChanges(); core20.endGroup(); core20.startGroup("Create commit on remote"); await createAndPushCommit(config, latestVersion); await printCommitSignatureDetails(config); core20.endGroup(); core20.startGroup("Create pull request"); const pullRequest = await createPullRequest( config, { currentVersion, latestVersion }, { e2ePass, testsPass } ); if (config.prAssignees.length > 0) { await addPullRequestAssignees(config, pullRequest); } await addPullRequestLabel(config, pullRequest); if (config.autoMerge) { if (isMajorUpdate) { core20.info("Skip auto-merge for major version migrations"); await addPullRequestComment( config.token, pullRequest, "Auto-merge is disabled for major version migrations" ); } else if (testsPass === false || e2ePass === false) { core20.info("Skip auto-merge since some tests failed"); await addPullRequestComment( config.token, pullRequest, "Auto-merge was disabled since some tests failed" ); } else { await enablePullRequestAutoMerge(config.token, pullRequest, "REBASE"); } } await cleanupPullRequests(config, pullRequest); core20.endGroup(); return { currentVersion, isMajorUpdate, isMigrated: true, latestVersion, pullRequest }; } else { core20.info("Skip nx migration [dry-run]"); return { currentVersion, isMajorUpdate, isMigrated: false, latestVersion, pullRequest: void 0 }; } } catch (error2) { if (error2 instanceof Error) { core20.setFailed(error2.message); if (throwOnError) { throw error2.message; } } return {}; } } // packages/nx-migrate-action/src/lib/main.ts async function run() { try { const inputs = ActionInputsSchema.parse({ token: core21.getInput("token", { required: true }), autoMerge: core21.getBooleanInput("auto-merge"), checkToken: core21.getBooleanInput("check-token"), committer: core21.getInput("committer"), author: core21.getInput("author"), mainBranch: core21.getInput("main-branch"), packagePatterns: core21.getMultilineInput("package-patterns"), prAssignees: core21.getInput("pull-request-assignees"), skipTests: core21.getBooleanInput("skip-tests"), skipE2E: core21.getBooleanInput("skip-e2e"), dryRun: core21.getBooleanInput("dry-run") }); core21.debug(`Inputs: ${JSON.stringify(inputs, null, 2)}`); const { currentVersion, isMajorUpdate, isMigrated, latestVersion, pullRequest } = await nxMigrate(inputs); core21.setOutput("current-version", currentVersion); core21.setOutput("latest-version", latestVersion); core21.setOutput("is-major-update", isMajorUpdate); core21.setOutput("is-migrated", isMigrated); core21.setOutput("pull-request", pullRequest); } catch (error2) { if (error2 instanceof Error) { core21.setFailed(error2.message); } } } // packages/nx-migrate-action/src/action.ts run();