From 966e8f7e06a2d386e3392a0369c2685432474eb6 Mon Sep 17 00:00:00 2001 From: Federico Grandi Date: Sat, 8 Aug 2026 23:07:19 +0200 Subject: [PATCH] fix: stop logging full git config (credential leak) Avoid dumping listConfig().all via core.debug so checkout extraheader tokens are never written to action logs. Co-authored-by: Cursor --- lib/index.js | 2 +- src/main.ts | 20 +++++++++++++++----- src/util.ts | 26 ++++++++++++++++++++++++++ test/util.test.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) diff --git a/lib/index.js b/lib/index.js index 789be550..95a97c7e 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 XA=["query","method","url"];var $A=/\/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(!XA.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($A.test(o)){n.url=o.replace($A,"/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 pa=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=Ea;const Ca=new Context;const Qa=getApiBaseUrl();const Ba={baseUrl:Qa,request:{agent:getProxyAgent(Qa),fetch:getProxyFetch(Qa)}};const Ia=Octokit.plugin(restEndpointMethods,paginateRest).defaults(Ba);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=Ia.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}}function log(e,t){if(t)console.log(t);if(e)error(e)}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 wa=[{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];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 isDangerousRemoteHelperOption(e){const t=getLongOptionName(e);if(!t)return false;return wa.some(({canonical:e,minPrefix:r})=>t.length>=r.length&&e.startsWith(t))}function matchGitArgs(e){const t=parseArgsStringToArgv(e);core_debug(`Git args parsed:\n - Original: ${e}\n - Parsed: ${JSON.stringify(t)}`);for(const e of t){if(isDangerousRemoteHelperOption(e)){throw new Error(`Git argument '${e}' is not allowed: overriding the remote helper (--upload-pack, --receive-pack, --exec) can execute arbitrary commands on the runner.`)}}return t}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 ya={committed:"false",commit_long_sha:undefined,commit_sha:undefined,pushed:"false",tagged:"false",tag_pushed:"false"};Object.entries(ya).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}`);ya[e]=t;setOutput(e,t)}function logOutputs(){startGroup("Outputs");for(const e in ya){info(`${e}: ${ya[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("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})`)}if(!io_getInput("github_token"))warning("No github_token has been detected, the action may fail if it needs to use the API")}const ba=u.join(process.cwd(),io_getInput("cwd")||"");const ka=lo({baseDir:ba});const Ta=[];info(`Running in ${ba}`);(async()=>{await checkInputs();startGroup("Internal logs");info("> Staging files...");const e=io_getInput("pathspec_error_handling")==="ignore"?"pathspec":"none";if(io_getInput("add")){info("> Adding files...");await add(e)}else info("> No files to add.");if(io_getInput("remove")){info("> Removing files...");await main_remove(e)}else info("> No files to remove.");info("> Checking for uncommitted changes in the git working tree...");const t=(await ka.diffSummary(["--cached"])).files.length;if(t>0||matchGitArgs(io_getInput("commit")||"").includes("--allow-empty")){info(`> Found ${t} changed files.`);core_debug(`--allow-empty argument detected: ${matchGitArgs(io_getInput("commit")||"").includes("--allow-empty")}`);await ka.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);core_debug("> Current git config\n"+JSON.stringify((await ka.listConfig()).all,null,2));let r;try{r=io_getInput("fetch",true)}catch{r=io_getInput("fetch")}if(r){info("> Fetching repo...");await ka.fetch(matchGitArgs(r===true?"":r),log)}else info("> Not fetching repo.");const s=io_getInput("new_branch");if(s){info("> Checking-out branch...");if(!r)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 ka.checkout([s]).then(()=>{log(undefined,`'${s}' branch already existed.`)}).catch(()=>{log(undefined,`Creating '${s}' branch.`);return ka.checkout(["-b",s],log)})}const n=io_getInput("pull");if(n){info("> Pulling from remote...");core_debug(`Current git pull arguments: ${n}`);await ka.fetch(undefined,log).pull(undefined,undefined,matchGitArgs(n),log);info("> Checking for conflicts...");const t=await ka.status(undefined,log);if(!t.conflicted.length){info("> No conflicts found.");info("> Re-staging files...");if(io_getInput("add"))await add(e);if(io_getInput("remove"))await main_remove(e)}else throw new Error(`There are ${t.conflicted.length} conflicting files: ${t.conflicted.join(", ")}`)}else info("> Not pulling from repo.");info("> Creating commit...");await ka.commit(io_getInput("message"),matchGitArgs(io_getInput("commit")||"")).then(async e=>{log(undefined,e);io_setOutput("committed","true");io_setOutput("commit_long_sha",e.commit);io_setOutput("commit_sha",e.commit.substring(0,7))}).catch(e=>setFailed(e));if(io_getInput("tag")){info("> Tagging commit...");if(!r)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 ka.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 o;try{o=io_getInput("push",true)}catch{o=io_getInput("push")}if(o){info("> Pushing commit to repo...");if(o===true){const e=io_getInput("new_branch");if(e){core_debug(`Running: git push --set-upstream origin -- ${e}`);await ka.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 ka.push("origin",undefined,{"--set-upstream":null},(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}else{core_debug(`Running: git push ${o}`);await ka.push(undefined,undefined,matchGitArgs(o),(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}if(io_getInput("tag")){info("> Pushing tags to repo...");await ka.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("> Working tree clean. Nothing to commit.")}})().then(()=>{if(Ta.length===1)throw Ta[0];else if(Ta.length>1){Ta.forEach(e=>error(e));throw"There have been multiple runtime errors."}}).then(logOutputs).catch(e=>{endGroup();logOutputs();setFailed(e)});async function add(e="none"){const t=io_getInput("add");if(!t)return[];const r=parseInputArray(t);const s=[];for(const t of r){s.push(await ka.add(matchGitArgs(t),(t,r)=>log(e==="all"?null:t,r)).catch(r=>{if(e==="all")return;if(r.message.includes("fatal: pathspec")&&r.message.includes("did not match any files")){if(e==="pathspec")return;const r=io_getInput("pathspec_error_handling"),s=new Error(`Add command did not match any file: git add ${t}`);if(r==="exitImmediately")throw s;if(r==="exitAtEnd")Ta.push(s)}else throw r}))}return s}async function main_remove(e="none"){const t=io_getInput("remove");if(!t)return[];const r=parseInputArray(t);const s=[];for(const t of r){s.push(await ka.rm(matchGitArgs(t),(t,r)=>log(e==="all"?null:t,r)).catch(r=>{if(e==="all")return;if(r.message.includes("fatal: pathspec")&&r.message.includes("did not match any files")){if(e==="pathspec")return;const r=io_getInput("pathspec_error_handling"),s=new Error(`Remove command did not match any file:\n git rm ${t}`);if(r==="exitImmediately")throw s;if(r==="exitAtEnd")Ta.push(s)}else throw r}))}return s} \ 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 XA=["query","method","url"];var $A=/\/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(!XA.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($A.test(o)){n.url=o.replace($A,"/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 pa=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=Ea;const Ca=new Context;const Qa=getApiBaseUrl();const Ba={baseUrl:Qa,request:{agent:getProxyAgent(Qa),fetch:getProxyFetch(Qa)}};const Ia=Octokit.plugin(restEndpointMethods,paginateRest).defaults(Ba);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=Ia.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}}function log(e,t){if(t)console.log(t);if(e)error(e)}const wa=["user.name","user.email","author.name","author.email","committer.name","committer.email"];function pickGitIdentityConfig(e){const t={};for(const r of wa){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 ya=[{canonical:"upload-pack",minPrefix:"upl"},{canonical:"receive-pack",minPrefix:"rece"},{canonical:"exec",minPrefix:"e"}];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 isDangerousRemoteHelperOption(e){const t=getLongOptionName(e);if(!t)return false;return ya.some(({canonical:e,minPrefix:r})=>t.length>=r.length&&e.startsWith(t))}function matchGitArgs(e){const t=parseArgsStringToArgv(e);core_debug(`Git args parsed:\n - Original: ${e}\n - Parsed: ${JSON.stringify(t)}`);for(const e of t){if(isDangerousRemoteHelperOption(e)){throw new Error(`Git argument '${e}' is not allowed: overriding the remote helper (--upload-pack, --receive-pack, --exec) can execute arbitrary commands on the runner.`)}}return t}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 ba={committed:"false",commit_long_sha:undefined,commit_sha:undefined,pushed:"false",tagged:"false",tag_pushed:"false"};Object.entries(ba).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}`);ba[e]=t;setOutput(e,t)}function logOutputs(){startGroup("Outputs");for(const e in ba){info(`${e}: ${ba[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("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})`)}if(!io_getInput("github_token"))warning("No github_token has been detected, the action may fail if it needs to use the API")}const ka=u.join(process.cwd(),io_getInput("cwd")||"");const Ta=lo({baseDir:ka});const Ra=[];info(`Running in ${ka}`);(async()=>{await checkInputs();startGroup("Internal logs");info("> Staging files...");const e=io_getInput("pathspec_error_handling")==="ignore"?"pathspec":"none";if(io_getInput("add")){info("> Adding files...");await add(e)}else info("> No files to add.");if(io_getInput("remove")){info("> Removing files...");await main_remove(e)}else info("> No files to remove.");info("> Checking for uncommitted changes in the git working tree...");const t=(await Ta.diffSummary(["--cached"])).files.length;if(t>0||matchGitArgs(io_getInput("commit")||"").includes("--allow-empty")){info(`> Found ${t} changed files.`);core_debug(`--allow-empty argument detected: ${matchGitArgs(io_getInput("commit")||"").includes("--allow-empty")}`);await Ta.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 Ta.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 r;try{r=io_getInput("fetch",true)}catch{r=io_getInput("fetch")}if(r){info("> Fetching repo...");await Ta.fetch(matchGitArgs(r===true?"":r),log)}else info("> Not fetching repo.");const s=io_getInput("new_branch");if(s){info("> Checking-out branch...");if(!r)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 Ta.checkout([s]).then(()=>{log(undefined,`'${s}' branch already existed.`)}).catch(()=>{log(undefined,`Creating '${s}' branch.`);return Ta.checkout(["-b",s],log)})}const n=io_getInput("pull");if(n){info("> Pulling from remote...");core_debug(`Current git pull arguments: ${n}`);await Ta.fetch(undefined,log).pull(undefined,undefined,matchGitArgs(n),log);info("> Checking for conflicts...");const t=await Ta.status(undefined,log);if(!t.conflicted.length){info("> No conflicts found.");info("> Re-staging files...");if(io_getInput("add"))await add(e);if(io_getInput("remove"))await main_remove(e)}else throw new Error(`There are ${t.conflicted.length} conflicting files: ${t.conflicted.join(", ")}`)}else info("> Not pulling from repo.");info("> Creating commit...");await Ta.commit(io_getInput("message"),matchGitArgs(io_getInput("commit")||"")).then(async e=>{log(undefined,e);io_setOutput("committed","true");io_setOutput("commit_long_sha",e.commit);io_setOutput("commit_sha",e.commit.substring(0,7))}).catch(e=>setFailed(e));if(io_getInput("tag")){info("> Tagging commit...");if(!r)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 Ta.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 o;try{o=io_getInput("push",true)}catch{o=io_getInput("push")}if(o){info("> Pushing commit to repo...");if(o===true){const e=io_getInput("new_branch");if(e){core_debug(`Running: git push --set-upstream origin -- ${e}`);await Ta.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 Ta.push("origin",undefined,{"--set-upstream":null},(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}}else{core_debug(`Running: git push ${o}`);await Ta.push(undefined,undefined,matchGitArgs(o),(e,t)=>{if(t)io_setOutput("pushed","true");return log(e,t)})}if(io_getInput("tag")){info("> Pushing tags to repo...");await Ta.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("> Working tree clean. Nothing to commit.")}})().then(()=>{if(Ra.length===1)throw Ra[0];else if(Ra.length>1){Ra.forEach(e=>error(e));throw"There have been multiple runtime errors."}}).then(logOutputs).catch(e=>{endGroup();logOutputs();setFailed(e)});async function add(e="none"){const t=io_getInput("add");if(!t)return[];const r=parseInputArray(t);const s=[];for(const t of r){s.push(await Ta.add(matchGitArgs(t),(t,r)=>log(e==="all"?null:t,r)).catch(r=>{if(e==="all")return;if(r.message.includes("fatal: pathspec")&&r.message.includes("did not match any files")){if(e==="pathspec")return;const r=io_getInput("pathspec_error_handling"),s=new Error(`Add command did not match any file: git add ${t}`);if(r==="exitImmediately")throw s;if(r==="exitAtEnd")Ra.push(s)}else throw r}))}return s}async function main_remove(e="none"){const t=io_getInput("remove");if(!t)return[];const r=parseInputArray(t);const s=[];for(const t of r){s.push(await Ta.rm(matchGitArgs(t),(t,r)=>log(e==="all"?null:t,r)).catch(r=>{if(e==="all")return;if(r.message.includes("fatal: pathspec")&&r.message.includes("did not match any files")){if(e==="pathspec")return;const r=io_getInput("pathspec_error_handling"),s=new Error(`Remove command did not match any file:\n git rm ${t}`);if(r==="exitImmediately")throw s;if(r==="exitAtEnd")Ra.push(s)}else throw r}))}return s} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index d4b75a73..4ca4daca 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,12 @@ import * as core from '@actions/core'; import * as path from 'path'; import simpleGit, {Response} from 'simple-git'; import {checkInputs, getInput, logOutputs, setOutput} from './io'; -import {log, matchGitArgs, parseInputArray} from './util'; +import { + log, + matchGitArgs, + parseInputArray, + pickGitIdentityConfig, +} from './util'; const baseDir = path.join(process.cwd(), getInput('cwd') || ''); const git = simpleGit({baseDir}); @@ -50,10 +55,15 @@ core.info(`Running in ${baseDir}`); .addConfig('author.name', getInput('author_name'), undefined, log) .addConfig('committer.email', getInput('committer_email'), undefined, log) .addConfig('committer.name', getInput('committer_name'), undefined, log); - core.debug( - '> Current git config\n' + - JSON.stringify((await git.listConfig()).all, null, 2), - ); + if (core.isDebug()) { + const identity = pickGitIdentityConfig((await git.listConfig()).all); + core.debug( + Object.keys(identity).length + ? '> Current git identity config\n' + + JSON.stringify(identity, null, 2) + : '> Git identity config set (no identity keys present in listConfig)', + ); + } let fetchOption: string | boolean; try { diff --git a/src/util.ts b/src/util.ts index a53568f3..62a108ae 100644 --- a/src/util.ts +++ b/src/util.ts @@ -36,6 +36,32 @@ export function log(err: any, data?: any) { if (err) core.error(err); } +/** Git identity keys this action sets; safe to log (no credentials). */ +const GIT_IDENTITY_CONFIG_KEYS = [ + 'user.name', + 'user.email', + 'author.name', + 'author.email', + 'committer.name', + 'committer.email', +] as const; + +/** + * Picks only git identity config entries for logging. + * Never includes credential-bearing keys (extraheader, remote URLs, etc.). + */ +export function pickGitIdentityConfig( + config: Record, +): Record { + const result: Record = {}; + for (const key of GIT_IDENTITY_CONFIG_KEYS) { + if (Object.prototype.hasOwnProperty.call(config, key)) { + result[key] = config[key]; + } + } + return result; +} + /** * Ensures `name` is safe to pass as a single git branch/ref positional argument. * Rejects empty values, leading hyphens (git option injection), whitespace/control diff --git a/test/util.test.ts b/test/util.test.ts index 39c6aede..3c886aaf 100644 --- a/test/util.test.ts +++ b/test/util.test.ts @@ -2,6 +2,7 @@ import { assertValidBranchName, matchGitArgs, parseInputArray, + pickGitIdentityConfig, } from '../src/util'; describe('parseInputArray', () => { @@ -170,3 +171,44 @@ describe('matchGitArgs', () => { expect(() => matchGitArgs('--exe=evil')).toThrow(/not allowed/); }); }); + +describe('pickGitIdentityConfig', () => { + it('keeps only identity keys', () => { + const picked = pickGitIdentityConfig({ + 'user.name': 'Alice', + 'user.email': 'alice@example.com', + 'author.name': 'Alice', + 'author.email': 'alice@example.com', + 'committer.name': 'Bot', + 'committer.email': 'bot@example.com', + 'http.https://github.com/.extraheader': + 'AUTHORIZATION: basic dGVzdDp0b2tlbg==', + 'credential.helper': 'store', + 'remote.origin.url': + 'https://x-access-token:ghp_secret@github.com/o/r.git', + 'core.sshCommand': 'ssh -i /secrets/id_rsa', + }); + + expect(picked).toStrictEqual({ + 'user.name': 'Alice', + 'user.email': 'alice@example.com', + 'author.name': 'Alice', + 'author.email': 'alice@example.com', + 'committer.name': 'Bot', + 'committer.email': 'bot@example.com', + }); + expect(picked).not.toHaveProperty('http.https://github.com/.extraheader'); + expect(picked).not.toHaveProperty('credential.helper'); + expect(picked).not.toHaveProperty('remote.origin.url'); + expect(picked).not.toHaveProperty('core.sshCommand'); + }); + + it('returns an empty object when no identity keys are present', () => { + expect( + pickGitIdentityConfig({ + 'http.https://github.com/.extraheader': + 'AUTHORIZATION: basic dGVzdDp0b2tlbg==', + }), + ).toStrictEqual({}); + }); +});