'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var errors = require('@backstage/errors');
var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
var octokit = require('octokit');
var integration = require('@backstage/integration');
var Sodium = require('libsodium-wrappers');
var yaml = require('yaml');
var webhooks = require('@octokit/webhooks');
var path = require('path');
var backendCommon = require('@backstage/backend-common');
var octokitPluginCreatePullRequest = require('octokit-plugin-create-pull-request');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var Sodium__default = /*#__PURE__*/_interopDefaultLegacy(Sodium);
var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);

const enableBranchProtectionOnDefaultRepoBranch = async ({
  repoName,
  client,
  owner,
  logger,
  requireCodeOwnerReviews,
  bypassPullRequestAllowances,
  requiredApprovingReviewCount,
  restrictions,
  requiredStatusCheckContexts = [],
  requireBranchesToBeUpToDate = true,
  requiredConversationResolution = false,
  defaultBranch = "master",
  enforceAdmins = true,
  dismissStaleReviews = false,
  requiredCommitSigning = false
}) => {
  const tryOnce = async () => {
    try {
      await client.rest.repos.updateBranchProtection({
        mediaType: {
          /**
           * 👇 we need this preview because allowing a custom
           * reviewer count on branch protection is a preview
           * feature
           *
           * More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews
           */
          previews: ["luke-cage-preview"]
        },
        owner,
        repo: repoName,
        branch: defaultBranch,
        required_status_checks: {
          strict: requireBranchesToBeUpToDate,
          contexts: requiredStatusCheckContexts
        },
        restrictions: restrictions != null ? restrictions : null,
        enforce_admins: enforceAdmins,
        required_pull_request_reviews: {
          required_approving_review_count: requiredApprovingReviewCount,
          require_code_owner_reviews: requireCodeOwnerReviews,
          bypass_pull_request_allowances: bypassPullRequestAllowances,
          dismiss_stale_reviews: dismissStaleReviews
        },
        required_conversation_resolution: requiredConversationResolution
      });
      if (requiredCommitSigning) {
        await client.rest.repos.createCommitSignatureProtection({
          owner,
          repo: repoName,
          branch: defaultBranch
        });
      }
    } catch (e) {
      errors.assertError(e);
      if (e.message.includes(
        "Upgrade to GitHub Pro or make this repository public to enable this feature"
      )) {
        logger.warn(
          "Branch protection was not enabled as it requires GitHub Pro for private repositories"
        );
      } else {
        throw e;
      }
    }
  };
  try {
    await tryOnce();
  } catch (e) {
    if (!e.message.includes("Branch not found")) {
      throw e;
    }
    await new Promise((resolve) => setTimeout(resolve, 600));
    await tryOnce();
  }
};
function entityRefToName(name) {
  return name.replace(/^.*[:/]/g, "");
}

const DEFAULT_TIMEOUT_MS = 6e4;
async function getOctokitOptions(options) {
  var _a;
  const { integrations, credentialsProvider, repoUrl, token } = options;
  const { owner, repo, host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
  const requestOptions = {
    // set timeout to 60 seconds
    timeout: DEFAULT_TIMEOUT_MS
  };
  if (!owner) {
    throw new errors.InputError(`No owner provided for repo ${repoUrl}`);
  }
  const integrationConfig = (_a = integrations.github.byHost(host)) == null ? void 0 : _a.config;
  if (!integrationConfig) {
    throw new errors.InputError(`No integration for host ${host}`);
  }
  if (token) {
    return {
      auth: token,
      baseUrl: integrationConfig.apiBaseUrl,
      previews: ["nebula-preview"],
      request: requestOptions
    };
  }
  const githubCredentialsProvider = credentialsProvider != null ? credentialsProvider : integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
  const { token: credentialProviderToken } = await githubCredentialsProvider.getCredentials({
    url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(
      repo
    )}`
  });
  if (!credentialProviderToken) {
    throw new errors.InputError(
      `No token available for host: ${host}, with owner ${owner}, and repo ${repo}`
    );
  }
  return {
    auth: credentialProviderToken,
    baseUrl: integrationConfig.apiBaseUrl,
    previews: ["nebula-preview"]
  };
}
async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, repoVisibility, description, homepage, deleteBranchOnMerge, allowMergeCommit, allowSquashMerge, squashMergeCommitTitle, squashMergeCommitMessage, allowRebaseMerge, allowAutoMerge, access, collaborators, hasProjects, hasWiki, hasIssues, topics, repoVariables, secrets, logger) {
  const user = await client.rest.users.getByUsername({
    username: owner
  });
  if (access == null ? void 0 : access.startsWith(`${owner}/`)) {
    await validateAccessTeam(client, access);
  }
  const repoCreationPromise = user.data.type === "Organization" ? client.rest.repos.createInOrg({
    name: repo,
    org: owner,
    private: repoVisibility === "private",
    // @ts-ignore https://github.com/octokit/types.ts/issues/522
    visibility: repoVisibility,
    description,
    delete_branch_on_merge: deleteBranchOnMerge,
    allow_merge_commit: allowMergeCommit,
    allow_squash_merge: allowSquashMerge,
    squash_merge_commit_title: squashMergeCommitTitle,
    squash_merge_commit_message: squashMergeCommitMessage,
    allow_rebase_merge: allowRebaseMerge,
    allow_auto_merge: allowAutoMerge,
    homepage,
    has_projects: hasProjects,
    has_wiki: hasWiki,
    has_issues: hasIssues
  }) : client.rest.repos.createForAuthenticatedUser({
    name: repo,
    private: repoVisibility === "private",
    description,
    delete_branch_on_merge: deleteBranchOnMerge,
    allow_merge_commit: allowMergeCommit,
    allow_squash_merge: allowSquashMerge,
    squash_merge_commit_title: squashMergeCommitTitle,
    squash_merge_commit_message: squashMergeCommitMessage,
    allow_rebase_merge: allowRebaseMerge,
    allow_auto_merge: allowAutoMerge,
    homepage,
    has_projects: hasProjects,
    has_wiki: hasWiki,
    has_issues: hasIssues
  });
  let newRepo;
  try {
    newRepo = (await repoCreationPromise).data;
  } catch (e) {
    errors.assertError(e);
    if (e.message === "Resource not accessible by integration") {
      logger.warn(
        `The GitHub app or token provided may not have the required permissions to create the ${user.data.type} repository ${owner}/${repo}.`
      );
    }
    throw new Error(
      `Failed to create the ${user.data.type} repository ${owner}/${repo}, ${e.message}`
    );
  }
  if (access == null ? void 0 : access.startsWith(`${owner}/`)) {
    const [, team] = access.split("/");
    await client.rest.teams.addOrUpdateRepoPermissionsInOrg({
      org: owner,
      team_slug: team,
      owner,
      repo,
      permission: "admin"
    });
  } else if (access && access !== owner) {
    await client.rest.repos.addCollaborator({
      owner,
      repo,
      username: access,
      permission: "admin"
    });
  }
  if (collaborators) {
    for (const collaborator of collaborators) {
      try {
        if ("user" in collaborator) {
          await client.rest.repos.addCollaborator({
            owner,
            repo,
            username: entityRefToName(collaborator.user),
            permission: collaborator.access
          });
        } else if ("team" in collaborator) {
          await client.rest.teams.addOrUpdateRepoPermissionsInOrg({
            org: owner,
            team_slug: entityRefToName(collaborator.team),
            owner,
            repo,
            permission: collaborator.access
          });
        }
      } catch (e) {
        errors.assertError(e);
        const name = extractCollaboratorName(collaborator);
        logger.warn(
          `Skipping ${collaborator.access} access for ${name}, ${e.message}`
        );
      }
    }
  }
  if (topics) {
    try {
      await client.rest.repos.replaceAllTopics({
        owner,
        repo,
        names: topics.map((t) => t.toLowerCase())
      });
    } catch (e) {
      errors.assertError(e);
      logger.warn(`Skipping topics ${topics.join(" ")}, ${e.message}`);
    }
  }
  for (const [key, value] of Object.entries(repoVariables != null ? repoVariables : {})) {
    await client.rest.actions.createRepoVariable({
      owner,
      repo,
      name: key,
      value
    });
  }
  if (secrets) {
    const publicKeyResponse = await client.rest.actions.getRepoPublicKey({
      owner,
      repo
    });
    await Sodium__default["default"].ready;
    const binaryKey = Sodium__default["default"].from_base64(
      publicKeyResponse.data.key,
      Sodium__default["default"].base64_variants.ORIGINAL
    );
    for (const [key, value] of Object.entries(secrets)) {
      const binarySecret = Sodium__default["default"].from_string(value);
      const encryptedBinarySecret = Sodium__default["default"].crypto_box_seal(
        binarySecret,
        binaryKey
      );
      const encryptedBase64Secret = Sodium__default["default"].to_base64(
        encryptedBinarySecret,
        Sodium__default["default"].base64_variants.ORIGINAL
      );
      await client.rest.actions.createOrUpdateRepoSecret({
        owner,
        repo,
        secret_name: key,
        encrypted_value: encryptedBase64Secret,
        key_id: publicKeyResponse.data.key_id
      });
    }
  }
  return newRepo;
}
async function initRepoPushAndProtect(remoteUrl, password, workspacePath, sourcePath, defaultBranch, protectDefaultBranch, protectEnforceAdmins, owner, client, repo, requireCodeOwnerReviews, bypassPullRequestAllowances, requiredApprovingReviewCount, restrictions, requiredStatusCheckContexts, requireBranchesToBeUpToDate, requiredConversationResolution, config, logger, gitCommitMessage, gitAuthorName, gitAuthorEmail, dismissStaleReviews, requiredCommitSigning) {
  const gitAuthorInfo = {
    name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
    email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
  };
  const commitMessage = getGitCommitMessage(gitCommitMessage, config) || "initial commit";
  const commitResult = await pluginScaffolderNode.initRepoAndPush({
    dir: pluginScaffolderNode.getRepoSourceDirectory(workspacePath, sourcePath),
    remoteUrl,
    defaultBranch,
    auth: {
      username: "x-access-token",
      password
    },
    logger,
    commitMessage,
    gitAuthorInfo
  });
  if (protectDefaultBranch) {
    try {
      await enableBranchProtectionOnDefaultRepoBranch({
        owner,
        client,
        repoName: repo,
        logger,
        defaultBranch,
        bypassPullRequestAllowances,
        requiredApprovingReviewCount,
        restrictions,
        requireCodeOwnerReviews,
        requiredStatusCheckContexts,
        requireBranchesToBeUpToDate,
        requiredConversationResolution,
        enforceAdmins: protectEnforceAdmins,
        dismissStaleReviews,
        requiredCommitSigning
      });
    } catch (e) {
      errors.assertError(e);
      logger.warn(
        `Skipping: default branch protection on '${repo}', ${e.message}`
      );
    }
  }
  return { commitHash: commitResult.commitHash };
}
function extractCollaboratorName(collaborator) {
  if ("username" in collaborator)
    return collaborator.username;
  if ("user" in collaborator)
    return collaborator.user;
  return collaborator.team;
}
async function validateAccessTeam(client, access) {
  const [org, team_slug] = access.split("/");
  try {
    await client.rest.teams.getByName({
      org,
      team_slug
    });
  } catch (e) {
    if (e.response.data.message === "Not Found") {
      const message = `Received 'Not Found' from the API; one of org:
        ${org} or team: ${team_slug} was not found within GitHub.`;
      throw new errors.NotFoundError(message);
    }
  }
}
function getGitCommitMessage(gitCommitMessage, config) {
  return gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage");
}

const examples$9 = [
  {
    description: "GitHub Action Workflow Without Inputs.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:actions:dispatch",
          name: "Dispatch Github Action Workflow",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            workflowId: "WORKFLOW_ID",
            branchOrTagName: "main"
          }
        }
      ]
    })
  },
  {
    description: "GitHub Action Workflow With Inputs",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:actions:dispatch",
          name: "Dispatch Github Action Workflow with inputs",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            workflowId: "WORKFLOW_ID",
            branchOrTagName: "main",
            workflowInputs: {
              input1: "value1",
              input2: "value2"
            }
          }
        }
      ]
    })
  },
  {
    description: "GitHub Action Workflow With Custom Token",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:actions:dispatch",
          name: "Dispatch GitHub Action Workflow (custom token)",
          input: {
            repoUrl: "github.com?repo=reponame&owner=owner",
            workflowId: "WORKFLOW_ID",
            branchOrTagName: "release-1.0",
            token: "${{ secrets.MY_CUSTOM_TOKEN }}"
          }
        }
      ]
    })
  }
];

function createGithubActionsDispatchAction(options) {
  const { integrations, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:actions:dispatch",
    description: "Dispatches a GitHub Action workflow for a given branch or tag",
    examples: examples$9,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "workflowId", "branchOrTagName"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
            type: "string"
          },
          workflowId: {
            title: "Workflow ID",
            description: "The GitHub Action Workflow filename",
            type: "string"
          },
          branchOrTagName: {
            title: "Branch or Tag name",
            description: "The git branch or tag name used to dispatch the workflow",
            type: "string"
          },
          workflowInputs: {
            title: "Workflow Inputs",
            description: "Inputs keys and values to send to GitHub Action configured on the workflow file. The maximum number of properties is 10. ",
            type: "object"
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The GITHUB_TOKEN to use for authorization to GitHub"
          }
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        workflowId,
        branchOrTagName,
        workflowInputs,
        token: providedToken
      } = ctx.input;
      ctx.logger.info(
        `Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`
      );
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const client = new octokit.Octokit(
        await getOctokitOptions({
          integrations,
          repoUrl,
          credentialsProvider: githubCredentialsProvider,
          token: providedToken
        })
      );
      await client.rest.actions.createWorkflowDispatch({
        owner,
        repo,
        workflow_id: workflowId,
        ref: branchOrTagName,
        inputs: workflowInputs
      });
      ctx.logger.info(`Workflow ${workflowId} dispatched successfully`);
    }
  });
}

const examples$8 = [
  {
    description: "Add labels to pull request or issue",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:issues:label",
          name: "Add labels to pull request or issue",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            number: "1",
            labels: ["bug"]
          }
        }
      ]
    })
  },
  {
    description: "Add labels to pull request or issue with specific token",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:issues:label",
          name: "Add labels to pull request or issue with token",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            number: "1",
            labels: ["bug", "documentation"],
            token: "gph_YourGitHubToken"
          }
        }
      ]
    })
  }
];

function createGithubIssuesLabelAction(options) {
  const { integrations, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:issues:label",
    description: "Adds labels to a pull request or issue on GitHub.",
    examples: examples$8,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "number", "labels"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the repository name and 'owner' is an organization or username`,
            type: "string"
          },
          number: {
            title: "Pull Request or issue number",
            description: "The pull request or issue number to add labels to",
            type: "number"
          },
          labels: {
            title: "Labels",
            description: "The labels to add to the pull request or issue",
            type: "array",
            items: {
              type: "string"
            }
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The GITHUB_TOKEN to use for authorization to GitHub"
          }
        }
      }
    },
    async handler(ctx) {
      const { repoUrl, number, labels, token: providedToken } = ctx.input;
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      ctx.logger.info(`Adding labels to ${number} issue on repo ${repo}`);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const client = new octokit.Octokit(
        await getOctokitOptions({
          integrations,
          credentialsProvider: githubCredentialsProvider,
          repoUrl,
          token: providedToken
        })
      );
      try {
        await client.rest.issues.addLabels({
          owner,
          repo,
          issue_number: number,
          labels
        });
      } catch (e) {
        errors.assertError(e);
        ctx.logger.warn(
          `Failed: adding labels to issue: '${number}' on repo: '${repo}', ${e.message}`
        );
      }
    }
  });
}

const repoUrl = {
  title: "Repository Location",
  description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
  type: "string"
};
const description = {
  title: "Repository Description",
  type: "string"
};
const homepage = {
  title: "Repository Homepage",
  type: "string"
};
const access = {
  title: "Repository Access",
  description: `Sets an admin collaborator on the repository. Can either be a user reference different from 'owner' in 'repoUrl' or team reference, eg. 'org/team-name'`,
  type: "string"
};
const requireCodeOwnerReviews = {
  title: "Require CODEOWNER Reviews?",
  description: "Require an approved review in PR including files with a designated Code Owner",
  type: "boolean"
};
const dismissStaleReviews = {
  title: "Dismiss Stale Reviews",
  description: "New reviewable commits pushed to a matching branch will dismiss pull request review approvals.",
  type: "boolean"
};
const requiredStatusCheckContexts = {
  title: "Required Status Check Contexts",
  description: "The list of status checks to require in order to merge into this branch",
  type: "array",
  items: {
    type: "string"
  }
};
const requireBranchesToBeUpToDate = {
  title: "Require Branches To Be Up To Date?",
  description: `Require branches to be up to date before merging. The default value is 'true'`,
  type: "boolean"
};
const requiredConversationResolution = {
  title: "Required Conversation Resolution",
  description: "Requires all conversations on code to be resolved before a pull request can be merged into this branch",
  type: "boolean"
};
const repoVisibility = {
  title: "Repository Visibility",
  type: "string",
  enum: ["private", "public", "internal"]
};
const deleteBranchOnMerge = {
  title: "Delete Branch On Merge",
  type: "boolean",
  description: `Delete the branch after merging the PR. The default value is 'false'`
};
const gitAuthorName = {
  title: "Default Author Name",
  type: "string",
  description: `Sets the default author name for the commit. The default value is 'Scaffolder'`
};
const gitAuthorEmail = {
  title: "Default Author Email",
  type: "string",
  description: `Sets the default author email for the commit.`
};
const allowMergeCommit = {
  title: "Allow Merge Commits",
  type: "boolean",
  description: `Allow merge commits. The default value is 'true'`
};
const allowSquashMerge = {
  title: "Allow Squash Merges",
  type: "boolean",
  description: `Allow squash merges. The default value is 'true'`
};
const squashMergeCommitTitle = {
  title: "Default squash merge commit title",
  enum: ["PR_TITLE", "COMMIT_OR_PR_TITLE"],
  description: `Sets the default value for a squash merge commit title. The default value is 'COMMIT_OR_PR_TITLE'`
};
const squashMergeCommitMessage = {
  title: "Default squash merge commit message",
  enum: ["PR_BODY", "COMMIT_MESSAGES", "BLANK"],
  description: `Sets the default value for a squash merge commit message. The default value is 'COMMIT_MESSAGES'`
};
const allowRebaseMerge = {
  title: "Allow Rebase Merges",
  type: "boolean",
  description: `Allow rebase merges. The default value is 'true'`
};
const allowAutoMerge = {
  title: "Allow Auto Merges",
  type: "boolean",
  description: `Allow individual PRs to merge automatically when all merge requirements are met. The default value is 'false'`
};
const collaborators = {
  title: "Collaborators",
  description: "Provide additional users or teams with permissions",
  type: "array",
  items: {
    type: "object",
    additionalProperties: false,
    required: ["access"],
    properties: {
      access: {
        type: "string",
        description: "The type of access for the user"
      },
      user: {
        type: "string",
        description: "The name of the user that will be added as a collaborator"
      },
      team: {
        type: "string",
        description: "The name of the team that will be added as a collaborator"
      }
    },
    oneOf: [{ required: ["user"] }, { required: ["team"] }]
  }
};
const hasProjects = {
  title: "Enable projects",
  type: "boolean",
  description: `Enable projects for the repository. The default value is 'true' unless the organization has disabled repository projects`
};
const hasWiki = {
  title: "Enable the wiki",
  type: "boolean",
  description: `Enable the wiki for the repository. The default value is 'true'`
};
const hasIssues = {
  title: "Enable issues",
  type: "boolean",
  description: `Enable issues for the repository. The default value is 'true'`
};
const token = {
  title: "Authentication Token",
  type: "string",
  description: "The token to use for authorization to GitHub"
};
const topics = {
  title: "Topics",
  type: "array",
  items: {
    type: "string"
  }
};
const defaultBranch = {
  title: "Default Branch",
  type: "string",
  description: `Sets the default branch on the repository. The default value is 'master'`
};
const protectDefaultBranch = {
  title: "Protect Default Branch",
  type: "boolean",
  description: `Protect the default branch after creating the repository. The default value is 'true'`
};
const protectEnforceAdmins = {
  title: "Enforce Admins On Protected Branches",
  type: "boolean",
  description: `Enforce admins to adhere to default branch protection. The default value is 'true'`
};
const bypassPullRequestAllowances = {
  title: "Bypass pull request requirements",
  description: "Allow specific users, teams, or apps to bypass pull request requirements.",
  type: "object",
  additionalProperties: false,
  properties: {
    apps: {
      type: "array",
      items: {
        type: "string"
      }
    },
    users: {
      type: "array",
      items: {
        type: "string"
      }
    },
    teams: {
      type: "array",
      items: {
        type: "string"
      }
    }
  }
};
const gitCommitMessage = {
  title: "Git Commit Message",
  type: "string",
  description: `Sets the commit message on the repository. The default value is 'initial commit'`
};
const sourcePath = {
  title: "Source Path",
  description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
  type: "string"
};
const requiredApprovingReviewCount = {
  title: "Required approving review count",
  type: "number",
  description: `Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6 or 0 to not require reviewers. Defaults to 1.`
};
const restrictions = {
  title: "Restrict who can push to the protected branch",
  description: "Restrict who can push to the protected branch. User, app, and team restrictions are only available for organization-owned repositories.",
  type: "object",
  additionalProperties: false,
  properties: {
    apps: {
      type: "array",
      items: {
        type: "string"
      }
    },
    users: {
      type: "array",
      items: {
        type: "string"
      }
    },
    teams: {
      type: "array",
      items: {
        type: "string"
      }
    }
  }
};
const requiredCommitSigning = {
  title: "Require commit signing",
  type: "boolean",
  description: `Require commit signing so that you must sign commits on this branch.`
};
const repoVariables = {
  title: "Repository Variables",
  description: `Variables attached to the repository`,
  type: "object"
};
const secrets = {
  title: "Repository Secrets",
  description: `Secrets attached to the repository`,
  type: "object"
};

const remoteUrl = {
  title: "A URL to the repository with the provider",
  type: "string"
};
const repoContentsUrl = {
  title: "A URL to the root of the repository",
  type: "string"
};
const commitHash = {
  title: "The git commit hash of the initial commit",
  type: "string"
};

const examples$7 = [
  {
    description: "Creates a GitHub repository with default configuration.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:create",
          name: "Create a new GitHub repository",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner"
          }
        }
      ]
    })
  },
  {
    description: "Add a description.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:create",
          name: "Create a new GitHub repository with a description",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            description: "My new repository"
          }
        }
      ]
    })
  },
  {
    description: "Disable wiki and issues.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:create",
          name: "Create a new GitHub repository without wiki and issues",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            hasIssues: false,
            hasWiki: false
          }
        }
      ]
    })
  }
];

function createGithubRepoCreateAction(options) {
  const { integrations, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:repo:create",
    description: "Creates a GitHub repository.",
    examples: examples$7,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl"],
        properties: {
          repoUrl: repoUrl,
          description: description,
          homepage: homepage,
          access: access,
          requireCodeOwnerReviews: requireCodeOwnerReviews,
          bypassPullRequestAllowances: bypassPullRequestAllowances,
          requiredApprovingReviewCount: requiredApprovingReviewCount,
          restrictions: restrictions,
          requiredStatusCheckContexts: requiredStatusCheckContexts,
          requireBranchesToBeUpToDate: requireBranchesToBeUpToDate,
          requiredConversationResolution: requiredConversationResolution,
          repoVisibility: repoVisibility,
          deleteBranchOnMerge: deleteBranchOnMerge,
          allowMergeCommit: allowMergeCommit,
          allowSquashMerge: allowSquashMerge,
          squashMergeCommitTitle: squashMergeCommitTitle,
          squashMergeCommitMessage: squashMergeCommitMessage,
          allowRebaseMerge: allowRebaseMerge,
          allowAutoMerge: allowAutoMerge,
          collaborators: collaborators,
          hasProjects: hasProjects,
          hasWiki: hasWiki,
          hasIssues: hasIssues,
          token: token,
          topics: topics,
          repoVariables: repoVariables,
          secrets: secrets,
          requiredCommitSigning: requiredCommitSigning
        }
      },
      output: {
        type: "object",
        properties: {
          remoteUrl: remoteUrl,
          repoContentsUrl: repoContentsUrl
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        description,
        homepage,
        access,
        repoVisibility = "private",
        deleteBranchOnMerge = false,
        allowMergeCommit = true,
        allowSquashMerge = true,
        squashMergeCommitTitle = "COMMIT_OR_PR_TITLE",
        squashMergeCommitMessage = "COMMIT_MESSAGES",
        allowRebaseMerge = true,
        allowAutoMerge = false,
        collaborators,
        hasProjects = void 0,
        hasWiki = void 0,
        hasIssues = void 0,
        topics,
        repoVariables,
        secrets,
        token: providedToken
      } = ctx.input;
      const octokitOptions = await getOctokitOptions({
        integrations,
        credentialsProvider: githubCredentialsProvider,
        token: providedToken,
        repoUrl
      });
      const client = new octokit.Octokit(octokitOptions);
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const newRepo = await createGithubRepoWithCollaboratorsAndTopics(
        client,
        repo,
        owner,
        repoVisibility,
        description,
        homepage,
        deleteBranchOnMerge,
        allowMergeCommit,
        allowSquashMerge,
        squashMergeCommitTitle,
        squashMergeCommitMessage,
        allowRebaseMerge,
        allowAutoMerge,
        access,
        collaborators,
        hasProjects,
        hasWiki,
        hasIssues,
        topics,
        repoVariables,
        secrets,
        ctx.logger
      );
      ctx.output("remoteUrl", newRepo.clone_url);
    }
  });
}

const examples$6 = [
  {
    description: "Setup repo with no modifications to branch protection rules",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:push",
          name: "Create test repo with testuser as owner.",
          input: {
            repoUrl: "github.com?repo=test&owner=testuser"
          }
        }
      ]
    })
  },
  {
    description: "Setup repo with required codeowners check",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:push",
          name: "Require codeowner branch protection rule",
          input: {
            repoUrl: "github.com?repo=reponame&owner=owner",
            requireCodeOwnerReviews: true
          }
        }
      ]
    })
  },
  {
    description: "Change the default required number of approvals",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:repo:push",
          name: "Require two approvals before merging",
          input: {
            repoUrl: "github.com?repo=reponame&owner=owner",
            requiredApprovingReviewCount: 2
          }
        }
      ]
    })
  }
];

function createGithubRepoPushAction(options) {
  const { integrations, config, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:repo:push",
    description: "Initializes a git repository of contents in workspace and publishes it to GitHub.",
    examples: examples$6,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl"],
        properties: {
          repoUrl: repoUrl,
          requireCodeOwnerReviews: requireCodeOwnerReviews,
          dismissStaleReviews: dismissStaleReviews,
          requiredStatusCheckContexts: requiredStatusCheckContexts,
          bypassPullRequestAllowances: bypassPullRequestAllowances,
          requiredApprovingReviewCount: requiredApprovingReviewCount,
          restrictions: restrictions,
          requireBranchesToBeUpToDate: requireBranchesToBeUpToDate,
          requiredConversationResolution: requiredConversationResolution,
          defaultBranch: defaultBranch,
          protectDefaultBranch: protectDefaultBranch,
          protectEnforceAdmins: protectEnforceAdmins,
          gitCommitMessage: gitCommitMessage,
          gitAuthorName: gitAuthorName,
          gitAuthorEmail: gitAuthorEmail,
          sourcePath: sourcePath,
          token: token,
          requiredCommitSigning: requiredCommitSigning
        }
      },
      output: {
        type: "object",
        properties: {
          remoteUrl: remoteUrl,
          repoContentsUrl: repoContentsUrl,
          commitHash: commitHash
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        defaultBranch = "master",
        protectDefaultBranch = true,
        protectEnforceAdmins = true,
        gitCommitMessage = "initial commit",
        gitAuthorName,
        gitAuthorEmail,
        requireCodeOwnerReviews = false,
        dismissStaleReviews = false,
        bypassPullRequestAllowances,
        requiredApprovingReviewCount = 1,
        restrictions,
        requiredStatusCheckContexts = [],
        requireBranchesToBeUpToDate = true,
        requiredConversationResolution = false,
        token: providedToken,
        requiredCommitSigning = false
      } = ctx.input;
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const octokitOptions = await getOctokitOptions({
        integrations,
        credentialsProvider: githubCredentialsProvider,
        token: providedToken,
        repoUrl
      });
      const client = new octokit.Octokit(octokitOptions);
      const targetRepo = await client.rest.repos.get({ owner, repo });
      const remoteUrl = targetRepo.data.clone_url;
      const repoContentsUrl = `${targetRepo.data.html_url}/blob/${defaultBranch}`;
      const { commitHash } = await initRepoPushAndProtect(
        remoteUrl,
        octokitOptions.auth,
        ctx.workspacePath,
        ctx.input.sourcePath,
        defaultBranch,
        protectDefaultBranch,
        protectEnforceAdmins,
        owner,
        client,
        repo,
        requireCodeOwnerReviews,
        bypassPullRequestAllowances,
        requiredApprovingReviewCount,
        restrictions,
        requiredStatusCheckContexts,
        requireBranchesToBeUpToDate,
        requiredConversationResolution,
        config,
        ctx.logger,
        gitCommitMessage,
        gitAuthorName,
        gitAuthorEmail,
        dismissStaleReviews,
        requiredCommitSigning
      );
      ctx.output("remoteUrl", remoteUrl);
      ctx.output("repoContentsUrl", repoContentsUrl);
      ctx.output("commitHash", commitHash);
    }
  });
}

const examples$5 = [
  {
    description: "Create a GitHub webhook for a repository",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook",
            webhookSecret: "mysecret",
            events: ["push"],
            active: true,
            contentType: "json",
            insecureSsl: false,
            token: "my-github-token"
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub webhook with minimal configuration",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook"
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub webhook with custom events",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook",
            events: ["push", "pull_request"]
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub webhook with JSON content type",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook",
            contentType: "json"
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub webhook with insecure SSL",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook",
            insecureSsl: true
          }
        }
      ]
    })
  },
  {
    description: "Create an inactive GitHub webhook",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:webhook",
          name: "Create GitHub Webhook",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            webhookUrl: "https://example.com/my-webhook",
            active: false
          }
        }
      ]
    })
  }
];

function createGithubWebhookAction(options) {
  const { integrations, defaultWebhookSecret, githubCredentialsProvider } = options;
  const eventNames = webhooks.emitterEventNames.filter((event) => !event.includes("."));
  return pluginScaffolderNode.createTemplateAction({
    id: "github:webhook",
    description: "Creates webhook for a repository on GitHub.",
    examples: examples$5,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "webhookUrl"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
            type: "string"
          },
          webhookUrl: {
            title: "Webhook URL",
            description: "The URL to which the payloads will be delivered",
            type: "string"
          },
          webhookSecret: {
            title: "Webhook Secret",
            description: "Webhook secret value. The default can be provided internally in action creation",
            type: "string"
          },
          events: {
            title: "Triggering Events",
            description: "Determines what events the hook is triggered for. Default: push",
            type: "array",
            oneOf: [
              {
                items: {
                  type: "string",
                  enum: eventNames
                }
              },
              {
                items: {
                  type: "string",
                  const: "*"
                }
              }
            ]
          },
          active: {
            title: "Active",
            type: "boolean",
            description: `Determines if notifications are sent when the webhook is triggered. Default: true`
          },
          contentType: {
            title: "Content Type",
            type: "string",
            enum: ["form", "json"],
            description: `The media type used to serialize the payloads. The default is 'form'`
          },
          insecureSsl: {
            title: "Insecure SSL",
            type: "boolean",
            description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The GITHUB_TOKEN to use for authorization to GitHub"
          }
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        webhookUrl,
        webhookSecret = defaultWebhookSecret,
        events = ["push"],
        active = true,
        contentType = "form",
        insecureSsl = false,
        token: providedToken
      } = ctx.input;
      ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const client = new octokit.Octokit(
        await getOctokitOptions({
          integrations,
          credentialsProvider: githubCredentialsProvider,
          repoUrl,
          token: providedToken
        })
      );
      try {
        const insecure_ssl = insecureSsl ? "1" : "0";
        await client.rest.repos.createWebhook({
          owner,
          repo,
          config: {
            url: webhookUrl,
            content_type: contentType,
            secret: webhookSecret,
            insecure_ssl
          },
          events,
          active
        });
        ctx.logger.info(`Webhook '${webhookUrl}' created successfully`);
      } catch (e) {
        errors.assertError(e);
        ctx.logger.warn(
          `Failed: create webhook '${webhookUrl}' on repo: '${repo}', ${e.message}`
        );
      }
    }
  });
}

const examples$4 = [
  {
    description: "Example 1: Create and store a Deploy Key",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:deployKey:create",
          name: "Create and store a Deploy Key",
          input: {
            repoUrl: "github.com?repo=repository&owner=owner",
            publicKey: "pubkey",
            privateKey: "privkey",
            deployKeyName: "Push Tags"
          }
        }
      ]
    })
  }
];

function createGithubDeployKeyAction(options) {
  const { integrations } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:deployKey:create",
    description: "Creates and stores Deploy Keys",
    examples: examples$4,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "publicKey", "privateKey", "deployKeyName"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
            type: "string"
          },
          publicKey: {
            title: "SSH Public Key",
            description: `Generated from ssh-keygen.  Begins with 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', or 'sk-ssh-ed25519@openssh.com'.`,
            type: "string"
          },
          privateKey: {
            title: "SSH Private Key",
            description: `SSH Private Key generated from ssh-keygen`,
            type: "string"
          },
          deployKeyName: {
            title: "Deploy Key Name",
            description: `Name of the Deploy Key`,
            type: "string"
          },
          privateKeySecretName: {
            title: "Private Key GitHub Secret Name",
            description: `Name of the GitHub Secret to store the private key related to the Deploy Key.  Defaults to: 'KEY_NAME_PRIVATE_KEY' where 'KEY_NAME' is the name of the Deploy Key`,
            type: "string"
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The token to use for authorization to GitHub"
          }
        }
      },
      output: {
        type: "object",
        properties: {
          privateKeySecretName: {
            title: "The GitHub Action Repo Secret Name for the Private Key",
            type: "string"
          }
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        publicKey,
        privateKey,
        deployKeyName,
        privateKeySecretName = `${deployKeyName.split(" ").join("_").toLocaleUpperCase("en-US")}_PRIVATE_KEY`,
        token: providedToken
      } = ctx.input;
      const octokitOptions = await getOctokitOptions({
        integrations,
        token: providedToken,
        repoUrl
      });
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError(`No owner provided for repo ${repoUrl}`);
      }
      const client = new octokit.Octokit(octokitOptions);
      await client.rest.repos.createDeployKey({
        owner,
        repo,
        title: deployKeyName,
        key: publicKey
      });
      const publicKeyResponse = await client.rest.actions.getRepoPublicKey({
        owner,
        repo
      });
      await Sodium__default["default"].ready;
      const binaryKey = Sodium__default["default"].from_base64(
        publicKeyResponse.data.key,
        Sodium__default["default"].base64_variants.ORIGINAL
      );
      const binarySecret = Sodium__default["default"].from_string(privateKey);
      const encryptedBinarySecret = Sodium__default["default"].crypto_box_seal(
        binarySecret,
        binaryKey
      );
      const encryptedBase64Secret = Sodium__default["default"].to_base64(
        encryptedBinarySecret,
        Sodium__default["default"].base64_variants.ORIGINAL
      );
      await client.rest.actions.createOrUpdateRepoSecret({
        owner,
        repo,
        secret_name: privateKeySecretName,
        encrypted_value: encryptedBase64Secret,
        key_id: publicKeyResponse.data.key_id
      });
      ctx.output("privateKeySecretName", privateKeySecretName);
    }
  });
}

const examples$3 = [
  {
    description: "Create a GitHub Environment (No Policies, No Variables, No Secrets)",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:environment:create",
          name: "Create Environment",
          input: {
            repoUrl: "github.com?repo=repository&owner=owner",
            name: "envname"
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub Environment with Protected Branch Policy",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:environment:create",
          name: "Create Environment",
          input: {
            repoUrl: "github.com?repo=repository&owner=owner",
            name: "envname",
            deploymentBranchPolicy: {
              protected_branches: true,
              custom_branch_policies: false
            }
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub Environment with Custom Branch Policies",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:environment:create",
          name: "Create Environment",
          input: {
            repoUrl: "github.com?repo=repository&owner=owner",
            name: "envname",
            deploymentBranchPolicy: {
              protected_branches: false,
              custom_branch_policies: true
            },
            customBranchPolicyNames: ["main", "*.*.*"]
          }
        }
      ]
    })
  },
  {
    description: "Create a GitHub Environment with Environment Variables and Secrets",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:environment:create",
          name: "Create Environment",
          input: {
            repoUrl: "github.com?repo=repository&owner=owner",
            name: "envname",
            environmentVariables: {
              key1: "val1",
              key2: "val2"
            },
            secrets: {
              secret1: "supersecret1",
              secret2: "supersecret2"
            }
          }
        }
      ]
    })
  }
];

function createGithubEnvironmentAction(options) {
  const { integrations } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:environment:create",
    description: "Creates Deployment Environments",
    examples: examples$3,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "name"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
            type: "string"
          },
          name: {
            title: "Environment Name",
            description: `Name of the deployment environment to create`,
            type: "string"
          },
          deploymentBranchPolicy: {
            title: "Deployment Branch Policy",
            description: `The type of deployment branch policy for this environment. To allow all branches to deploy, set to null.`,
            type: "object",
            required: ["protected_branches", "custom_branch_policies"],
            properties: {
              protected_branches: {
                title: "Protected Branches",
                description: `Whether only branches with branch protection rules can deploy to this environment. If protected_branches is true, custom_branch_policies must be false; if protected_branches is false, custom_branch_policies must be true.`,
                type: "boolean"
              },
              custom_branch_policies: {
                title: "Custom Branch Policies",
                description: `Whether only branches that match the specified name patterns can deploy to this environment. If custom_branch_policies is true, protected_branches must be false; if custom_branch_policies is false, protected_branches must be true.`,
                type: "boolean"
              }
            }
          },
          customBranchPolicyNames: {
            title: "Custom Branch Policy Name",
            description: `The name pattern that branches must match in order to deploy to the environment.

            Wildcard characters will not match /. For example, to match branches that begin with release/ and contain an additional single slash, use release/*/*. For more information about pattern matching syntax, see the Ruby File.fnmatch documentation.`,
            type: "array",
            items: {
              type: "string"
            }
          },
          environmentVariables: {
            title: "Environment Variables",
            description: `Environment variables attached to the deployment environment`,
            type: "object"
          },
          secrets: {
            title: "Deployment Secrets",
            description: `Secrets attached to the deployment environment`,
            type: "object"
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The token to use for authorization to GitHub"
          }
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        name,
        deploymentBranchPolicy,
        customBranchPolicyNames,
        environmentVariables,
        secrets,
        token: providedToken
      } = ctx.input;
      const octokitOptions = await getOctokitOptions({
        integrations,
        token: providedToken,
        repoUrl
      });
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError(`No owner provided for repo ${repoUrl}`);
      }
      const client = new octokit.Octokit(octokitOptions);
      const repository = await client.rest.repos.get({
        owner,
        repo
      });
      await client.rest.repos.createOrUpdateEnvironment({
        owner,
        repo,
        environment_name: name,
        deployment_branch_policy: deploymentBranchPolicy != null ? deploymentBranchPolicy : null
      });
      if (customBranchPolicyNames) {
        for (const item of customBranchPolicyNames) {
          await client.rest.repos.createDeploymentBranchPolicy({
            owner,
            repo,
            environment_name: name,
            name: item
          });
        }
      }
      for (const [key, value] of Object.entries(environmentVariables != null ? environmentVariables : {})) {
        await client.rest.actions.createEnvironmentVariable({
          repository_id: repository.data.id,
          environment_name: name,
          name: key,
          value
        });
      }
      if (secrets) {
        const publicKeyResponse = await client.rest.actions.getEnvironmentPublicKey({
          repository_id: repository.data.id,
          environment_name: name
        });
        await Sodium__default["default"].ready;
        const binaryKey = Sodium__default["default"].from_base64(
          publicKeyResponse.data.key,
          Sodium__default["default"].base64_variants.ORIGINAL
        );
        for (const [key, value] of Object.entries(secrets)) {
          const binarySecret = Sodium__default["default"].from_string(value);
          const encryptedBinarySecret = Sodium__default["default"].crypto_box_seal(
            binarySecret,
            binaryKey
          );
          const encryptedBase64Secret = Sodium__default["default"].to_base64(
            encryptedBinarySecret,
            Sodium__default["default"].base64_variants.ORIGINAL
          );
          await client.rest.actions.createOrUpdateEnvironmentSecret({
            repository_id: repository.data.id,
            environment_name: name,
            secret_name: key,
            encrypted_value: encryptedBase64Secret,
            key_id: publicKeyResponse.data.key_id
          });
        }
      }
    }
  });
}

const examples$2 = [
  {
    description: "Create a pull request",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with target branch name",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest with target branch name",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            targetBranchName: "test"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request as draft",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest as draft",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            draft: true
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with target path",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest with target path",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            targetPath: "targetPath"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with source path",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest with source path",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            sourcePath: "source"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with token",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            token: "gph_YourGitHubToken"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with reviewers",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest with reviewers",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            reviewers: ["foobar"]
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with team reviewers",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest with team reviewers",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            teamReviewers: ["team-foo"]
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with commit message",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            commitMessage: "Custom commit message"
          }
        }
      ]
    })
  },
  {
    description: "Create a pull request with all parameters",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "publish:github:pull-request",
          name: "Create a pull reuqest",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            branchName: "new-app",
            title: "Create my new app",
            description: "This PR is really good",
            targetBranchName: "test",
            draft: true,
            targetPath: "targetPath",
            sourcePath: "source",
            token: "gph_YourGitHubToken",
            reviewers: ["foobar"],
            teamReviewers: ["team-foo"],
            commitMessage: "Commit for foo changes"
          }
        }
      ]
    })
  }
];

class GithubResponseError extends errors.CustomErrorBase {
}
const defaultClientFactory = async ({
  integrations,
  githubCredentialsProvider,
  owner,
  repo,
  host = "github.com",
  token: providedToken
}) => {
  const [encodedHost, encodedOwner, encodedRepo] = [host, owner, repo].map(
    encodeURIComponent
  );
  const octokitOptions = await getOctokitOptions({
    integrations,
    credentialsProvider: githubCredentialsProvider,
    repoUrl: `${encodedHost}?owner=${encodedOwner}&repo=${encodedRepo}`,
    token: providedToken
  });
  const OctokitPR = octokit.Octokit.plugin(octokitPluginCreatePullRequest.createPullRequest);
  return new OctokitPR({
    ...octokitOptions,
    ...{ throttle: { enabled: false } }
  });
};
const createPublishGithubPullRequestAction = (options) => {
  const {
    integrations,
    githubCredentialsProvider,
    clientFactory = defaultClientFactory
  } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "publish:github:pull-request",
    examples: examples$2,
    schema: {
      input: {
        required: ["repoUrl", "title", "description", "branchName"],
        type: "object",
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the repository name and 'owner' is an organization or username`,
            type: "string"
          },
          branchName: {
            type: "string",
            title: "Branch Name",
            description: "The name for the branch"
          },
          targetBranchName: {
            type: "string",
            title: "Target Branch Name",
            description: "The target branch name of the merge request"
          },
          title: {
            type: "string",
            title: "Pull Request Name",
            description: "The name for the pull request"
          },
          description: {
            type: "string",
            title: "Pull Request Description",
            description: "The description of the pull request"
          },
          draft: {
            type: "boolean",
            title: "Create as Draft",
            description: "Create a draft pull request"
          },
          sourcePath: {
            type: "string",
            title: "Working Subdirectory",
            description: "Subdirectory of working directory to copy changes from"
          },
          targetPath: {
            type: "string",
            title: "Repository Subdirectory",
            description: "Subdirectory of repository to apply changes to"
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The token to use for authorization to GitHub"
          },
          reviewers: {
            title: "Pull Request Reviewers",
            type: "array",
            items: {
              type: "string"
            },
            description: "The users that will be added as reviewers to the pull request"
          },
          teamReviewers: {
            title: "Pull Request Team Reviewers",
            type: "array",
            items: {
              type: "string"
            },
            description: "The teams that will be added as reviewers to the pull request"
          },
          commitMessage: {
            type: "string",
            title: "Commit Message",
            description: "The commit message for the pull request commit"
          },
          update: {
            type: "boolean",
            title: "Update",
            description: "Update pull request if already exists"
          }
        }
      },
      output: {
        required: ["remoteUrl"],
        type: "object",
        properties: {
          targetBranchName: {
            title: "Target branch name of the merge request",
            type: "string"
          },
          remoteUrl: {
            type: "string",
            title: "Pull Request URL",
            description: "Link to the pull request in Github"
          },
          pullRequestNumber: {
            type: "number",
            title: "Pull Request Number",
            description: "The pull request number"
          }
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        branchName,
        targetBranchName,
        title,
        description,
        draft,
        targetPath,
        sourcePath,
        token: providedToken,
        reviewers,
        teamReviewers,
        commitMessage,
        update
      } = ctx.input;
      const { owner, repo, host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError(
          `No owner provided for host: ${host}, and repo ${repo}`
        );
      }
      const client = await clientFactory({
        integrations,
        githubCredentialsProvider,
        host,
        owner,
        repo,
        token: providedToken
      });
      const fileRoot = sourcePath ? backendCommon.resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath;
      const directoryContents = await pluginScaffolderNode.serializeDirectoryContents(fileRoot, {
        gitignore: true
      });
      const determineFileMode = (file) => {
        if (file.symlink)
          return "120000";
        if (file.executable)
          return "100755";
        return "100644";
      };
      const determineFileEncoding = (file) => file.symlink ? "utf-8" : "base64";
      const files = Object.fromEntries(
        directoryContents.map((file) => [
          targetPath ? path__default["default"].posix.join(targetPath, file.path) : file.path,
          {
            // See the properties of tree items
            // in https://docs.github.com/en/rest/reference/git#trees
            mode: determineFileMode(file),
            // Always use base64 encoding where possible to avoid doubling a binary file in size
            // due to interpreting a binary file as utf-8 and sending github
            // the utf-8 encoded content. Symlinks are kept as utf-8 to avoid them
            // being formatted as a series of scrambled characters
            //
            // For example, the original gradle-wrapper.jar is 57.8k in https://github.com/kennethzfeng/pull-request-test/pull/5/files.
            // Its size could be doubled to 98.3K (See https://github.com/kennethzfeng/pull-request-test/pull/4/files)
            encoding: determineFileEncoding(file),
            content: file.content.toString(determineFileEncoding(file))
          }
        ])
      );
      try {
        const createOptions = {
          owner,
          repo,
          title,
          changes: [
            {
              files,
              commit: commitMessage != null ? commitMessage : title
            }
          ],
          body: description,
          head: branchName,
          draft,
          update
        };
        if (targetBranchName) {
          createOptions.base = targetBranchName;
        }
        const response = await client.createPullRequest(createOptions);
        if (!response) {
          throw new GithubResponseError("null response from Github");
        }
        const pullRequestNumber = response.data.number;
        if (reviewers || teamReviewers) {
          const pullRequest = { owner, repo, number: pullRequestNumber };
          await requestReviewersOnPullRequest(
            pullRequest,
            reviewers,
            teamReviewers,
            client,
            ctx.logger
          );
        }
        const targetBranch = response.data.base.ref;
        ctx.output("targetBranchName", targetBranch);
        ctx.output("remoteUrl", response.data.html_url);
        ctx.output("pullRequestNumber", pullRequestNumber);
      } catch (e) {
        throw new GithubResponseError("Pull request creation failed", e);
      }
    }
  });
  async function requestReviewersOnPullRequest(pr, reviewers, teamReviewers, client, logger) {
    var _a, _b, _c, _d;
    try {
      const result = await client.rest.pulls.requestReviewers({
        owner: pr.owner,
        repo: pr.repo,
        pull_number: pr.number,
        reviewers,
        team_reviewers: teamReviewers ? [...new Set(teamReviewers)] : void 0
      });
      const addedUsers = (_b = (_a = result.data.requested_reviewers) == null ? void 0 : _a.join(", ")) != null ? _b : "";
      const addedTeams = (_d = (_c = result.data.requested_teams) == null ? void 0 : _c.join(", ")) != null ? _d : "";
      logger.info(
        `Added users [${addedUsers}] and teams [${addedTeams}] as reviewers to Pull request ${pr.number}`
      );
    } catch (e) {
      logger.error(
        `Failure when adding reviewers to Pull request ${pr.number}`,
        e
      );
    }
  }
};

const examples$1 = [
  {
    description: "Initializes a git repository of contents in workspace and publish it to GitHub with default configuration.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          id: "publish",
          action: "publish:github",
          name: "Publish to GitHub",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner"
          }
        }
      ]
    })
  },
  {
    description: "Add a description.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          id: "publish",
          action: "publish:github",
          name: "Publish to GitHub",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            description: "Initialize a git repository"
          }
        }
      ]
    })
  },
  {
    description: "Change visibility of the repository.",
    example: yaml__default["default"].stringify({
      steps: [
        {
          id: "publish",
          action: "publish:github",
          name: "Publish to GitHub",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            description: "Initialize a git repository",
            repoVisibility: "public"
          }
        }
      ]
    })
  }
];

function createPublishGithubAction(options) {
  const { integrations, config, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "publish:github",
    description: "Initializes a git repository of contents in workspace and publishes it to GitHub.",
    examples: examples$1,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl"],
        properties: {
          repoUrl: repoUrl,
          description: description,
          homepage: homepage,
          access: access,
          bypassPullRequestAllowances: bypassPullRequestAllowances,
          requiredApprovingReviewCount: requiredApprovingReviewCount,
          restrictions: restrictions,
          requireCodeOwnerReviews: requireCodeOwnerReviews,
          dismissStaleReviews: dismissStaleReviews,
          requiredStatusCheckContexts: requiredStatusCheckContexts,
          requireBranchesToBeUpToDate: requireBranchesToBeUpToDate,
          requiredConversationResolution: requiredConversationResolution,
          repoVisibility: repoVisibility,
          defaultBranch: defaultBranch,
          protectDefaultBranch: protectDefaultBranch,
          protectEnforceAdmins: protectEnforceAdmins,
          deleteBranchOnMerge: deleteBranchOnMerge,
          gitCommitMessage: gitCommitMessage,
          gitAuthorName: gitAuthorName,
          gitAuthorEmail: gitAuthorEmail,
          allowMergeCommit: allowMergeCommit,
          allowSquashMerge: allowSquashMerge,
          squashMergeCommitTitle: squashMergeCommitTitle,
          squashMergeCommitMessage: squashMergeCommitMessage,
          allowRebaseMerge: allowRebaseMerge,
          allowAutoMerge: allowAutoMerge,
          sourcePath: sourcePath,
          collaborators: collaborators,
          hasProjects: hasProjects,
          hasWiki: hasWiki,
          hasIssues: hasIssues,
          token: token,
          topics: topics,
          repoVariables: repoVariables,
          secrets: secrets,
          requiredCommitSigning: requiredCommitSigning
        }
      },
      output: {
        type: "object",
        properties: {
          remoteUrl: remoteUrl,
          repoContentsUrl: repoContentsUrl,
          commitHash: commitHash
        }
      }
    },
    async handler(ctx) {
      const {
        repoUrl,
        description,
        homepage,
        access,
        requireCodeOwnerReviews = false,
        dismissStaleReviews = false,
        bypassPullRequestAllowances,
        requiredApprovingReviewCount = 1,
        restrictions,
        requiredStatusCheckContexts = [],
        requireBranchesToBeUpToDate = true,
        requiredConversationResolution = false,
        repoVisibility = "private",
        defaultBranch = "master",
        protectDefaultBranch = true,
        protectEnforceAdmins = true,
        deleteBranchOnMerge = false,
        gitCommitMessage,
        gitAuthorName,
        gitAuthorEmail,
        allowMergeCommit = true,
        allowSquashMerge = true,
        squashMergeCommitTitle = "COMMIT_OR_PR_TITLE",
        squashMergeCommitMessage = "COMMIT_MESSAGES",
        allowRebaseMerge = true,
        allowAutoMerge = false,
        collaborators,
        hasProjects = void 0,
        hasWiki = void 0,
        hasIssues = void 0,
        topics,
        repoVariables,
        secrets,
        token: providedToken,
        requiredCommitSigning = false
      } = ctx.input;
      const octokitOptions = await getOctokitOptions({
        integrations,
        credentialsProvider: githubCredentialsProvider,
        token: providedToken,
        repoUrl
      });
      const client = new octokit.Octokit(octokitOptions);
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const newRepo = await createGithubRepoWithCollaboratorsAndTopics(
        client,
        repo,
        owner,
        repoVisibility,
        description,
        homepage,
        deleteBranchOnMerge,
        allowMergeCommit,
        allowSquashMerge,
        squashMergeCommitTitle,
        squashMergeCommitMessage,
        allowRebaseMerge,
        allowAutoMerge,
        access,
        collaborators,
        hasProjects,
        hasWiki,
        hasIssues,
        topics,
        repoVariables,
        secrets,
        ctx.logger
      );
      const remoteUrl = newRepo.clone_url;
      const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`;
      const commitResult = await initRepoPushAndProtect(
        remoteUrl,
        octokitOptions.auth,
        ctx.workspacePath,
        ctx.input.sourcePath,
        defaultBranch,
        protectDefaultBranch,
        protectEnforceAdmins,
        owner,
        client,
        repo,
        requireCodeOwnerReviews,
        bypassPullRequestAllowances,
        requiredApprovingReviewCount,
        restrictions,
        requiredStatusCheckContexts,
        requireBranchesToBeUpToDate,
        requiredConversationResolution,
        config,
        ctx.logger,
        gitCommitMessage,
        gitAuthorName,
        gitAuthorEmail,
        dismissStaleReviews,
        requiredCommitSigning
      );
      ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
      ctx.output("remoteUrl", remoteUrl);
      ctx.output("repoContentsUrl", repoContentsUrl);
    }
  });
}

const examples = [
  {
    description: "GitHub alphanumric autolink reference",
    example: yaml__default["default"].stringify({
      steps: [
        {
          action: "github:autolinks:create",
          name: "Create an autolink reference",
          input: {
            repoUrl: "github.com?repo=repo&owner=owner",
            keyPrefix: "TICKET-",
            urlTemplate: "https://example.com/TICKET?query=<num>",
            isAlphanumeric: false
          }
        }
      ]
    })
  }
];

function createGithubAutolinksAction(options) {
  const { integrations, githubCredentialsProvider } = options;
  return pluginScaffolderNode.createTemplateAction({
    id: "github:autolinks:create",
    description: "Create an autolink reference for a repository",
    examples,
    schema: {
      input: {
        type: "object",
        required: ["repoUrl", "keyPrefix", "urlTemplate"],
        properties: {
          repoUrl: {
            title: "Repository Location",
            description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
            type: "string"
          },
          keyPrefix: {
            title: "Key Prefix",
            description: "This prefix appended by certain characters will generate a link any time it is found in an issue, pull request, or commit.",
            type: "string"
          },
          urlTemplate: {
            title: "URL Template",
            description: "The URL must contain <num> for the reference number. <num> matches different characters depending on the value of isAlphanumeric.",
            type: "string"
          },
          isAlphanumeric: {
            title: "Alphanumeric",
            description: "Whether this autolink reference matches alphanumeric characters. If true, the <num> parameter of the url_template matches alphanumeric characters A-Z (case insensitive), 0-9, and -. If false, this autolink reference only matches numeric characters. Default: true",
            type: "boolean"
          },
          token: {
            title: "Authentication Token",
            type: "string",
            description: "The token to use for authorization to GitHub"
          }
        }
      }
    },
    async handler(ctx) {
      const { repoUrl, keyPrefix, urlTemplate, isAlphanumeric, token } = ctx.input;
      ctx.logger.info(`Creating autolink reference for repo ${repoUrl}`);
      const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
      if (!owner) {
        throw new errors.InputError("Invalid repository owner provided in repoUrl");
      }
      const client = new octokit.Octokit(
        await getOctokitOptions({
          integrations,
          repoUrl,
          credentialsProvider: githubCredentialsProvider,
          token
        })
      );
      await client.rest.repos.createAutolink({
        owner,
        repo,
        key_prefix: keyPrefix,
        url_template: urlTemplate,
        is_alphanumeric: isAlphanumeric
      });
      ctx.logger.info(`Autolink reference created successfully`);
    }
  });
}

exports.createGithubActionsDispatchAction = createGithubActionsDispatchAction;
exports.createGithubAutolinksAction = createGithubAutolinksAction;
exports.createGithubDeployKeyAction = createGithubDeployKeyAction;
exports.createGithubEnvironmentAction = createGithubEnvironmentAction;
exports.createGithubIssuesLabelAction = createGithubIssuesLabelAction;
exports.createGithubRepoCreateAction = createGithubRepoCreateAction;
exports.createGithubRepoPushAction = createGithubRepoPushAction;
exports.createGithubWebhookAction = createGithubWebhookAction;
exports.createPublishGithubAction = createPublishGithubAction;
exports.createPublishGithubPullRequestAction = createPublishGithubPullRequestAction;
//# sourceMappingURL=index.cjs.js.map
