diff --git a/README.md b/README.md index a1f09fb9..9f1a8815 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ Add a step like this to your workflow: Multiple options let you provide the `git` arguments that you want the action to use. It's important to note that these arguments **are not actually used with a CLI command**, but they are parsed by a package called [`string-argv`](https://npm.im/string-argv), and then used with [`simple-git`](https://npm.im/simple-git). What does this mean for you? It means that strings that contain a lot of nested quotes may be parsed incorrectly, and that specific ways of declaring arguments may not be supported by these libraries. If you're having issues with your argument strings you can check whether they're being parsed correctly either by [enabling debug logging](https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging) for your workflow runs or by testing it directly with `string-argv` ([RunKit demo](https://npm.runkit.com/string-argv)): if each argument and option is parsed correctly you'll see an array where every string is an option or value. -Remote-helper overrides (`--upload-pack`, `--receive-pack`, `--exec`, and abbreviations of those) are rejected: they can make git run an arbitrary Git transport program during fetch/pull/push. +Remote-helper overrides (`--upload-pack`, `--receive-pack`, `--exec`, and abbreviations of those) are rejected on every token, including values after `-u` / `-m`: they can make git run an arbitrary Git transport program during fetch/pull/push. Message-from-file flags (`-F`, `--file`, abbreviations such as `--fi`, and short-option clusters that include `F` such as `-aF`) are rejected: they can embed arbitrary runner filesystem contents into a tag or commit message and, with a push, into the repository history. Unmatched `'` / `"` quotes are also rejected: `string-argv` can otherwise split on an odd quote and turn part of a value into extra flags (for example a branch name like `fix'--force` becoming `fix` plus `--force`). Do not interpolate untrusted data (for example values from `github.event.*`, `github.head_ref`, or repository content that contributors can edit) into `fetch`, `pull`, `push`, `tag`, `tag_push`, or `commit` without sanitizing them first. When the branch name is dynamic, prefer the default `push: true` with [`new_branch`](#creating-a-new-branch) instead of embedding the ref in a custom `push` string. diff --git a/lib/index.js b/lib/index.js index 0fe78108..74a8189a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,4 +7,4 @@ var uo=Symbol("NOT_RESOLVED");var go=Symbol("MERGE_KEY");function defineScalarTa /* v8 ignore next -- @preserve */ ()=>new ArrayBuffer(0))}}function isJSONResponse(e){return e.type==="application/json"||e.type==="application/scim+json"}function toErrorMessage(e){if(typeof e==="string"){return e}if(e instanceof ArrayBuffer){return"Unknown error"}if("message"in e){const t="documentation_url"in e?` - ${e.documentation_url}`:"";return Array.isArray(e.errors)?`${e.message}: ${e.errors.map(e=>JSON.stringify(e)).join(", ")}${t}`:`${e.message}${t}`}return`Unknown error: ${JSON.stringify(e)}`}function dist_bundle_withDefaults(e,t){const r=e.defaults(t);const newApi=function(e,t){const s=r.merge(e,t);if(!s.request||!s.request.hook){return fetchWrapper(r.parse(s))}const request2=(e,t)=>fetchWrapper(r.parse(r.merge(e,t)));Object.assign(request2,{endpoint:r,defaults:dist_bundle_withDefaults.bind(null,r)});return s.request.hook(request2,s)};return Object.assign(newApi,{endpoint:r,defaults:dist_bundle_withDefaults.bind(null,r)})}var jA=dist_bundle_withDefaults(JA,qA); /* v8 ignore next -- @preserve */ -/* v8 ignore else -- @preserve */var zA="0.0.0-development";function _buildMessageForResponseErrors(e){return`Request failed due to following response errors:\n`+e.errors.map(e=>` - ${e.message}`).join("\n")}var KA=class extends Error{constructor(e,t,r){super(_buildMessageForResponseErrors(r));this.request=e;this.headers=t;this.response=r;this.errors=r.errors;this.data=r.data;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}name="GraphqlResponseError";errors;data};var ZA=["method","baseUrl","url","headers","request","query","mediaType","operationName"];var $A=["query","method","url"];var XA=/\/api\/v3\/?$/;function graphql(e,t,r){if(r){if(typeof t==="string"&&"query"in r){return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`))}for(const e in r){if(!$A.includes(e))continue;return Promise.reject(new Error(`[@octokit/graphql] "${e}" cannot be used as variable name`))}}const s=typeof t==="string"?Object.assign({query:t},r):t;const n=Object.keys(s).reduce((e,t)=>{if(ZA.includes(t)){e[t]=s[t];return e}if(!e.variables){e.variables={}}e.variables[t]=s[t];return e},{});const o=s.baseUrl||e.endpoint.DEFAULTS.baseUrl;if(XA.test(o)){n.url=o.replace(XA,"/api/graphql")}return e(n).then(e=>{if(e.data.errors){const t={};for(const r of Object.keys(e.headers)){t[r]=e.headers[r]}throw new KA(n,t,e.data)}return e.data.data})}function graphql_dist_bundle_withDefaults(e,t){const r=e.defaults(t);const newApi=(e,t)=>graphql(r,e,t);return Object.assign(newApi,{defaults:graphql_dist_bundle_withDefaults.bind(null,r),endpoint:r.endpoint})}var ea=graphql_dist_bundle_withDefaults(jA,{headers:{"user-agent":`octokit-graphql.js/${zA} ${getUserAgent()}`},method:"POST",url:"/graphql"});function withCustomRequest(e){return graphql_dist_bundle_withDefaults(e,{method:"POST",url:"/graphql"})}var ta="(?:[a-zA-Z0-9_-]+)";var ra="\\.";var sa=new RegExp(`^${ta}${ra}${ta}${ra}${ta}$`);var na=sa.test.bind(sa);async function auth(e){const t=na(e);const r=e.startsWith("v1.")||e.startsWith("ghs_");const s=e.startsWith("ghu_");const n=t?"app":r?"installation":s?"user-to-server":"oauth";return{type:"token",token:e,tokenType:n}}function withAuthorizationPrefix(e){if(e.split(/\./).length===3){return`bearer ${e}`}return`token ${e}`}async function hook(e,t,r,s){const n=t.endpoint.merge(r,s);n.headers.authorization=withAuthorizationPrefix(e);return t(n)}var oa=function createTokenAuth2(e){if(!e){throw new Error("[@octokit/auth-token] No token passed to createTokenAuth")}if(typeof e!=="string"){throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string")}e=e.replace(/^(token|bearer) +/i,"");return Object.assign(auth.bind(null,e),{hook:hook.bind(null,e)})};const ia="7.0.6";const dist_src_noop=()=>{};const Aa=console.warn.bind(console);const aa=console.error.bind(console);function dist_src_createLogger(e={}){if(typeof e.debug!=="function"){e.debug=dist_src_noop}if(typeof e.info!=="function"){e.info=dist_src_noop}if(typeof e.warn!=="function"){e.warn=Aa}if(typeof e.error!=="function"){e.error=aa}return e}const ca=`octokit-core.js/${ia} ${getUserAgent()}`;class Octokit{static VERSION=ia;static defaults(e){const t=class extends(this){constructor(...t){const r=t[0]||{};if(typeof e==="function"){super(e(r));return}super(Object.assign({},e,r,r.userAgent&&e.userAgent?{userAgent:`${r.userAgent} ${e.userAgent}`}:null))}};return t}static plugins=[];static plugin(...e){const t=this.plugins;const r=class extends(this){static plugins=t.concat(e.filter(e=>!t.includes(e)))};return r}constructor(e={}){const t=new OA.Collection;const r={baseUrl:jA.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},e.request,{hook:t.bind(null,"request")}),mediaType:{previews:[],format:""}};r.headers["user-agent"]=e.userAgent?`${e.userAgent} ${ca}`:ca;if(e.baseUrl){r.baseUrl=e.baseUrl}if(e.previews){r.mediaType.previews=e.previews}if(e.timeZone){r.headers["time-zone"]=e.timeZone}this.request=jA.defaults(r);this.graphql=withCustomRequest(this.request).defaults(r);this.log=dist_src_createLogger(e.log);this.hook=t;if(!e.authStrategy){if(!e.auth){this.auth=async()=>({type:"unauthenticated"})}else{const r=oa(e.auth);t.wrap("request",r.hook);this.auth=r}}else{const{authStrategy:r,...s}=e;const n=r(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:s},e.auth));t.wrap("request",n.hook);this.auth=n}const s=this.constructor;for(let t=0;t({async next(){if(!l)return{done:true};try{const e=await n({method:o,url:l,headers:a});const t=normalizePaginatedListResponse(e);l=((t.headers.link||"").match(/<([^<>]+)>;\s*rel="next"/)||[])[1];if(!l&&"total_commits"in t.data){const e=new URL(t.url);const r=e.searchParams;const s=parseInt(r.get("page")||"1",10);const n=parseInt(r.get("per_page")||"250",10);if(s*n{if(n.done){return t}let o=false;function done(){o=true}t=t.concat(s?s(n.value,done):n.value.data);if(o){return t}return gather(e,t,r,s)})}var Ea=Object.assign(paginate,{iterator:iterator});var fa=null&&["GET /advisories","GET /app/hook/deliveries","GET /app/installation-requests","GET /app/installations","GET /assignments/{assignment_id}/accepted_assignments","GET /classrooms","GET /classrooms/{classroom_id}/assignments","GET /enterprises/{enterprise}/code-security/configurations","GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories","GET /enterprises/{enterprise}/dependabot/alerts","GET /enterprises/{enterprise}/teams","GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships","GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations","GET /events","GET /gists","GET /gists/public","GET /gists/starred","GET /gists/{gist_id}/comments","GET /gists/{gist_id}/commits","GET /gists/{gist_id}/forks","GET /installation/repositories","GET /issues","GET /licenses","GET /marketplace_listing/plans","GET /marketplace_listing/plans/{plan_id}/accounts","GET /marketplace_listing/stubbed/plans","GET /marketplace_listing/stubbed/plans/{plan_id}/accounts","GET /networks/{owner}/{repo}/events","GET /notifications","GET /organizations","GET /organizations/{org}/dependabot/repository-access","GET /orgs/{org}/actions/cache/usage-by-repository","GET /orgs/{org}/actions/hosted-runners","GET /orgs/{org}/actions/permissions/repositories","GET /orgs/{org}/actions/permissions/self-hosted-runners/repositories","GET /orgs/{org}/actions/runner-groups","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners","GET /orgs/{org}/actions/runners","GET /orgs/{org}/actions/secrets","GET /orgs/{org}/actions/secrets/{secret_name}/repositories","GET /orgs/{org}/actions/variables","GET /orgs/{org}/actions/variables/{name}/repositories","GET /orgs/{org}/attestations/repositories","GET /orgs/{org}/attestations/{subject_digest}","GET /orgs/{org}/blocks","GET /orgs/{org}/campaigns","GET /orgs/{org}/code-scanning/alerts","GET /orgs/{org}/code-security/configurations","GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories","GET /orgs/{org}/codespaces","GET /orgs/{org}/codespaces/secrets","GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories","GET /orgs/{org}/copilot/billing/seats","GET /orgs/{org}/copilot/metrics","GET /orgs/{org}/dependabot/alerts","GET /orgs/{org}/dependabot/secrets","GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories","GET /orgs/{org}/events","GET /orgs/{org}/failed_invitations","GET /orgs/{org}/hooks","GET /orgs/{org}/hooks/{hook_id}/deliveries","GET /orgs/{org}/insights/api/route-stats/{actor_type}/{actor_id}","GET /orgs/{org}/insights/api/subject-stats","GET /orgs/{org}/insights/api/user-stats/{user_id}","GET /orgs/{org}/installations","GET /orgs/{org}/invitations","GET /orgs/{org}/invitations/{invitation_id}/teams","GET /orgs/{org}/issues","GET /orgs/{org}/members","GET /orgs/{org}/members/{username}/codespaces","GET /orgs/{org}/migrations","GET /orgs/{org}/migrations/{migration_id}/repositories","GET /orgs/{org}/organization-roles/{role_id}/teams","GET /orgs/{org}/organization-roles/{role_id}/users","GET /orgs/{org}/outside_collaborators","GET /orgs/{org}/packages","GET /orgs/{org}/packages/{package_type}/{package_name}/versions","GET /orgs/{org}/personal-access-token-requests","GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories","GET /orgs/{org}/personal-access-tokens","GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories","GET /orgs/{org}/private-registries","GET /orgs/{org}/projects","GET /orgs/{org}/projectsV2","GET /orgs/{org}/projectsV2/{project_number}/fields","GET /orgs/{org}/projectsV2/{project_number}/items","GET /orgs/{org}/properties/values","GET /orgs/{org}/public_members","GET /orgs/{org}/repos","GET /orgs/{org}/rulesets","GET /orgs/{org}/rulesets/rule-suites","GET /orgs/{org}/rulesets/{ruleset_id}/history","GET /orgs/{org}/secret-scanning/alerts","GET /orgs/{org}/security-advisories","GET /orgs/{org}/settings/immutable-releases/repositories","GET /orgs/{org}/settings/network-configurations","GET /orgs/{org}/team/{team_slug}/copilot/metrics","GET /orgs/{org}/teams","GET /orgs/{org}/teams/{team_slug}/discussions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions","GET /orgs/{org}/teams/{team_slug}/invitations","GET /orgs/{org}/teams/{team_slug}/members","GET /orgs/{org}/teams/{team_slug}/projects","GET /orgs/{org}/teams/{team_slug}/repos","GET /orgs/{org}/teams/{team_slug}/teams","GET /projects/{project_id}/collaborators","GET /repos/{owner}/{repo}/actions/artifacts","GET /repos/{owner}/{repo}/actions/caches","GET /repos/{owner}/{repo}/actions/organization-secrets","GET /repos/{owner}/{repo}/actions/organization-variables","GET /repos/{owner}/{repo}/actions/runners","GET /repos/{owner}/{repo}/actions/runs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts","GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs","GET /repos/{owner}/{repo}/actions/secrets","GET /repos/{owner}/{repo}/actions/variables","GET /repos/{owner}/{repo}/actions/workflows","GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs","GET /repos/{owner}/{repo}/activity","GET /repos/{owner}/{repo}/assignees","GET /repos/{owner}/{repo}/attestations/{subject_digest}","GET /repos/{owner}/{repo}/branches","GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations","GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs","GET /repos/{owner}/{repo}/code-scanning/alerts","GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances","GET /repos/{owner}/{repo}/code-scanning/analyses","GET /repos/{owner}/{repo}/codespaces","GET /repos/{owner}/{repo}/codespaces/devcontainers","GET /repos/{owner}/{repo}/codespaces/secrets","GET /repos/{owner}/{repo}/collaborators","GET /repos/{owner}/{repo}/comments","GET /repos/{owner}/{repo}/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/commits","GET /repos/{owner}/{repo}/commits/{commit_sha}/comments","GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls","GET /repos/{owner}/{repo}/commits/{ref}/check-runs","GET /repos/{owner}/{repo}/commits/{ref}/check-suites","GET /repos/{owner}/{repo}/commits/{ref}/status","GET /repos/{owner}/{repo}/commits/{ref}/statuses","GET /repos/{owner}/{repo}/compare/{basehead}","GET /repos/{owner}/{repo}/compare/{base}...{head}","GET /repos/{owner}/{repo}/contributors","GET /repos/{owner}/{repo}/dependabot/alerts","GET /repos/{owner}/{repo}/dependabot/secrets","GET /repos/{owner}/{repo}/deployments","GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses","GET /repos/{owner}/{repo}/environments","GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies","GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps","GET /repos/{owner}/{repo}/environments/{environment_name}/secrets","GET /repos/{owner}/{repo}/environments/{environment_name}/variables","GET /repos/{owner}/{repo}/events","GET /repos/{owner}/{repo}/forks","GET /repos/{owner}/{repo}/hooks","GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries","GET /repos/{owner}/{repo}/invitations","GET /repos/{owner}/{repo}/issues","GET /repos/{owner}/{repo}/issues/comments","GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/issues/events","GET /repos/{owner}/{repo}/issues/{issue_number}/comments","GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by","GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking","GET /repos/{owner}/{repo}/issues/{issue_number}/events","GET /repos/{owner}/{repo}/issues/{issue_number}/labels","GET /repos/{owner}/{repo}/issues/{issue_number}/reactions","GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues","GET /repos/{owner}/{repo}/issues/{issue_number}/timeline","GET /repos/{owner}/{repo}/keys","GET /repos/{owner}/{repo}/labels","GET /repos/{owner}/{repo}/milestones","GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels","GET /repos/{owner}/{repo}/notifications","GET /repos/{owner}/{repo}/pages/builds","GET /repos/{owner}/{repo}/projects","GET /repos/{owner}/{repo}/pulls","GET /repos/{owner}/{repo}/pulls/comments","GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/pulls/{pull_number}/comments","GET /repos/{owner}/{repo}/pulls/{pull_number}/commits","GET /repos/{owner}/{repo}/pulls/{pull_number}/files","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments","GET /repos/{owner}/{repo}/releases","GET /repos/{owner}/{repo}/releases/{release_id}/assets","GET /repos/{owner}/{repo}/releases/{release_id}/reactions","GET /repos/{owner}/{repo}/rules/branches/{branch}","GET /repos/{owner}/{repo}/rulesets","GET /repos/{owner}/{repo}/rulesets/rule-suites","GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history","GET /repos/{owner}/{repo}/secret-scanning/alerts","GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations","GET /repos/{owner}/{repo}/security-advisories","GET /repos/{owner}/{repo}/stargazers","GET /repos/{owner}/{repo}/subscribers","GET /repos/{owner}/{repo}/tags","GET /repos/{owner}/{repo}/teams","GET /repos/{owner}/{repo}/topics","GET /repositories","GET /search/code","GET /search/commits","GET /search/issues","GET /search/labels","GET /search/repositories","GET /search/topics","GET /search/users","GET /teams/{team_id}/discussions","GET /teams/{team_id}/discussions/{discussion_number}/comments","GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /teams/{team_id}/discussions/{discussion_number}/reactions","GET /teams/{team_id}/invitations","GET /teams/{team_id}/members","GET /teams/{team_id}/projects","GET /teams/{team_id}/repos","GET /teams/{team_id}/teams","GET /user/blocks","GET /user/codespaces","GET /user/codespaces/secrets","GET /user/emails","GET /user/followers","GET /user/following","GET /user/gpg_keys","GET /user/installations","GET /user/installations/{installation_id}/repositories","GET /user/issues","GET /user/keys","GET /user/marketplace_purchases","GET /user/marketplace_purchases/stubbed","GET /user/memberships/orgs","GET /user/migrations","GET /user/migrations/{migration_id}/repositories","GET /user/orgs","GET /user/packages","GET /user/packages/{package_type}/{package_name}/versions","GET /user/public_emails","GET /user/repos","GET /user/repository_invitations","GET /user/social_accounts","GET /user/ssh_signing_keys","GET /user/starred","GET /user/subscriptions","GET /user/teams","GET /users","GET /users/{username}/attestations/{subject_digest}","GET /users/{username}/events","GET /users/{username}/events/orgs/{org}","GET /users/{username}/events/public","GET /users/{username}/followers","GET /users/{username}/following","GET /users/{username}/gists","GET /users/{username}/gpg_keys","GET /users/{username}/keys","GET /users/{username}/orgs","GET /users/{username}/packages","GET /users/{username}/projects","GET /users/{username}/projectsV2","GET /users/{username}/projectsV2/{project_number}/fields","GET /users/{username}/projectsV2/{project_number}/items","GET /users/{username}/received_events","GET /users/{username}/received_events/public","GET /users/{username}/repos","GET /users/{username}/social_accounts","GET /users/{username}/ssh_signing_keys","GET /users/{username}/starred","GET /users/{username}/subscriptions"];function isPaginatingEndpoint(e){if(typeof e==="string"){return fa.includes(e)}else{return false}}function paginateRest(e){return{paginate:Object.assign(paginate.bind(null,e),{iterator:iterator.bind(null,e)})}}paginateRest.VERSION=pa;const Ca=new Context;const Qa=getApiBaseUrl();const Ia={baseUrl:Qa,request:{agent:getProxyAgent(Qa),fetch:getProxyFetch(Qa)}};const Ba=Octokit.plugin(restEndpointMethods,paginateRest).defaults(Ia);function getOctokitOptions(e,t){const r=Object.assign({},t||{});const s=getAuthString(e,r);if(s){r.auth=s}const n=getUserAgentWithOrchestrationId(r.userAgent);if(n){r.userAgent=n}return r}const ma=new Context;function getOctokit(e,t,...r){const s=Ba.plugin(...r);return new s(getOctokitOptions(e,t))}function getOctokitClient(){const e=io_getInput("github_token");if(!e){throw new Error("github_token is required")}return getOctokit(e)}async function getUserInfo(e){if(!e)return undefined;const t=getOctokitClient();const r=await t.rest.users.getByUsername({username:e});core_debug(`Fetched github actor from the API: ${JSON.stringify(r?.data,null,2)}`);return{name:r?.data?.name,email:r?.data?.email}}const wa=/[\u0000-\u001F\u007F-\u009F\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/gu;function neutralizeLogString(e){return e.replace(wa,e=>{const t=e.codePointAt(0).toString(16).padStart(4,"0");return`\\u${t}`})}const ya="[Circular]";function neutralizeForLog(e,t=new WeakSet){if(typeof e==="string")return neutralizeLogString(e);if(typeof e==="number"||typeof e==="boolean"||e===null||e===undefined){return e}if(e instanceof Error){const t=new Error(neutralizeLogString(e.message));t.name=neutralizeLogString(e.name);if(e.stack){t.stack=neutralizeLogString(e.stack)}return t}if(Array.isArray(e)){if(t.has(e))return ya;t.add(e);return e.map(e=>neutralizeForLog(e,t))}if(typeof e==="object"){if(t.has(e))return ya;t.add(e);const r={};for(const[s,n]of Object.entries(e)){r[neutralizeLogString(s)]=neutralizeForLog(n,t)}return r}return e}function log(e,t){if(t)console.log(neutralizeForLog(t));if(e){const t=neutralizeForLog(e);if(typeof t==="string"||t instanceof Error){error(t)}else{error(String(t))}}}const ba=["user.name","user.email","author.name","author.email","committer.name","committer.email"];function pickGitIdentityConfig(e){const t={};for(const r of ba){if(Object.prototype.hasOwnProperty.call(e,r)){t[r]=e[r]}}return t}function assertValidBranchName(e){if(!e||!e.trim()){throw new Error("The new_branch value is empty.")}if(e.startsWith("-")){throw new Error(`The new_branch value '${e}' cannot start with '-' (it would be interpreted as a git option).`)}for(const t of e){const r=t.codePointAt(0);if(r<=31||r===127||r>=128&&r<=159||/\s/u.test(t)){throw new Error(`The new_branch value '${e}' contains whitespace or control characters.`)}}try{(0,ue.execFileSync)("git",["check-ref-format","--branch",e],{stdio:"ignore"})}catch{throw new Error(`The new_branch value '${e}' is not a valid git branch name.`)}}const ka=[{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];const Ta=[{canonical:"file",minPrefix:"fi"}];const Ra=[{canonical:"message",minPrefix:"mes"},{canonical:"local-user",minPrefix:"local-"},{canonical:"cleanup",minPrefix:"cleanup"},{canonical:"file",minPrefix:"fi"},{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];const Da=new Set(["m","u","F"]);function getLongOptionName(e){if(!e.startsWith("--")||e==="--")return undefined;const t=e.slice(2);const r=t.indexOf("=");return(r===-1?t:t.slice(0,r)).toLowerCase()}function longOptionHasInlineValue(e){if(!e.startsWith("--")||e==="--")return false;return e.slice(2).includes("=")}function matchesLongOptionPrefix(e,t){const r=getLongOptionName(e);if(!r)return false;return t.some(({canonical:e,minPrefix:t})=>r.length>=t.length&&e.startsWith(r))}function isDangerousRemoteHelperOption(e){return matchesLongOptionPrefix(e,ka)}function isDangerousMessageFileShortOption(e){if(!e.startsWith("-")||e.startsWith("--"))return false;const t=e.slice(1);for(let e=0;e` - ${e}`).join("\n");const r=e.map(e=>` git rm --cached -- ${e}`).join("\n");throw new Error(`Refusing to commit unexpected gitlink(s) (embedded git repository staged as mode 160000):\n${t}\n`+"Git records a nested .git directory as a gitlink, not as its files. "+`Remove the nested .git directory, or unstage the path(s) with:\n${r}`)}function parseInputArray(e){core_debug(`Parsing input array: ${e}`);try{const t=load(e);if(t&&Array.isArray(t)&&t.every(e=>typeof e==="string")){core_debug(`Input parsed as YAML array of length ${t.length}`);return t}}catch{}core_debug("Input parsed as single string");return[e]}function readJSON(e){let t;try{t=fs.readFileSync(e,{encoding:"utf8"})}catch{throw`Couldn't read file. File path: ${e}`}try{return JSON.parse(t)}catch{throw`Couldn't parse file to JSON. File path: ${e}`}}const Sa={committed:"false",commit_long_sha:undefined,commit_sha:undefined,pushed:"false",tagged:"false",tag_pushed:"false"};Object.entries(Sa).forEach(([e,t])=>setOutput(e,t));function io_getInput(e,t=false){if(t)return getBooleanInput(e);return getInput(e)}function io_setOutput(e,t){core_debug(`Setting output: ${e}=${t}`);Sa[e]=t;setOutput(e,t)}function parsePushAttempts(e){const t=e.trim();if(!/^\+?\d+$/.test(t)){throw new Error(`'${e}' is not a valid value for push_attempts. It must be a positive integer (≥ 1).`)}const r=Number.parseInt(t,10);if(!Number.isSafeInteger(r)||r<1){throw new Error(`'${e}' is not a valid value for push_attempts. It must be a positive integer (≥ 1).`)}return r}function logOutputs(){startGroup("Outputs");for(const e in Sa){info(`${e}: ${Sa[e]}`)}endGroup()}async function checkInputs(){function setInput(e,t){if(t)return process.env[`INPUT_${e.toUpperCase()}`]=t;else return delete process.env[`INPUT_${e.toUpperCase()}`]}function setDefault(e,t){if(!io_getInput(e))setInput(e,t);return io_getInput(e)}if(!io_getInput("add")&&!io_getInput("remove"))throw new Error("Both 'add' and 'remove' are empty, the action has nothing to do.");if(io_getInput("add")){const e=parseInputArray(io_getInput("add"));if(e.length===1)info("Add input parsed as single string, running 1 git add command.");else if(e.length>1)info(`Add input parsed as string array, running ${e.length} git add commands.`);else setFailed("Add input: array length < 1")}if(io_getInput("remove")){const e=parseInputArray(io_getInput("remove")||"");if(e.length===1)info("Remove input parsed as single string, running 1 git rm command.");else if(e.length>1)info(`Remove input parsed as string array, running ${e.length} git rm commands.`);else setFailed("Remove input: array length < 1")}const e=["github_actor","user_info","github_actions"];if(!e.includes(io_getInput("default_author")))throw new Error(`'${io_getInput("default_author")}' is not a valid value for default_author. Valid values: ${e.join(", ")}`);if(io_getInput("dry_run",true))info("> Dry run enabled: no mutating git operations will be performed.");if(io_getInput("fetch")){let e;try{e=io_getInput("fetch",true)}catch{e=io_getInput("fetch")}core_debug(`Current fetch option: '${e}' (parsed as ${typeof e})`)}let t,r;switch(io_getInput("default_author")){case"github_actor":{t=process.env.GITHUB_ACTOR??"";r=`${process.env.GITHUB_ACTOR}@users.noreply.github.com`;break}case"user_info":{if(!io_getInput("author_name")||!io_getInput("author_email")){const e=await getUserInfo(process.env.GITHUB_ACTOR);if(!e?.name)warning("Couldn't fetch author name, filling with github_actor.");if(!e?.email)warning("Couldn't fetch author email, filling with github_actor.");e?.name&&(t=e?.name);e?.email&&(r=e.email);if(t&&r)break}!t&&(t=process.env.GITHUB_ACTOR??"");!r&&(r=`${process.env.GITHUB_ACTOR}@users.noreply.github.com`);break}case"github_actions":{t="github-actions";r="41898282+github-actions[bot]@users.noreply.github.com";break}default:throw new Error("This should not happen, please contact the author of this action. (checkInputs.author)")}setDefault("author_name",t);setDefault("author_email",r);info(`> Using '${io_getInput("author_name")} <${io_getInput("author_email")}>' as author.`);if(io_getInput("committer_name")||io_getInput("committer_email"))info(`> Using custom committer info: ${io_getInput("committer_name")||io_getInput("author_name")+" [from author info]"} <${io_getInput("committer_email")||io_getInput("author_email")+" [from author info]"}>`);setDefault("committer_name",io_getInput("author_name"));setDefault("committer_email",io_getInput("author_email"));core_debug(`Committer: ${io_getInput("committer_name")} <${io_getInput("committer_email")}>`);setDefault("message",`Commit from GitHub Actions (${process.env.GITHUB_WORKFLOW})`);info(`> Using "${io_getInput("message")}" as commit message.`);const s=io_getInput("new_branch");if(s)assertValidBranchName(s);const n=["ignore","exitImmediately","exitAtEnd"];if(!n.includes(io_getInput("pathspec_error_handling")))throw new Error(`"${io_getInput("pathspec_error_handling")}" is not a valid value for the 'pathspec_error_handling' input. Valid values are: ${n.join(", ")}`);if(io_getInput("pull")==="NO-PULL")warning("`NO-PULL` is a legacy option for the `pull` input. If you don't want the action to pull the repo, simply remove this input.");if(io_getInput("push")){let e;try{e=io_getInput("push",true)}catch{e=io_getInput("push")}core_debug(`Current push option: '${e}' (parsed as ${typeof e})`)}const o=parsePushAttempts(io_getInput("push_attempts")||"1");core_debug(`Current push_attempts option: ${o}`);if(o>1&&!io_getInput("pull")){warning("push_attempts is greater than 1 but pull is not set. Retries will re-run push only; without pull (e.g. --rebase), concurrent remote updates are unlikely to recover.")}if(!io_getInput("github_token"))warning("No github_token has been detected, the action may fail if it needs to use the API")}const Fa=u.join(process.cwd(),io_getInput("cwd")||"");const va=lo({baseDir:Fa});const Ua=[];info(`Running in ${Fa}`);(async()=>{await checkInputs();const e=io_getInput("dry_run",true);startGroup("Internal logs");info(e?"> Staging files (dry run)...":"> Staging files...");const t=io_getInput("pathspec_error_handling")==="ignore"?"pathspec":"none";let r=false;if(io_getInput("add")){info(e?"> Adding files (dry run)...":"> Adding files...");const s=await add(t,e);if(e)r=r||s.some(e=>typeof e==="string"&&e.trim().length>0)}else info("> No files to add.");if(io_getInput("remove")){info(e?"> Removing files (dry run)...":"> Removing files...");const s=await main_remove(t,e);if(e)r=r||s.some(e=>{if(e===null||e===undefined)return false;const t=typeof e==="string"?e:String(e);return t.trim().length>0})}else info("> No files to remove.");info("> Checking for uncommitted changes in the git working tree...");const s=(await va.diffSummary(["--cached"])).files.length;const n=matchGitArgs(io_getInput("commit")||"").includes("--allow-empty");if(s>0||r||n){info(e?`> Dry run: would proceed (${s} already staged`+`${r?", staging probes reported changes":""}`+`${n?", --allow-empty":""}).`:`> Found ${s} changed files.`);core_debug(`--allow-empty argument detected: ${n}`);if(e){await logDryRunRemainingSteps();endGroup();info("> Dry run completed. No changes were made.");return}await va.addConfig("user.email",io_getInput("author_email"),undefined,log).addConfig("user.name",io_getInput("author_name"),undefined,log).addConfig("author.email",io_getInput("author_email"),undefined,log).addConfig("author.name",io_getInput("author_name"),undefined,log).addConfig("committer.email",io_getInput("committer_email"),undefined,log).addConfig("committer.name",io_getInput("committer_name"),undefined,log);if(isDebug()){const e=pickGitIdentityConfig((await va.listConfig()).all);core_debug(Object.keys(e).length?"> Current git identity config\n"+JSON.stringify(e,null,2):"> Git identity config set (no identity keys present in listConfig)")}let o;try{o=io_getInput("fetch",true)}catch{o=io_getInput("fetch")}if(o){info("> Fetching repo...");await va.fetch(matchGitArgs(o===true?"":o),log)}else info("> Not fetching repo.");const a=io_getInput("new_branch");if(a){info("> Checking-out branch...");if(!o)warning("Creating a new branch without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.");await va.checkout([a]).then(()=>{log(undefined,`'${a}' branch already existed.`)}).catch(()=>{log(undefined,`Creating '${a}' branch.`);return va.checkout(["-b",a],log)})}const l=io_getInput("pull");if(l){await pullFromRemote(l,{restage:true,ignoreErrors:t})}else info("> Not pulling from repo.");info("> Creating commit...");const u=await va.commit(io_getInput("message"),matchGitArgs(io_getInput("commit")||""));log(undefined,u);if(!u.commit){throw new Error("Commit did not produce a SHA; refusing to report committed=true.")}io_setOutput("committed","true");io_setOutput("commit_long_sha",u.commit);io_setOutput("commit_sha",u.commit.substring(0,7));if(io_getInput("tag")){info("> Tagging commit...");if(!o)warning("Creating a tag without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.");await va.tag(matchGitArgs(io_getInput("tag")||""),(e,t)=>{if(t)io_setOutput("tagged","true");return log(e,t)}).then(e=>{io_setOutput("tagged","true");return log(null,e)}).catch(e=>setFailed(e))}else info("> No tag info provided.");let g;try{g=io_getInput("push",true)}catch{g=io_getInput("push")}if(g){const e=parsePushAttempts(io_getInput("push_attempts")||"1");for(let r=1;r<=e;r++){try{info(e>1?`> Pushing commit to repo (attempt ${r}/${e})...`:"> Pushing commit to repo...");await pushCommit(g);break}catch(s){if(r===e)throw s;const n=s instanceof Error?s.message:String(s);warning(`Push failed (attempt ${r}/${e}): ${neutralizeLogString(n)}`);if(l){await pullFromRemote(l,{restage:false,ignoreErrors:t});const e=(await va.revparse(["HEAD"])).trim();io_setOutput("commit_long_sha",e);io_setOutput("commit_sha",e.substring(0,7))}}}if(io_getInput("tag")){info("> Pushing tags to repo...");await va.pushTags("origin",matchGitArgs(io_getInput("tag_push")||"")).then(e=>{io_setOutput("tag_pushed","true");return log(null,e)}).catch(e=>setFailed(e))}else info("> No tags to push.")}else info("> Not pushing anything.");endGroup();info("> Task completed.")}else{endGroup();info(e?"> Dry run: working tree clean. Nothing would be committed.":"> Working tree clean. Nothing to commit.")}})().then(()=>{if(Ua.length===1)throw Ua[0];else if(Ua.length>1){Ua.forEach(e=>error(e));throw"There have been multiple runtime errors."}}).then(logOutputs).catch(e=>{endGroup();logOutputs();setFailed(e)});async function logDryRunRemainingSteps(){info(`> Would set git identity: ${io_getInput("author_name")} <${io_getInput("author_email")}> (committer: ${io_getInput("committer_name")} <${io_getInput("committer_email")}>)`);let e;try{e=io_getInput("fetch",true)}catch{e=io_getInput("fetch")}if(e){info(`> Would fetch repo${e===true?"":` with: ${e}`}.`)}else info("> Would not fetch repo.");const t=io_getInput("new_branch");if(t){info(`> Would check out branch '${t}'.`);if(!e)warning("Creating a new branch without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.")}const r=io_getInput("pull");if(r)info(`> Would pull from remote with: ${r}.`);else info("> Would not pull from repo.");info(`> Would create commit with message: "${io_getInput("message")}"${io_getInput("commit")?` (extra args: ${io_getInput("commit")})`:""}.`);if(io_getInput("tag")){info(`> Would tag commit with: ${io_getInput("tag")}.`);if(!e)warning("Creating a tag without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.")}else info("> No tag info provided.");let s;try{s=io_getInput("push",true)}catch{s=io_getInput("push")}if(s){const e=parsePushAttempts(io_getInput("push_attempts")||"1");if(s===true){const t=io_getInput("new_branch");info(t?`> Would push commit to repo (set upstream for '${t}')${e>1?` with up to ${e} attempts`:""}.`:`> Would push commit to repo${e>1?` with up to ${e} attempts`:""}.`)}else info(`> Would push commit to repo with: ${s}${e>1?` (up to ${e} attempts)`:""}.`);if(io_getInput("tag")){info(`> Would push tags to repo${io_getInput("tag_push")?` with: ${io_getInput("tag_push")}`:""}.`)}else info("> No tags to push.")}else info("> Would not push anything.")}async function pullFromRemote(e,t){info("> Pulling from remote...");core_debug(`Current git pull arguments: ${e}`);await va.fetch(undefined,log).pull(undefined,undefined,matchGitArgs(e),log);info("> Checking for conflicts...");const r=await va.status(undefined,log);if(r.conflicted.length){throw new Error(`There are ${r.conflicted.length} conflicting files: ${r.conflicted.map(neutralizeLogString).join(", ")}`)}info("> No conflicts found.");if(t.restage){info("> Re-staging files...");if(io_getInput("add"))await add(t.ignoreErrors);if(io_getInput("remove"))await main_remove(t.ignoreErrors)}}async function pushCommit(e){if(e===true){const e=io_getInput("new_branch");if(e){core_debug(`Running: git push --set-upstream origin -- ${e}`);await va.raw(["push","--set-upstream","origin","--",e],(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}else{core_debug("Running: git push origin --set-upstream");await va.push("origin",undefined,{"--set-upstream":null},(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}else{core_debug(`Running: git push ${e}`);await va.push(undefined,undefined,matchGitArgs(e),(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}async function add(e="none",t=false){const r=io_getInput("add");if(!r)return[];const s=parseInputArray(r);const n=[];for(const r of s){const s=t?["--dry-run",...matchGitArgs(r)]:matchGitArgs(r);n.push(await va.add(s,(t,r)=>log(e==="all"?null:t,r)).catch(t=>{if(e==="all")return;if(t.message.includes("fatal: pathspec")&&t.message.includes("did not match any files")){if(e==="pathspec")return;const t=io_getInput("pathspec_error_handling"),s=new Error(`Add command did not match any file: git add ${r}`);if(t==="exitImmediately")throw s;if(t==="exitAtEnd")Ua.push(s)}else throw t}))}if(t){await assertGitlinksWithTempIndex(s,e)}else{const e=await va.raw(["diff","--cached","--raw"]);assertNoUnexpectedGitlinks(findUnexpectedGitlinks(e))}return n}async function assertGitlinksWithTempIndex(e,t){const r=u.join(n.tmpdir(),`add-and-commit-${process.pid}-${Date.now()}.index`);try{const s=(await va.raw(["rev-parse","--git-path","index"])).trim();const n=u.isAbsolute(s)?s:u.join(Fa,s);if(l.existsSync(n)){l.copyFileSync(n,r)}else{const e=lo({baseDir:Fa}).env({...process.env,GIT_INDEX_FILE:r});const t=await va.raw(["rev-parse","--verify","HEAD"]).then(()=>true).catch(()=>false);if(t){await e.raw(["read-tree","HEAD"])}else{await e.raw(["read-tree","--empty"])}}const o=lo({baseDir:Fa}).env({...process.env,GIT_INDEX_FILE:r});for(const r of e){await o.add(matchGitArgs(r),(e,r)=>log(t==="all"?null:e,r)).catch(e=>{if(t==="all")return;if(e.message.includes("fatal: pathspec")&&e.message.includes("did not match any files")){if(t==="pathspec")return;const e=io_getInput("pathspec_error_handling");if(e==="exitImmediately"){throw new Error(`Add command did not match any file: git add ${r}`)}return}throw e})}const a=await o.raw(["diff","--cached","--raw"]);assertNoUnexpectedGitlinks(findUnexpectedGitlinks(a))}finally{l.rmSync(r,{force:true});l.rmSync(`${r}.lock`,{force:true})}}async function main_remove(e="none",t=false){const r=io_getInput("remove");if(!r)return[];const s=parseInputArray(r);const n=[];for(const r of s){const s=t?["--dry-run",...matchGitArgs(r)]:matchGitArgs(r);n.push(await va.rm(s,(t,r)=>log(e==="all"?null:t,r)).catch(t=>{if(e==="all")return;if(t.message.includes("fatal: pathspec")&&t.message.includes("did not match any files")){if(e==="pathspec")return;const t=io_getInput("pathspec_error_handling"),s=new Error(`Remove command did not match any file:\n git rm ${r}`);if(t==="exitImmediately")throw s;if(t==="exitAtEnd")Ua.push(s)}else throw t}))}return n} \ No newline at end of file +/* v8 ignore else -- @preserve */var zA="0.0.0-development";function _buildMessageForResponseErrors(e){return`Request failed due to following response errors:\n`+e.errors.map(e=>` - ${e.message}`).join("\n")}var KA=class extends Error{constructor(e,t,r){super(_buildMessageForResponseErrors(r));this.request=e;this.headers=t;this.response=r;this.errors=r.errors;this.data=r.data;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}name="GraphqlResponseError";errors;data};var ZA=["method","baseUrl","url","headers","request","query","mediaType","operationName"];var $A=["query","method","url"];var XA=/\/api\/v3\/?$/;function graphql(e,t,r){if(r){if(typeof t==="string"&&"query"in r){return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`))}for(const e in r){if(!$A.includes(e))continue;return Promise.reject(new Error(`[@octokit/graphql] "${e}" cannot be used as variable name`))}}const s=typeof t==="string"?Object.assign({query:t},r):t;const n=Object.keys(s).reduce((e,t)=>{if(ZA.includes(t)){e[t]=s[t];return e}if(!e.variables){e.variables={}}e.variables[t]=s[t];return e},{});const o=s.baseUrl||e.endpoint.DEFAULTS.baseUrl;if(XA.test(o)){n.url=o.replace(XA,"/api/graphql")}return e(n).then(e=>{if(e.data.errors){const t={};for(const r of Object.keys(e.headers)){t[r]=e.headers[r]}throw new KA(n,t,e.data)}return e.data.data})}function graphql_dist_bundle_withDefaults(e,t){const r=e.defaults(t);const newApi=(e,t)=>graphql(r,e,t);return Object.assign(newApi,{defaults:graphql_dist_bundle_withDefaults.bind(null,r),endpoint:r.endpoint})}var ea=graphql_dist_bundle_withDefaults(jA,{headers:{"user-agent":`octokit-graphql.js/${zA} ${getUserAgent()}`},method:"POST",url:"/graphql"});function withCustomRequest(e){return graphql_dist_bundle_withDefaults(e,{method:"POST",url:"/graphql"})}var ta="(?:[a-zA-Z0-9_-]+)";var ra="\\.";var sa=new RegExp(`^${ta}${ra}${ta}${ra}${ta}$`);var na=sa.test.bind(sa);async function auth(e){const t=na(e);const r=e.startsWith("v1.")||e.startsWith("ghs_");const s=e.startsWith("ghu_");const n=t?"app":r?"installation":s?"user-to-server":"oauth";return{type:"token",token:e,tokenType:n}}function withAuthorizationPrefix(e){if(e.split(/\./).length===3){return`bearer ${e}`}return`token ${e}`}async function hook(e,t,r,s){const n=t.endpoint.merge(r,s);n.headers.authorization=withAuthorizationPrefix(e);return t(n)}var oa=function createTokenAuth2(e){if(!e){throw new Error("[@octokit/auth-token] No token passed to createTokenAuth")}if(typeof e!=="string"){throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string")}e=e.replace(/^(token|bearer) +/i,"");return Object.assign(auth.bind(null,e),{hook:hook.bind(null,e)})};const ia="7.0.6";const dist_src_noop=()=>{};const Aa=console.warn.bind(console);const aa=console.error.bind(console);function dist_src_createLogger(e={}){if(typeof e.debug!=="function"){e.debug=dist_src_noop}if(typeof e.info!=="function"){e.info=dist_src_noop}if(typeof e.warn!=="function"){e.warn=Aa}if(typeof e.error!=="function"){e.error=aa}return e}const ca=`octokit-core.js/${ia} ${getUserAgent()}`;class Octokit{static VERSION=ia;static defaults(e){const t=class extends(this){constructor(...t){const r=t[0]||{};if(typeof e==="function"){super(e(r));return}super(Object.assign({},e,r,r.userAgent&&e.userAgent?{userAgent:`${r.userAgent} ${e.userAgent}`}:null))}};return t}static plugins=[];static plugin(...e){const t=this.plugins;const r=class extends(this){static plugins=t.concat(e.filter(e=>!t.includes(e)))};return r}constructor(e={}){const t=new OA.Collection;const r={baseUrl:jA.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},e.request,{hook:t.bind(null,"request")}),mediaType:{previews:[],format:""}};r.headers["user-agent"]=e.userAgent?`${e.userAgent} ${ca}`:ca;if(e.baseUrl){r.baseUrl=e.baseUrl}if(e.previews){r.mediaType.previews=e.previews}if(e.timeZone){r.headers["time-zone"]=e.timeZone}this.request=jA.defaults(r);this.graphql=withCustomRequest(this.request).defaults(r);this.log=dist_src_createLogger(e.log);this.hook=t;if(!e.authStrategy){if(!e.auth){this.auth=async()=>({type:"unauthenticated"})}else{const r=oa(e.auth);t.wrap("request",r.hook);this.auth=r}}else{const{authStrategy:r,...s}=e;const n=r(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:s},e.auth));t.wrap("request",n.hook);this.auth=n}const s=this.constructor;for(let t=0;t({async next(){if(!l)return{done:true};try{const e=await n({method:o,url:l,headers:a});const t=normalizePaginatedListResponse(e);l=((t.headers.link||"").match(/<([^<>]+)>;\s*rel="next"/)||[])[1];if(!l&&"total_commits"in t.data){const e=new URL(t.url);const r=e.searchParams;const s=parseInt(r.get("page")||"1",10);const n=parseInt(r.get("per_page")||"250",10);if(s*n{if(n.done){return t}let o=false;function done(){o=true}t=t.concat(s?s(n.value,done):n.value.data);if(o){return t}return gather(e,t,r,s)})}var Ea=Object.assign(paginate,{iterator:iterator});var fa=null&&["GET /advisories","GET /app/hook/deliveries","GET /app/installation-requests","GET /app/installations","GET /assignments/{assignment_id}/accepted_assignments","GET /classrooms","GET /classrooms/{classroom_id}/assignments","GET /enterprises/{enterprise}/code-security/configurations","GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories","GET /enterprises/{enterprise}/dependabot/alerts","GET /enterprises/{enterprise}/teams","GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships","GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations","GET /events","GET /gists","GET /gists/public","GET /gists/starred","GET /gists/{gist_id}/comments","GET /gists/{gist_id}/commits","GET /gists/{gist_id}/forks","GET /installation/repositories","GET /issues","GET /licenses","GET /marketplace_listing/plans","GET /marketplace_listing/plans/{plan_id}/accounts","GET /marketplace_listing/stubbed/plans","GET /marketplace_listing/stubbed/plans/{plan_id}/accounts","GET /networks/{owner}/{repo}/events","GET /notifications","GET /organizations","GET /organizations/{org}/dependabot/repository-access","GET /orgs/{org}/actions/cache/usage-by-repository","GET /orgs/{org}/actions/hosted-runners","GET /orgs/{org}/actions/permissions/repositories","GET /orgs/{org}/actions/permissions/self-hosted-runners/repositories","GET /orgs/{org}/actions/runner-groups","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners","GET /orgs/{org}/actions/runners","GET /orgs/{org}/actions/secrets","GET /orgs/{org}/actions/secrets/{secret_name}/repositories","GET /orgs/{org}/actions/variables","GET /orgs/{org}/actions/variables/{name}/repositories","GET /orgs/{org}/attestations/repositories","GET /orgs/{org}/attestations/{subject_digest}","GET /orgs/{org}/blocks","GET /orgs/{org}/campaigns","GET /orgs/{org}/code-scanning/alerts","GET /orgs/{org}/code-security/configurations","GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories","GET /orgs/{org}/codespaces","GET /orgs/{org}/codespaces/secrets","GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories","GET /orgs/{org}/copilot/billing/seats","GET /orgs/{org}/copilot/metrics","GET /orgs/{org}/dependabot/alerts","GET /orgs/{org}/dependabot/secrets","GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories","GET /orgs/{org}/events","GET /orgs/{org}/failed_invitations","GET /orgs/{org}/hooks","GET /orgs/{org}/hooks/{hook_id}/deliveries","GET /orgs/{org}/insights/api/route-stats/{actor_type}/{actor_id}","GET /orgs/{org}/insights/api/subject-stats","GET /orgs/{org}/insights/api/user-stats/{user_id}","GET /orgs/{org}/installations","GET /orgs/{org}/invitations","GET /orgs/{org}/invitations/{invitation_id}/teams","GET /orgs/{org}/issues","GET /orgs/{org}/members","GET /orgs/{org}/members/{username}/codespaces","GET /orgs/{org}/migrations","GET /orgs/{org}/migrations/{migration_id}/repositories","GET /orgs/{org}/organization-roles/{role_id}/teams","GET /orgs/{org}/organization-roles/{role_id}/users","GET /orgs/{org}/outside_collaborators","GET /orgs/{org}/packages","GET /orgs/{org}/packages/{package_type}/{package_name}/versions","GET /orgs/{org}/personal-access-token-requests","GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories","GET /orgs/{org}/personal-access-tokens","GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories","GET /orgs/{org}/private-registries","GET /orgs/{org}/projects","GET /orgs/{org}/projectsV2","GET /orgs/{org}/projectsV2/{project_number}/fields","GET /orgs/{org}/projectsV2/{project_number}/items","GET /orgs/{org}/properties/values","GET /orgs/{org}/public_members","GET /orgs/{org}/repos","GET /orgs/{org}/rulesets","GET /orgs/{org}/rulesets/rule-suites","GET /orgs/{org}/rulesets/{ruleset_id}/history","GET /orgs/{org}/secret-scanning/alerts","GET /orgs/{org}/security-advisories","GET /orgs/{org}/settings/immutable-releases/repositories","GET /orgs/{org}/settings/network-configurations","GET /orgs/{org}/team/{team_slug}/copilot/metrics","GET /orgs/{org}/teams","GET /orgs/{org}/teams/{team_slug}/discussions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions","GET /orgs/{org}/teams/{team_slug}/invitations","GET /orgs/{org}/teams/{team_slug}/members","GET /orgs/{org}/teams/{team_slug}/projects","GET /orgs/{org}/teams/{team_slug}/repos","GET /orgs/{org}/teams/{team_slug}/teams","GET /projects/{project_id}/collaborators","GET /repos/{owner}/{repo}/actions/artifacts","GET /repos/{owner}/{repo}/actions/caches","GET /repos/{owner}/{repo}/actions/organization-secrets","GET /repos/{owner}/{repo}/actions/organization-variables","GET /repos/{owner}/{repo}/actions/runners","GET /repos/{owner}/{repo}/actions/runs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts","GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs","GET /repos/{owner}/{repo}/actions/secrets","GET /repos/{owner}/{repo}/actions/variables","GET /repos/{owner}/{repo}/actions/workflows","GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs","GET /repos/{owner}/{repo}/activity","GET /repos/{owner}/{repo}/assignees","GET /repos/{owner}/{repo}/attestations/{subject_digest}","GET /repos/{owner}/{repo}/branches","GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations","GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs","GET /repos/{owner}/{repo}/code-scanning/alerts","GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances","GET /repos/{owner}/{repo}/code-scanning/analyses","GET /repos/{owner}/{repo}/codespaces","GET /repos/{owner}/{repo}/codespaces/devcontainers","GET /repos/{owner}/{repo}/codespaces/secrets","GET /repos/{owner}/{repo}/collaborators","GET /repos/{owner}/{repo}/comments","GET /repos/{owner}/{repo}/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/commits","GET /repos/{owner}/{repo}/commits/{commit_sha}/comments","GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls","GET /repos/{owner}/{repo}/commits/{ref}/check-runs","GET /repos/{owner}/{repo}/commits/{ref}/check-suites","GET /repos/{owner}/{repo}/commits/{ref}/status","GET /repos/{owner}/{repo}/commits/{ref}/statuses","GET /repos/{owner}/{repo}/compare/{basehead}","GET /repos/{owner}/{repo}/compare/{base}...{head}","GET /repos/{owner}/{repo}/contributors","GET /repos/{owner}/{repo}/dependabot/alerts","GET /repos/{owner}/{repo}/dependabot/secrets","GET /repos/{owner}/{repo}/deployments","GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses","GET /repos/{owner}/{repo}/environments","GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies","GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps","GET /repos/{owner}/{repo}/environments/{environment_name}/secrets","GET /repos/{owner}/{repo}/environments/{environment_name}/variables","GET /repos/{owner}/{repo}/events","GET /repos/{owner}/{repo}/forks","GET /repos/{owner}/{repo}/hooks","GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries","GET /repos/{owner}/{repo}/invitations","GET /repos/{owner}/{repo}/issues","GET /repos/{owner}/{repo}/issues/comments","GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/issues/events","GET /repos/{owner}/{repo}/issues/{issue_number}/comments","GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by","GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking","GET /repos/{owner}/{repo}/issues/{issue_number}/events","GET /repos/{owner}/{repo}/issues/{issue_number}/labels","GET /repos/{owner}/{repo}/issues/{issue_number}/reactions","GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues","GET /repos/{owner}/{repo}/issues/{issue_number}/timeline","GET /repos/{owner}/{repo}/keys","GET /repos/{owner}/{repo}/labels","GET /repos/{owner}/{repo}/milestones","GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels","GET /repos/{owner}/{repo}/notifications","GET /repos/{owner}/{repo}/pages/builds","GET /repos/{owner}/{repo}/projects","GET /repos/{owner}/{repo}/pulls","GET /repos/{owner}/{repo}/pulls/comments","GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/pulls/{pull_number}/comments","GET /repos/{owner}/{repo}/pulls/{pull_number}/commits","GET /repos/{owner}/{repo}/pulls/{pull_number}/files","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments","GET /repos/{owner}/{repo}/releases","GET /repos/{owner}/{repo}/releases/{release_id}/assets","GET /repos/{owner}/{repo}/releases/{release_id}/reactions","GET /repos/{owner}/{repo}/rules/branches/{branch}","GET /repos/{owner}/{repo}/rulesets","GET /repos/{owner}/{repo}/rulesets/rule-suites","GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history","GET /repos/{owner}/{repo}/secret-scanning/alerts","GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations","GET /repos/{owner}/{repo}/security-advisories","GET /repos/{owner}/{repo}/stargazers","GET /repos/{owner}/{repo}/subscribers","GET /repos/{owner}/{repo}/tags","GET /repos/{owner}/{repo}/teams","GET /repos/{owner}/{repo}/topics","GET /repositories","GET /search/code","GET /search/commits","GET /search/issues","GET /search/labels","GET /search/repositories","GET /search/topics","GET /search/users","GET /teams/{team_id}/discussions","GET /teams/{team_id}/discussions/{discussion_number}/comments","GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /teams/{team_id}/discussions/{discussion_number}/reactions","GET /teams/{team_id}/invitations","GET /teams/{team_id}/members","GET /teams/{team_id}/projects","GET /teams/{team_id}/repos","GET /teams/{team_id}/teams","GET /user/blocks","GET /user/codespaces","GET /user/codespaces/secrets","GET /user/emails","GET /user/followers","GET /user/following","GET /user/gpg_keys","GET /user/installations","GET /user/installations/{installation_id}/repositories","GET /user/issues","GET /user/keys","GET /user/marketplace_purchases","GET /user/marketplace_purchases/stubbed","GET /user/memberships/orgs","GET /user/migrations","GET /user/migrations/{migration_id}/repositories","GET /user/orgs","GET /user/packages","GET /user/packages/{package_type}/{package_name}/versions","GET /user/public_emails","GET /user/repos","GET /user/repository_invitations","GET /user/social_accounts","GET /user/ssh_signing_keys","GET /user/starred","GET /user/subscriptions","GET /user/teams","GET /users","GET /users/{username}/attestations/{subject_digest}","GET /users/{username}/events","GET /users/{username}/events/orgs/{org}","GET /users/{username}/events/public","GET /users/{username}/followers","GET /users/{username}/following","GET /users/{username}/gists","GET /users/{username}/gpg_keys","GET /users/{username}/keys","GET /users/{username}/orgs","GET /users/{username}/packages","GET /users/{username}/projects","GET /users/{username}/projectsV2","GET /users/{username}/projectsV2/{project_number}/fields","GET /users/{username}/projectsV2/{project_number}/items","GET /users/{username}/received_events","GET /users/{username}/received_events/public","GET /users/{username}/repos","GET /users/{username}/social_accounts","GET /users/{username}/ssh_signing_keys","GET /users/{username}/starred","GET /users/{username}/subscriptions"];function isPaginatingEndpoint(e){if(typeof e==="string"){return fa.includes(e)}else{return false}}function paginateRest(e){return{paginate:Object.assign(paginate.bind(null,e),{iterator:iterator.bind(null,e)})}}paginateRest.VERSION=pa;const Ca=new Context;const Qa=getApiBaseUrl();const Ia={baseUrl:Qa,request:{agent:getProxyAgent(Qa),fetch:getProxyFetch(Qa)}};const Ba=Octokit.plugin(restEndpointMethods,paginateRest).defaults(Ia);function getOctokitOptions(e,t){const r=Object.assign({},t||{});const s=getAuthString(e,r);if(s){r.auth=s}const n=getUserAgentWithOrchestrationId(r.userAgent);if(n){r.userAgent=n}return r}const ma=new Context;function getOctokit(e,t,...r){const s=Ba.plugin(...r);return new s(getOctokitOptions(e,t))}function getOctokitClient(){const e=io_getInput("github_token");if(!e){throw new Error("github_token is required")}return getOctokit(e)}async function getUserInfo(e){if(!e)return undefined;const t=getOctokitClient();const r=await t.rest.users.getByUsername({username:e});core_debug(`Fetched github actor from the API: ${JSON.stringify(r?.data,null,2)}`);return{name:r?.data?.name,email:r?.data?.email}}const wa=/[\u0000-\u001F\u007F-\u009F\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/gu;function neutralizeLogString(e){return e.replace(wa,e=>{const t=e.codePointAt(0).toString(16).padStart(4,"0");return`\\u${t}`})}const ya="[Circular]";function neutralizeForLog(e,t=new WeakSet){if(typeof e==="string")return neutralizeLogString(e);if(typeof e==="number"||typeof e==="boolean"||e===null||e===undefined){return e}if(e instanceof Error){const t=new Error(neutralizeLogString(e.message));t.name=neutralizeLogString(e.name);if(e.stack){t.stack=neutralizeLogString(e.stack)}return t}if(Array.isArray(e)){if(t.has(e))return ya;t.add(e);return e.map(e=>neutralizeForLog(e,t))}if(typeof e==="object"){if(t.has(e))return ya;t.add(e);const r={};for(const[s,n]of Object.entries(e)){r[neutralizeLogString(s)]=neutralizeForLog(n,t)}return r}return e}function log(e,t){if(t)console.log(neutralizeForLog(t));if(e){const t=neutralizeForLog(e);if(typeof t==="string"||t instanceof Error){error(t)}else{error(String(t))}}}const ba=["user.name","user.email","author.name","author.email","committer.name","committer.email"];function pickGitIdentityConfig(e){const t={};for(const r of ba){if(Object.prototype.hasOwnProperty.call(e,r)){t[r]=e[r]}}return t}function assertValidBranchName(e){if(!e||!e.trim()){throw new Error("The new_branch value is empty.")}if(e.startsWith("-")){throw new Error(`The new_branch value '${e}' cannot start with '-' (it would be interpreted as a git option).`)}for(const t of e){const r=t.codePointAt(0);if(r<=31||r===127||r>=128&&r<=159||/\s/u.test(t)){throw new Error(`The new_branch value '${e}' contains whitespace or control characters.`)}}try{(0,ue.execFileSync)("git",["check-ref-format","--branch",e],{stdio:"ignore"})}catch{throw new Error(`The new_branch value '${e}' is not a valid git branch name.`)}}const ka=[{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];const Ta=[{canonical:"file",minPrefix:"fi"}];const Ra=[{canonical:"message",minPrefix:"mes"},{canonical:"local-user",minPrefix:"local-"},{canonical:"cleanup",minPrefix:"cleanup"},{canonical:"file",minPrefix:"fi"},{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];const Da=new Set(["m","F"]);function getLongOptionName(e){if(!e.startsWith("--")||e==="--")return undefined;const t=e.slice(2);const r=t.indexOf("=");return(r===-1?t:t.slice(0,r)).toLowerCase()}function longOptionHasInlineValue(e){if(!e.startsWith("--")||e==="--")return false;return e.slice(2).includes("=")}function matchesLongOptionPrefix(e,t){const r=getLongOptionName(e);if(!r)return false;return t.some(({canonical:e,minPrefix:t})=>r.length>=t.length&&e.startsWith(r))}function isDangerousRemoteHelperOption(e){return matchesLongOptionPrefix(e,ka)}function isDangerousMessageFileShortOption(e){if(!e.startsWith("-")||e.startsWith("--"))return false;const t=e.slice(1);for(let e=0;e` - ${e}`).join("\n");const r=e.map(e=>` git rm --cached -- ${e}`).join("\n");throw new Error(`Refusing to commit unexpected gitlink(s) (embedded git repository staged as mode 160000):\n${t}\n`+"Git records a nested .git directory as a gitlink, not as its files. "+`Remove the nested .git directory, or unstage the path(s) with:\n${r}`)}function parseInputArray(e){core_debug(`Parsing input array: ${e}`);try{const t=load(e);if(t&&Array.isArray(t)&&t.every(e=>typeof e==="string")){core_debug(`Input parsed as YAML array of length ${t.length}`);return t}}catch{}core_debug("Input parsed as single string");return[e]}function readJSON(e){let t;try{t=fs.readFileSync(e,{encoding:"utf8"})}catch{throw`Couldn't read file. File path: ${e}`}try{return JSON.parse(t)}catch{throw`Couldn't parse file to JSON. File path: ${e}`}}const Sa={committed:"false",commit_long_sha:undefined,commit_sha:undefined,pushed:"false",tagged:"false",tag_pushed:"false"};Object.entries(Sa).forEach(([e,t])=>setOutput(e,t));function io_getInput(e,t=false){if(t)return getBooleanInput(e);return getInput(e)}function io_setOutput(e,t){core_debug(`Setting output: ${e}=${t}`);Sa[e]=t;setOutput(e,t)}function parsePushAttempts(e){const t=e.trim();if(!/^\+?\d+$/.test(t)){throw new Error(`'${e}' is not a valid value for push_attempts. It must be a positive integer (≥ 1).`)}const r=Number.parseInt(t,10);if(!Number.isSafeInteger(r)||r<1){throw new Error(`'${e}' is not a valid value for push_attempts. It must be a positive integer (≥ 1).`)}return r}function logOutputs(){startGroup("Outputs");for(const e in Sa){info(`${e}: ${Sa[e]}`)}endGroup()}async function checkInputs(){function setInput(e,t){if(t)return process.env[`INPUT_${e.toUpperCase()}`]=t;else return delete process.env[`INPUT_${e.toUpperCase()}`]}function setDefault(e,t){if(!io_getInput(e))setInput(e,t);return io_getInput(e)}if(!io_getInput("add")&&!io_getInput("remove"))throw new Error("Both 'add' and 'remove' are empty, the action has nothing to do.");if(io_getInput("add")){const e=parseInputArray(io_getInput("add"));if(e.length===1)info("Add input parsed as single string, running 1 git add command.");else if(e.length>1)info(`Add input parsed as string array, running ${e.length} git add commands.`);else setFailed("Add input: array length < 1")}if(io_getInput("remove")){const e=parseInputArray(io_getInput("remove")||"");if(e.length===1)info("Remove input parsed as single string, running 1 git rm command.");else if(e.length>1)info(`Remove input parsed as string array, running ${e.length} git rm commands.`);else setFailed("Remove input: array length < 1")}const e=["github_actor","user_info","github_actions"];if(!e.includes(io_getInput("default_author")))throw new Error(`'${io_getInput("default_author")}' is not a valid value for default_author. Valid values: ${e.join(", ")}`);if(io_getInput("dry_run",true))info("> Dry run enabled: no mutating git operations will be performed.");if(io_getInput("fetch")){let e;try{e=io_getInput("fetch",true)}catch{e=io_getInput("fetch")}core_debug(`Current fetch option: '${e}' (parsed as ${typeof e})`)}let t,r;switch(io_getInput("default_author")){case"github_actor":{t=process.env.GITHUB_ACTOR??"";r=`${process.env.GITHUB_ACTOR}@users.noreply.github.com`;break}case"user_info":{if(!io_getInput("author_name")||!io_getInput("author_email")){const e=await getUserInfo(process.env.GITHUB_ACTOR);if(!e?.name)warning("Couldn't fetch author name, filling with github_actor.");if(!e?.email)warning("Couldn't fetch author email, filling with github_actor.");e?.name&&(t=e?.name);e?.email&&(r=e.email);if(t&&r)break}!t&&(t=process.env.GITHUB_ACTOR??"");!r&&(r=`${process.env.GITHUB_ACTOR}@users.noreply.github.com`);break}case"github_actions":{t="github-actions";r="41898282+github-actions[bot]@users.noreply.github.com";break}default:throw new Error("This should not happen, please contact the author of this action. (checkInputs.author)")}setDefault("author_name",t);setDefault("author_email",r);info(`> Using '${io_getInput("author_name")} <${io_getInput("author_email")}>' as author.`);if(io_getInput("committer_name")||io_getInput("committer_email"))info(`> Using custom committer info: ${io_getInput("committer_name")||io_getInput("author_name")+" [from author info]"} <${io_getInput("committer_email")||io_getInput("author_email")+" [from author info]"}>`);setDefault("committer_name",io_getInput("author_name"));setDefault("committer_email",io_getInput("author_email"));core_debug(`Committer: ${io_getInput("committer_name")} <${io_getInput("committer_email")}>`);setDefault("message",`Commit from GitHub Actions (${process.env.GITHUB_WORKFLOW})`);info(`> Using "${io_getInput("message")}" as commit message.`);const s=io_getInput("new_branch");if(s)assertValidBranchName(s);const n=["ignore","exitImmediately","exitAtEnd"];if(!n.includes(io_getInput("pathspec_error_handling")))throw new Error(`"${io_getInput("pathspec_error_handling")}" is not a valid value for the 'pathspec_error_handling' input. Valid values are: ${n.join(", ")}`);if(io_getInput("pull")==="NO-PULL")warning("`NO-PULL` is a legacy option for the `pull` input. If you don't want the action to pull the repo, simply remove this input.");if(io_getInput("push")){let e;try{e=io_getInput("push",true)}catch{e=io_getInput("push")}core_debug(`Current push option: '${e}' (parsed as ${typeof e})`)}const o=parsePushAttempts(io_getInput("push_attempts")||"1");core_debug(`Current push_attempts option: ${o}`);if(o>1&&!io_getInput("pull")){warning("push_attempts is greater than 1 but pull is not set. Retries will re-run push only; without pull (e.g. --rebase), concurrent remote updates are unlikely to recover.")}if(!io_getInput("github_token"))warning("No github_token has been detected, the action may fail if it needs to use the API")}const Fa=u.join(process.cwd(),io_getInput("cwd")||"");const va=lo({baseDir:Fa});const Ua=[];info(`Running in ${Fa}`);(async()=>{await checkInputs();const e=io_getInput("dry_run",true);startGroup("Internal logs");info(e?"> Staging files (dry run)...":"> Staging files...");const t=io_getInput("pathspec_error_handling")==="ignore"?"pathspec":"none";let r=false;if(io_getInput("add")){info(e?"> Adding files (dry run)...":"> Adding files...");const s=await add(t,e);if(e)r=r||s.some(e=>typeof e==="string"&&e.trim().length>0)}else info("> No files to add.");if(io_getInput("remove")){info(e?"> Removing files (dry run)...":"> Removing files...");const s=await main_remove(t,e);if(e)r=r||s.some(e=>{if(e===null||e===undefined)return false;const t=typeof e==="string"?e:String(e);return t.trim().length>0})}else info("> No files to remove.");info("> Checking for uncommitted changes in the git working tree...");const s=(await va.diffSummary(["--cached"])).files.length;const n=matchGitArgs(io_getInput("commit")||"").includes("--allow-empty");if(s>0||r||n){info(e?`> Dry run: would proceed (${s} already staged`+`${r?", staging probes reported changes":""}`+`${n?", --allow-empty":""}).`:`> Found ${s} changed files.`);core_debug(`--allow-empty argument detected: ${n}`);if(e){await logDryRunRemainingSteps();endGroup();info("> Dry run completed. No changes were made.");return}await va.addConfig("user.email",io_getInput("author_email"),undefined,log).addConfig("user.name",io_getInput("author_name"),undefined,log).addConfig("author.email",io_getInput("author_email"),undefined,log).addConfig("author.name",io_getInput("author_name"),undefined,log).addConfig("committer.email",io_getInput("committer_email"),undefined,log).addConfig("committer.name",io_getInput("committer_name"),undefined,log);if(isDebug()){const e=pickGitIdentityConfig((await va.listConfig()).all);core_debug(Object.keys(e).length?"> Current git identity config\n"+JSON.stringify(e,null,2):"> Git identity config set (no identity keys present in listConfig)")}let o;try{o=io_getInput("fetch",true)}catch{o=io_getInput("fetch")}if(o){info("> Fetching repo...");await va.fetch(matchGitArgs(o===true?"":o),log)}else info("> Not fetching repo.");const a=io_getInput("new_branch");if(a){info("> Checking-out branch...");if(!o)warning("Creating a new branch without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.");await va.checkout([a]).then(()=>{log(undefined,`'${a}' branch already existed.`)}).catch(()=>{log(undefined,`Creating '${a}' branch.`);return va.checkout(["-b",a],log)})}const l=io_getInput("pull");if(l){await pullFromRemote(l,{restage:true,ignoreErrors:t})}else info("> Not pulling from repo.");info("> Creating commit...");const u=await va.commit(io_getInput("message"),matchGitArgs(io_getInput("commit")||""));log(undefined,u);if(!u.commit){throw new Error("Commit did not produce a SHA; refusing to report committed=true.")}io_setOutput("committed","true");io_setOutput("commit_long_sha",u.commit);io_setOutput("commit_sha",u.commit.substring(0,7));if(io_getInput("tag")){info("> Tagging commit...");if(!o)warning("Creating a tag without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.");await va.tag(matchGitArgs(io_getInput("tag")||""),(e,t)=>{if(t)io_setOutput("tagged","true");return log(e,t)}).then(e=>{io_setOutput("tagged","true");return log(null,e)}).catch(e=>setFailed(e))}else info("> No tag info provided.");let g;try{g=io_getInput("push",true)}catch{g=io_getInput("push")}if(g){const e=parsePushAttempts(io_getInput("push_attempts")||"1");for(let r=1;r<=e;r++){try{info(e>1?`> Pushing commit to repo (attempt ${r}/${e})...`:"> Pushing commit to repo...");await pushCommit(g);break}catch(s){if(r===e)throw s;const n=s instanceof Error?s.message:String(s);warning(`Push failed (attempt ${r}/${e}): ${neutralizeLogString(n)}`);if(l){await pullFromRemote(l,{restage:false,ignoreErrors:t});const e=(await va.revparse(["HEAD"])).trim();io_setOutput("commit_long_sha",e);io_setOutput("commit_sha",e.substring(0,7))}}}if(io_getInput("tag")){info("> Pushing tags to repo...");await va.pushTags("origin",matchGitArgs(io_getInput("tag_push")||"")).then(e=>{io_setOutput("tag_pushed","true");return log(null,e)}).catch(e=>setFailed(e))}else info("> No tags to push.")}else info("> Not pushing anything.");endGroup();info("> Task completed.")}else{endGroup();info(e?"> Dry run: working tree clean. Nothing would be committed.":"> Working tree clean. Nothing to commit.")}})().then(()=>{if(Ua.length===1)throw Ua[0];else if(Ua.length>1){Ua.forEach(e=>error(e));throw"There have been multiple runtime errors."}}).then(logOutputs).catch(e=>{endGroup();logOutputs();setFailed(e)});async function logDryRunRemainingSteps(){info(`> Would set git identity: ${io_getInput("author_name")} <${io_getInput("author_email")}> (committer: ${io_getInput("committer_name")} <${io_getInput("committer_email")}>)`);let e;try{e=io_getInput("fetch",true)}catch{e=io_getInput("fetch")}if(e){info(`> Would fetch repo${e===true?"":` with: ${e}`}.`)}else info("> Would not fetch repo.");const t=io_getInput("new_branch");if(t){info(`> Would check out branch '${t}'.`);if(!e)warning("Creating a new branch without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.")}const r=io_getInput("pull");if(r)info(`> Would pull from remote with: ${r}.`);else info("> Would not pull from repo.");info(`> Would create commit with message: "${io_getInput("message")}"${io_getInput("commit")?` (extra args: ${io_getInput("commit")})`:""}.`);if(io_getInput("tag")){info(`> Would tag commit with: ${io_getInput("tag")}.`);if(!e)warning("Creating a tag without fetching the repo first could result in an error when pushing to GitHub. Refer to the action README for more info about this topic.")}else info("> No tag info provided.");let s;try{s=io_getInput("push",true)}catch{s=io_getInput("push")}if(s){const e=parsePushAttempts(io_getInput("push_attempts")||"1");if(s===true){const t=io_getInput("new_branch");info(t?`> Would push commit to repo (set upstream for '${t}')${e>1?` with up to ${e} attempts`:""}.`:`> Would push commit to repo${e>1?` with up to ${e} attempts`:""}.`)}else info(`> Would push commit to repo with: ${s}${e>1?` (up to ${e} attempts)`:""}.`);if(io_getInput("tag")){info(`> Would push tags to repo${io_getInput("tag_push")?` with: ${io_getInput("tag_push")}`:""}.`)}else info("> No tags to push.")}else info("> Would not push anything.")}async function pullFromRemote(e,t){info("> Pulling from remote...");core_debug(`Current git pull arguments: ${e}`);await va.fetch(undefined,log).pull(undefined,undefined,matchGitArgs(e),log);info("> Checking for conflicts...");const r=await va.status(undefined,log);if(r.conflicted.length){throw new Error(`There are ${r.conflicted.length} conflicting files: ${r.conflicted.map(neutralizeLogString).join(", ")}`)}info("> No conflicts found.");if(t.restage){info("> Re-staging files...");if(io_getInput("add"))await add(t.ignoreErrors);if(io_getInput("remove"))await main_remove(t.ignoreErrors)}}async function pushCommit(e){if(e===true){const e=io_getInput("new_branch");if(e){core_debug(`Running: git push --set-upstream origin -- ${e}`);await va.raw(["push","--set-upstream","origin","--",e],(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}else{core_debug("Running: git push origin --set-upstream");await va.push("origin",undefined,{"--set-upstream":null},(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}else{core_debug(`Running: git push ${e}`);await va.push(undefined,undefined,matchGitArgs(e),(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}async function add(e="none",t=false){const r=io_getInput("add");if(!r)return[];const s=parseInputArray(r);const n=[];for(const r of s){const s=t?["--dry-run",...matchGitArgs(r)]:matchGitArgs(r);n.push(await va.add(s,(t,r)=>log(e==="all"?null:t,r)).catch(t=>{if(e==="all")return;if(t.message.includes("fatal: pathspec")&&t.message.includes("did not match any files")){if(e==="pathspec")return;const t=io_getInput("pathspec_error_handling"),s=new Error(`Add command did not match any file: git add ${r}`);if(t==="exitImmediately")throw s;if(t==="exitAtEnd")Ua.push(s)}else throw t}))}if(t){await assertGitlinksWithTempIndex(s,e)}else{const e=await va.raw(["diff","--cached","--raw"]);assertNoUnexpectedGitlinks(findUnexpectedGitlinks(e))}return n}async function assertGitlinksWithTempIndex(e,t){const r=u.join(n.tmpdir(),`add-and-commit-${process.pid}-${Date.now()}.index`);try{const s=(await va.raw(["rev-parse","--git-path","index"])).trim();const n=u.isAbsolute(s)?s:u.join(Fa,s);if(l.existsSync(n)){l.copyFileSync(n,r)}else{const e=lo({baseDir:Fa}).env({...process.env,GIT_INDEX_FILE:r});const t=await va.raw(["rev-parse","--verify","HEAD"]).then(()=>true).catch(()=>false);if(t){await e.raw(["read-tree","HEAD"])}else{await e.raw(["read-tree","--empty"])}}const o=lo({baseDir:Fa}).env({...process.env,GIT_INDEX_FILE:r});for(const r of e){await o.add(matchGitArgs(r),(e,r)=>log(t==="all"?null:e,r)).catch(e=>{if(t==="all")return;if(e.message.includes("fatal: pathspec")&&e.message.includes("did not match any files")){if(t==="pathspec")return;const e=io_getInput("pathspec_error_handling");if(e==="exitImmediately"){throw new Error(`Add command did not match any file: git add ${r}`)}return}throw e})}const a=await o.raw(["diff","--cached","--raw"]);assertNoUnexpectedGitlinks(findUnexpectedGitlinks(a))}finally{l.rmSync(r,{force:true});l.rmSync(`${r}.lock`,{force:true})}}async function main_remove(e="none",t=false){const r=io_getInput("remove");if(!r)return[];const s=parseInputArray(r);const n=[];for(const r of s){const s=t?["--dry-run",...matchGitArgs(r)]:matchGitArgs(r);n.push(await va.rm(s,(t,r)=>log(e==="all"?null:t,r)).catch(t=>{if(e==="all")return;if(t.message.includes("fatal: pathspec")&&t.message.includes("did not match any files")){if(e==="pathspec")return;const t=io_getInput("pathspec_error_handling"),s=new Error(`Remove command did not match any file:\n git rm ${r}`);if(t==="exitImmediately")throw s;if(t==="exitAtEnd")Ua.push(s)}else throw t}))}return n} \ No newline at end of file diff --git a/src/util.ts b/src/util.ts index 0bdc6057..199fb0b9 100644 --- a/src/util.ts +++ b/src/util.ts @@ -221,8 +221,14 @@ const LONG_OPTIONS_WITH_SEPARATE_ARG: ReadonlyArray<{ {canonical: 'exec', minPrefix: 'e'}, ]; -/** Short options that take a value (glued or as the following argv token). */ -const SHORT_OPTIONS_WITH_ARG = new Set(['m', 'u', 'F']); +/** + * Short options that take a value (glued or as the following argv token). + * `-u` is intentionally omitted: it only takes a key-id for `git tag`, while + * `git fetch` (`--update-head-ok`) and `git push` (`--set-upstream`) treat it + * as a flag. Tag signing still uses `--local-user` in + * `LONG_OPTIONS_WITH_SEPARATE_ARG`. + */ +const SHORT_OPTIONS_WITH_ARG = new Set(['m', 'F']); function getLongOptionName(arg: string): string | undefined { if (!arg.startsWith('--') || arg === '--') return undefined; @@ -348,7 +354,7 @@ function assertBalancedQuotes(input: string): void { * ``` * @returns An array, if there's no match it'll be empty * @throws If the args include unmatched quotes - * @throws If the args include a blocked remote-helper override (`--upload-pack`, `--receive-pack`, `--exec`, or abbreviations) + * @throws If the args include a blocked remote-helper override (`--upload-pack`, `--receive-pack`, `--exec`, or abbreviations) on any token, including values after `-u` / `-m` * @throws If the args include a blocked message-from-file flag (`-F`, `--file`, abbreviations, or short-option clusters containing `F`) */ export function matchGitArgs(string: string) { @@ -361,16 +367,19 @@ export function matchGitArgs(string: string) { let skipNext = false; for (const arg of parsed) { - if (skipNext) { - skipNext = false; - continue; - } - + // Remote-helper overrides are rejected on every token, including values + // after `-m` / `--message`. `-u` must not skip `--upl=` / `--upload-pack`. if (isDangerousRemoteHelperOption(arg)) { throw new Error( `Git argument '${arg}' is not allowed: overriding the remote helper (--upload-pack, --receive-pack, --exec) can execute arbitrary commands on the runner.`, ); } + + if (skipNext) { + skipNext = false; + continue; + } + if (isDangerousMessageFileOption(arg)) { throw new Error( `Git argument '${arg}' is not allowed: reading a tag/commit message from a file (-F/--file) can exfiltrate runner filesystem contents into git history.`, diff --git a/test/integration/action.test.ts b/test/integration/action.test.ts index 4f9aeb4c..258ada9b 100644 --- a/test/integration/action.test.ts +++ b/test/integration/action.test.ts @@ -122,6 +122,23 @@ describe('action integration', () => { expect(`${result.stdout}\n${result.stderr}`).toMatch(/gitlink/i); }); + it('rejects remote-helper overrides after -u in fetch args', () => { + const f = fixture!; + writeFile(f.local, 'fetch-args.txt', 'changed\n'); + const before = gitRevParse(f.local, 'HEAD'); + + const result = runAction(f, { + message: 'Should not fetch with blocked args', + fetch: '-u --upl=evil', + push: 'false', + }); + + expect(result.status).not.toBe(0); + expect(result.outputs.committed).toBe('false'); + expect(gitRevParse(f.local, 'HEAD')).toBe(before); + expect(`${result.stdout}\n${result.stderr}`).toMatch(/not allowed/); + }); + it('applies custom author and committer', () => { const f = fixture!; writeFile(f.local, 'id.txt', 'id\n'); diff --git a/test/util.test.ts b/test/util.test.ts index 19a61da7..de373e82 100644 --- a/test/util.test.ts +++ b/test/util.test.ts @@ -146,6 +146,11 @@ describe('matchGitArgs', () => { 'release', ]); expect(matchGitArgs('v1.0.0 -f')).toStrictEqual(['v1.0.0', '-f']); + expect(matchGitArgs('v1.0.0 -u ABCDEF')).toStrictEqual([ + 'v1.0.0', + '-u', + 'ABCDEF', + ]); }); it('returns an empty array for blank input', () => { @@ -182,6 +187,16 @@ describe('matchGitArgs', () => { expect(() => matchGitArgs('--exe=evil')).toThrow(/not allowed/); }); + it('rejects remote-helper overrides after -u (fetch/push flag, not a value option)', () => { + expect(() => matchGitArgs('-u --upl=evil')).toThrow(/not allowed/); + expect(() => matchGitArgs('-u --upload-pack=evil')).toThrow(/not allowed/); + }); + + it('rejects remote-helper overrides after -m / --message', () => { + expect(() => matchGitArgs('-m --upl=evil')).toThrow(/not allowed/); + expect(() => matchGitArgs('--message --exec=evil')).toThrow(/not allowed/); + }); + it('rejects unmatched quotes that would inject flags via string-argv', () => { expect(() => matchGitArgs("origin fix'--force --set-upstream")).toThrow( /unmatched ' quote/,