mirror of
https://github.com/actions/checkout.git
synced 2026-07-14 19:33:48 +08:00
Compare commits
7 Commits
3d60e0be12
...
releases/v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6026fb2ad3 | ||
|
|
93cb6efe18 | ||
|
|
08c6903cd8 | ||
|
|
9f265659d3 | ||
|
|
08eba0b27e | ||
|
|
631c7dc4f8 | ||
|
|
8edcb1bdb4 |
4
.github/workflows/check-dist.yml
vendored
4
.github/workflows/check-dist.yml
vendored
@@ -24,10 +24,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.6
|
- uses: actions/checkout@v4.1.6
|
||||||
|
|
||||||
- name: Set Node.js 20.x
|
- name: Set Node.js 24.x
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 24.x
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
100
.github/workflows/codeql.yml
vendored
100
.github/workflows/codeql.yml
vendored
@@ -1,100 +0,0 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL Advanced"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '38 16 * * 5'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze (${{ matrix.language }})
|
|
||||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
||||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
||||||
# - https://gh.io/supported-runners-and-hardware-resources
|
|
||||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
|
||||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
||||||
permissions:
|
|
||||||
# required for all workflows
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
# required to fetch internal or private CodeQL packs
|
|
||||||
packages: read
|
|
||||||
|
|
||||||
# only required for workflows in private repositories
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- language: actions
|
|
||||||
build-mode: none
|
|
||||||
- language: javascript-typescript
|
|
||||||
build-mode: none
|
|
||||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
|
||||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
|
||||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
||||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
||||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
|
||||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
|
||||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
|
||||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
|
||||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
|
||||||
# or others). This is typically only required for manual builds.
|
|
||||||
# - name: Setup runtime (example)
|
|
||||||
# uses: actions/setup-example@v1
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
build-mode: ${{ matrix.build-mode }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
|
|
||||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
||||||
# queries: security-extended,security-and-quality
|
|
||||||
|
|
||||||
# If the analyze step fails for one of the languages you are analyzing with
|
|
||||||
# "We were unable to automatically build your code", modify the matrix above
|
|
||||||
# to set the build mode to "manual" for that language. Then modify this step
|
|
||||||
# to build your code.
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
||||||
- if: matrix.build-mode == 'manual'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
||||||
'languages you are analyzing, replace this with the commands to build' \
|
|
||||||
'your code, for example:'
|
|
||||||
echo ' make bootstrap'
|
|
||||||
echo ' make release'
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
18
.github/workflows/docker-image.yml
vendored
18
.github/workflows/docker-image.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
name: Docker Image CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build the Docker image
|
|
||||||
run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
|
|
||||||
129
.github/workflows/fortify.yml
vendored
129
.github/workflows/fortify.yml
vendored
@@ -1,129 +0,0 @@
|
|||||||
# This workflow uses actions that are not certified by GitHub.
|
|
||||||
# They are provided by a third-party and are governed by
|
|
||||||
# separate terms of service, privacy policy, and support
|
|
||||||
# documentation.
|
|
||||||
|
|
||||||
################################################################################################################################################
|
|
||||||
# Fortify Application Security provides your team with solutions to empower DevSecOps practices, enable cloud transformation, and secure your #
|
|
||||||
# software supply chain. To learn more about Fortify, start a free trial or contact our sales team, visit fortify.com. #
|
|
||||||
# #
|
|
||||||
# Use this starter workflow as a basis for integrating Fortify Application Security Testing into your GitHub workflows. This template #
|
|
||||||
# demonstrates the steps to package the code+dependencies, initiate a scan, and optionally import SAST vulnerabilities into GitHub Security #
|
|
||||||
# Code Scanning Alerts. Additional information is available in the workflow comments and the Fortify AST Action / fcli / Fortify product #
|
|
||||||
# documentation. If you need additional assistance, please contact Fortify support. #
|
|
||||||
################################################################################################################################################
|
|
||||||
|
|
||||||
name: Fortify AST Scan
|
|
||||||
|
|
||||||
# Customize trigger events based on your DevSecOps process and/or policy
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ "main" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '40 23 * * 6'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
Fortify-AST-Scan:
|
|
||||||
# Use the appropriate runner for building your source code. Ensure dev tools required to build your code are present and configured appropriately (MSBuild, Python, etc).
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
# pull-requests: write # Required if DO_PR_COMMENT is set to true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Check out source code
|
|
||||||
- name: Check Out Source Code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Perform SAST and/or SCA scan via Fortify on Demand/Fortify Hosted/ScanCentral SAST/Debricked. Based on
|
|
||||||
# configuration, the Fortify GitHub Action can optionally set up the application version/release, generate
|
|
||||||
# job summaries and Pull Request comments, and/or export SAST results to the GitHub code scanning dashboard.
|
|
||||||
# The Fortify GitHub Action provides many customization capabilities, but in case further customization is
|
|
||||||
# required, you can use sub-actions like fortify/github-action/setup@v1 to set up the various Fortify tools
|
|
||||||
# and run them directly from within your pipeline. It is recommended to review the Fortify GitHub Action
|
|
||||||
# documentation at https://github.com/fortify/github-action#readme for more information on the various
|
|
||||||
# configuration options and available sub-actions.
|
|
||||||
- name: Run Fortify Scan
|
|
||||||
# Specify Fortify GitHub Action version to run. As per GitHub starter workflow requirements, this example
|
|
||||||
# uses the commit id corresponding to version 1.6.2. It is recommended to check whether any later releases
|
|
||||||
# are available at https://github.com/fortify/github-action/releases. Depending on the amount of stability
|
|
||||||
# required, you may want to consider using fortify/github-action@v1 instead to use the latest 1.x.y version
|
|
||||||
# of this action, allowing your workflows to automatically benefit from any new features and bug fixes.
|
|
||||||
uses: fortify/github-action@ef5539bf4bd9c45c0bd971978f635a69eae55297
|
|
||||||
with:
|
|
||||||
sast-scan: true # Run a SAST scan; if not specified or set to false, no SAST scan will be run
|
|
||||||
debricked-sca-scan: true # For FoD, run an open-source scan as part of the SAST scan (ignored if SAST scan
|
|
||||||
# is disabled). For SSC, run a Debricked scan and import results into SSC.
|
|
||||||
env:
|
|
||||||
#############################################################
|
|
||||||
##### Fortify on Demand configuration
|
|
||||||
##### Remove this section if you're integrating with Fortify Hosted/Software Security Center (see below)
|
|
||||||
### Required configuration
|
|
||||||
FOD_URL: https://ams.fortify.com # Must be hardcoded or configured through GitHub variable, not secret
|
|
||||||
FOD_TENANT: ${{secrets.FOD_TENANT}} # Either tenant/user/password or client id/secret are required;
|
|
||||||
FOD_USER: ${{secrets.FOD_USER}} # these should be configured through GitHub secrets.
|
|
||||||
FOD_PASSWORD: ${{secrets.FOD_PAT}}
|
|
||||||
# FOD_CLIENT_ID: ${{secrets.FOD_CLIENT_ID}}
|
|
||||||
# FOD_CLIENT_SECRET: ${{secrets.FOD_CLIENT_SECRET}}
|
|
||||||
### Optional configuration
|
|
||||||
# FOD_LOGIN_EXTRA_OPTS: --socket-timeout=60s # Extra 'fcli fod session login' options
|
|
||||||
# FOD_RELEASE: MyApp:MyRelease # FoD release name, default: <org>/<repo>:<branch>
|
|
||||||
# DO_SETUP: true # Setup FoD application, release & static scan configuration
|
|
||||||
# SETUP_ACTION: <URL or file> # Customize setup action
|
|
||||||
# Pass extra options to setup action:
|
|
||||||
# SETUP_EXTRA_OPTS: --copy-from "${{ github.repository }}:${{ github.event.repository.default_branch }}"
|
|
||||||
# PACKAGE_EXTRA_OPTS: -oss -bt mvn # Extra 'scancentral package' options
|
|
||||||
# FOD_SAST_SCAN_EXTRA_OPTS: # Extra 'fcli fod sast-scan start' options
|
|
||||||
# DO_WAIT: true # Wait for successful scan completion (implied if post-scan actions enabled)
|
|
||||||
# DO_POLICY_CHECK: true # Fail pipeline if security policy outcome is FAIL
|
|
||||||
# POLICY_CHECK_ACTION: <URL or file> # Customize security policy checks
|
|
||||||
# POLICY_CHECK_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to policy check action
|
|
||||||
# DO_JOB_SUMMARY: true # Generate workflow job summary
|
|
||||||
# JOB_SUMMARY_ACTION: <URL or file> # Customize job summary
|
|
||||||
# JOB_SUMMARY_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to job summary action
|
|
||||||
# DO_PR_COMMENT: true # Generate PR comments, only used on pull_request triggers
|
|
||||||
# PR_COMMENT_ACTION: <URL or file> # Customize PR comments
|
|
||||||
# PR_COMMENT_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to PR comment action
|
|
||||||
# DO_EXPORT: true # Export vulnerability data to GitHub code scanning dashboard
|
|
||||||
# EXPORT_ACTION: <URL or file> # Customize export action
|
|
||||||
# EXPORT_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to export action
|
|
||||||
# TOOL_DEFINITIONS: <URL> # URL from where to retrieve Fortify tool definitions
|
|
||||||
|
|
||||||
#############################################################
|
|
||||||
##### Fortify Hosted / Software Security Center & ScanCentral
|
|
||||||
##### Remove this section if you're integrating with Fortify on Demand (see above)
|
|
||||||
### Required configuration
|
|
||||||
SSC_URL: ${{vars.SSC_URL}} # Must be hardcoded or configured through GitHub variable, not secret
|
|
||||||
SSC_TOKEN: ${{secrets.SSC_TOKEN}} # SSC CIToken; credentials should be configured through GitHub secrets
|
|
||||||
SC_SAST_TOKEN: ${{secrets.SC_CLIENT_AUTH_TOKEN}} # ScanCentral SAST client_auth_token, required if SAST scan is enabled
|
|
||||||
DEBRICKED_TOKEN: ${{secrets.DEBRICKED_TOKEN}} # Debricked token, required if Debricked scan is enabled
|
|
||||||
SC_SAST_SENSOR_VERSION: 24.4.0 # Sensor version to use for the scan, required if SAST scan is enabled
|
|
||||||
### Optional configuration
|
|
||||||
# SSC_LOGIN_EXTRA_OPTS: --socket-timeout=60s # Extra 'fcli ssc session login' options
|
|
||||||
# SC_SAST_LOGIN_EXTRA_OPTS: --socket-timeout=60s # Extra 'fcli sc-sast session login' options
|
|
||||||
# SSC_APPVERSION: MyApp:MyVersion # SSC application version name, default: <org>/<repo>:<branch>
|
|
||||||
# DO_SETUP: true # Set up SSC application & version
|
|
||||||
# SETUP_ACTION: <URL or file> # Customize setup action
|
|
||||||
# SETUP_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to setup action
|
|
||||||
# PACKAGE_EXTRA_OPTS: -bt mvn # Extra 'scancentral package' options
|
|
||||||
# EXTRA_SC_SAST_SCAN_OPTS: # Extra 'fcli sc-sast scan start' options
|
|
||||||
# DO_WAIT: true # Wait for successful scan completion (implied if post-scan actions enabled)
|
|
||||||
# DO_POLICY_CHECK: true # Fail pipeline if security policy outcome is FAIL
|
|
||||||
# POLICY_CHECK_ACTION: <URL or file> # Customize security policy checks
|
|
||||||
# POLICY_CHECK_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to policy check action
|
|
||||||
# DO_JOB_SUMMARY: true # Generate workflow job summary
|
|
||||||
# JOB_SUMMARY_ACTION: <URL or file> # Customize job summary
|
|
||||||
# JOB_SUMMARY_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to job summary action
|
|
||||||
# DO_PR_COMMENT: true # Generate PR comments, only used on pull_request triggers
|
|
||||||
# PR_COMMENT_ACTION: <URL or file> # Customize PR comments
|
|
||||||
# PR_COMMENT_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to PR comment action
|
|
||||||
# DO_EXPORT: true # Export vulnerability data to GitHub code scanning dashboard
|
|
||||||
# EXPORT_ACTION: <URL or file> # Customize export action
|
|
||||||
# EXPORT_EXTRA_OPTS: --on-unsigned=ignore # Pass extra options to export action
|
|
||||||
# TOOL_DEFINITIONS: <URL> # URL from where to retrieve Fortify tool definitions
|
|
||||||
51
.github/workflows/jekyll-gh-pages.yml
vendored
51
.github/workflows/jekyll-gh-pages.yml
vendored
@@ -1,51 +0,0 @@
|
|||||||
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
|
|
||||||
name: Deploy Jekyll with GitHub Pages dependencies preinstalled
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Runs on pushes targeting the default branch
|
|
||||||
push:
|
|
||||||
branches: ["main"]
|
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
||||||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
||||||
concurrency:
|
|
||||||
group: "pages"
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Build job
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Pages
|
|
||||||
uses: actions/configure-pages@v5
|
|
||||||
- name: Build with Jekyll
|
|
||||||
uses: actions/jekyll-build-pages@v1
|
|
||||||
with:
|
|
||||||
source: ./
|
|
||||||
destination: ./_site
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-pages-artifact@v3
|
|
||||||
|
|
||||||
# Deployment job
|
|
||||||
deploy:
|
|
||||||
environment:
|
|
||||||
name: github-pages
|
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v4
|
|
||||||
16
.github/workflows/main.yml
vendored
16
.github/workflows/main.yml
vendored
@@ -1,16 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
|
|
||||||
- package-ecosystem: "terraform"
|
|
||||||
directory: "/infra"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
|
|
||||||
- package-ecosystem: "docker"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 24.x
|
||||||
- uses: actions/checkout@v4.1.6
|
- uses: actions/checkout@v4.1.6
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
|
|||||||
1
.github/workflows/update-main-version.yml
vendored
1
.github/workflows/update-main-version.yml
vendored
@@ -11,6 +11,7 @@ on:
|
|||||||
type: choice
|
type: choice
|
||||||
description: The major version to update
|
description: The major version to update
|
||||||
options:
|
options:
|
||||||
|
- v5
|
||||||
- v4
|
- v4
|
||||||
- v3
|
- v3
|
||||||
- v2
|
- v2
|
||||||
|
|||||||
4
.licenses/npm/@octokit/endpoint.dep.yml
generated
4
.licenses/npm/@octokit/endpoint.dep.yml
generated
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
name: "@octokit/endpoint"
|
name: "@octokit/endpoint"
|
||||||
version: 9.0.5
|
version: 9.0.6
|
||||||
type: npm
|
type: npm
|
||||||
summary: Turns REST API endpoints into generic request options
|
summary: Turns REST API endpoints into generic request options
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
name: "@octokit/plugin-paginate-rest"
|
name: "@octokit/plugin-paginate-rest"
|
||||||
version: 9.2.1
|
version: 9.2.2
|
||||||
type: npm
|
type: npm
|
||||||
summary: Octokit plugin to paginate REST API endpoint responses
|
summary: Octokit plugin to paginate REST API endpoint responses
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|||||||
4
.licenses/npm/@octokit/request-error.dep.yml
generated
4
.licenses/npm/@octokit/request-error.dep.yml
generated
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
name: "@octokit/request-error"
|
name: "@octokit/request-error"
|
||||||
version: 5.1.0
|
version: 5.1.1
|
||||||
type: npm
|
type: npm
|
||||||
summary: Error class for Octokit request errors
|
summary: Error class for Octokit request errors
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|||||||
4
.licenses/npm/@octokit/request.dep.yml
generated
4
.licenses/npm/@octokit/request.dep.yml
generated
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
name: "@octokit/request"
|
name: "@octokit/request"
|
||||||
version: 8.4.0
|
version: 8.4.1
|
||||||
type: npm
|
type: npm
|
||||||
summary: Send parameterized requests to GitHub's APIs with sensible defaults in browsers
|
summary: Send parameterized requests to GitHub's APIs with sensible defaults in browsers
|
||||||
and Node
|
and Node
|
||||||
homepage:
|
homepage:
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
|
|||||||
2
.licenses/npm/undici.dep.yml
generated
2
.licenses/npm/undici.dep.yml
generated
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: undici
|
name: undici
|
||||||
version: 5.28.4
|
version: 5.29.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: An HTTP/1.1 client, written from scratch for Node.js
|
summary: An HTTP/1.1 client, written from scratch for Node.js
|
||||||
homepage: https://undici.nodejs.org
|
homepage: https://undici.nodejs.org
|
||||||
|
|||||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## V5.0.0
|
||||||
|
* Update actions checkout to use node 24 by @salmanmkc in https://github.com/actions/checkout/pull/2226
|
||||||
|
|
||||||
|
|
||||||
|
## V4.3.0
|
||||||
|
* docs: update README.md by @motss in https://github.com/actions/checkout/pull/1971
|
||||||
|
* Add internal repos for checking out multiple repositories by @mouismail in https://github.com/actions/checkout/pull/1977
|
||||||
|
* Documentation update - add recommended permissions to Readme by @benwells in https://github.com/actions/checkout/pull/2043
|
||||||
|
* Adjust positioning of user email note and permissions heading by @joshmgross in https://github.com/actions/checkout/pull/2044
|
||||||
|
* Update README.md by @nebuk89 in https://github.com/actions/checkout/pull/2194
|
||||||
|
* Update CODEOWNERS for actions by @TingluoHuang in https://github.com/actions/checkout/pull/2224
|
||||||
|
* Update package dependencies by @salmanmkc in https://github.com/actions/checkout/pull/2236
|
||||||
|
|
||||||
## v4.2.2
|
## v4.2.2
|
||||||
* `url-helper.ts` now leverages well-known environment variables by @jww3 in https://github.com/actions/checkout/pull/1941
|
* `url-helper.ts` now leverages well-known environment variables by @jww3 in https://github.com/actions/checkout/pull/1941
|
||||||
* Expand unit test coverage for `isGhes` by @jww3 in https://github.com/actions/checkout/pull/1946
|
* Expand unit test coverage for `isGhes` by @jww3 in https://github.com/actions/checkout/pull/1946
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
* @actions/actions-launch
|
* @actions/actions-runtime
|
||||||
|
|||||||
81
README.md
81
README.md
@@ -1,5 +1,9 @@
|
|||||||
[](https://github.com/actions/checkout/actions/workflows/test.yml)
|
[](https://github.com/actions/checkout/actions/workflows/test.yml)
|
||||||
|
|
||||||
|
# Checkout V5
|
||||||
|
|
||||||
|
Checkout v5 now supports Node.js 24
|
||||||
|
|
||||||
# Checkout V4
|
# Checkout V4
|
||||||
|
|
||||||
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
|
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
|
||||||
@@ -36,7 +40,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
|
|
||||||
<!-- start usage -->
|
<!-- start usage -->
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
# Repository name with owner. For example, actions/checkout
|
# Repository name with owner. For example, actions/checkout
|
||||||
# Default: ${{ github.repository }}
|
# Default: ${{ github.repository }}
|
||||||
@@ -144,29 +148,46 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
# running from unless specified. Example URLs are https://github.com or
|
# running from unless specified. Example URLs are https://github.com or
|
||||||
# https://my-ghes-server.example.com
|
# https://my-ghes-server.example.com
|
||||||
github-server-url: ''
|
github-server-url: ''
|
||||||
|
|
||||||
|
# Required to check out fork pull request code from a workflow triggered by
|
||||||
|
# `pull_request_target` or `workflow_run`. These workflows run with the base
|
||||||
|
# repository's GITHUB_TOKEN, secrets, default-branch cache scope, and runner
|
||||||
|
# access; fetching and executing a fork's code in that trusted context commonly
|
||||||
|
# leads to "pwn request" vulnerabilities. Set to `true` only after reviewing the
|
||||||
|
# risks at https://gh.io/securely-using-pull_request_target.
|
||||||
|
# Default: false
|
||||||
|
allow-unsafe-pr-checkout: ''
|
||||||
```
|
```
|
||||||
<!-- end usage -->
|
<!-- end usage -->
|
||||||
|
|
||||||
# Scenarios
|
# Scenarios
|
||||||
|
|
||||||
- [Fetch only the root files](#Fetch-only-the-root-files)
|
- [Checkout V5](#checkout-v5)
|
||||||
- [Fetch only the root files and `.github` and `src` folder](#Fetch-only-the-root-files-and-github-and-src-folder)
|
- [Checkout V4](#checkout-v4)
|
||||||
- [Fetch only a single file](#Fetch-only-a-single-file)
|
- [Note](#note)
|
||||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
- [What's new](#whats-new)
|
||||||
- [Checkout a different branch](#Checkout-a-different-branch)
|
- [Usage](#usage)
|
||||||
- [Checkout HEAD^](#Checkout-HEAD)
|
- [Scenarios](#scenarios)
|
||||||
- [Checkout multiple repos (side by side)](#Checkout-multiple-repos-side-by-side)
|
- [Fetch only the root files](#fetch-only-the-root-files)
|
||||||
- [Checkout multiple repos (nested)](#Checkout-multiple-repos-nested)
|
- [Fetch only the root files and `.github` and `src` folder](#fetch-only-the-root-files-and-github-and-src-folder)
|
||||||
- [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
|
- [Fetch only a single file](#fetch-only-a-single-file)
|
||||||
- [Checkout pull request HEAD commit instead of merge commit](#Checkout-pull-request-HEAD-commit-instead-of-merge-commit)
|
- [Fetch all history for all tags and branches](#fetch-all-history-for-all-tags-and-branches)
|
||||||
- [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
|
- [Checkout a different branch](#checkout-a-different-branch)
|
||||||
- [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
|
- [Checkout HEAD^](#checkout-head)
|
||||||
- [Push a commit to a PR using the built-in token](#Push-a-commit-to-a-PR-using-the-built-in-token)
|
- [Checkout multiple repos (side by side)](#checkout-multiple-repos-side-by-side)
|
||||||
|
- [Checkout multiple repos (nested)](#checkout-multiple-repos-nested)
|
||||||
|
- [Checkout multiple repos (private)](#checkout-multiple-repos-private)
|
||||||
|
- [Checkout pull request HEAD commit instead of merge commit](#checkout-pull-request-head-commit-instead-of-merge-commit)
|
||||||
|
- [Checkout pull request on closed event](#checkout-pull-request-on-closed-event)
|
||||||
|
- [Push a commit using the built-in token](#push-a-commit-using-the-built-in-token)
|
||||||
|
- [Push a commit to a PR using the built-in token](#push-a-commit-to-a-pr-using-the-built-in-token)
|
||||||
|
- [Recommended permissions](#recommended-permissions)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
## Fetch only the root files
|
## Fetch only the root files
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
sparse-checkout: .
|
sparse-checkout: .
|
||||||
```
|
```
|
||||||
@@ -174,7 +195,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Fetch only the root files and `.github` and `src` folder
|
## Fetch only the root files and `.github` and `src` folder
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
sparse-checkout: |
|
sparse-checkout: |
|
||||||
.github
|
.github
|
||||||
@@ -184,7 +205,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Fetch only a single file
|
## Fetch only a single file
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
sparse-checkout: |
|
sparse-checkout: |
|
||||||
README.md
|
README.md
|
||||||
@@ -194,7 +215,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Fetch all history for all tags and branches
|
## Fetch all history for all tags and branches
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
```
|
```
|
||||||
@@ -202,7 +223,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Checkout a different branch
|
## Checkout a different branch
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
ref: my-branch
|
ref: my-branch
|
||||||
```
|
```
|
||||||
@@ -210,7 +231,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Checkout HEAD^
|
## Checkout HEAD^
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- run: git checkout HEAD^
|
- run: git checkout HEAD^
|
||||||
@@ -220,12 +241,12 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
path: main
|
path: main
|
||||||
|
|
||||||
- name: Checkout tools repo
|
- name: Checkout tools repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
repository: my-org/my-tools
|
repository: my-org/my-tools
|
||||||
path: my-tools
|
path: my-tools
|
||||||
@@ -236,10 +257,10 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Checkout tools repo
|
- name: Checkout tools repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
repository: my-org/my-tools
|
repository: my-org/my-tools
|
||||||
path: my-tools
|
path: my-tools
|
||||||
@@ -250,12 +271,12 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
path: main
|
path: main
|
||||||
|
|
||||||
- name: Checkout private tools
|
- name: Checkout private tools
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
repository: my-org/my-private-tools
|
repository: my-org/my-private-tools
|
||||||
token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
|
token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
|
||||||
@@ -268,7 +289,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
## Checkout pull request HEAD commit instead of merge commit
|
## Checkout pull request HEAD commit instead of merge commit
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
```
|
```
|
||||||
@@ -284,7 +305,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
```
|
```
|
||||||
|
|
||||||
## Push a commit using the built-in token
|
## Push a commit using the built-in token
|
||||||
@@ -295,7 +316,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- run: |
|
- run: |
|
||||||
date > generated.txt
|
date > generated.txt
|
||||||
# Note: the following account information will not work on GHES
|
# Note: the following account information will not work on GHES
|
||||||
@@ -317,7 +338,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.head_ref }}
|
ref: ${{ github.head_ref }}
|
||||||
- run: |
|
- run: |
|
||||||
|
|||||||
21
SECURITY.md
21
SECURITY.md
@@ -1,21 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Use this section to tell people about which versions of your project are
|
|
||||||
currently being supported with security updates.
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| 5.1.x | :white_check_mark: |
|
|
||||||
| 5.0.x | :x: |
|
|
||||||
| 4.0.x | :white_check_mark: |
|
|
||||||
| < 4.0 | :x: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Use this section to tell people how to report a vulnerability.
|
|
||||||
|
|
||||||
Tell them where to go, how often they can expect to get an update on a
|
|
||||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
|
||||||
declined, etc.
|
|
||||||
@@ -675,6 +675,283 @@ describe('git-auth-helper tests', () => {
|
|||||||
expect(gitConfigContent.indexOf('http.')).toBeLessThan(0)
|
expect(gitConfigContent.indexOf('http.')).toBeLessThan(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const removeAuth_removesV6StyleCredentials =
|
||||||
|
'removeAuth removes v6 style credentials'
|
||||||
|
it(removeAuth_removesV6StyleCredentials, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(removeAuth_removesV6StyleCredentials)
|
||||||
|
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
|
await authHelper.configureAuth()
|
||||||
|
|
||||||
|
// Manually create v6-style credentials that would be left by v6
|
||||||
|
const credentialsFileName =
|
||||||
|
'git-credentials-12345678-1234-1234-1234-123456789abc.config'
|
||||||
|
const credentialsFilePath = path.join(runnerTemp, credentialsFileName)
|
||||||
|
const basicCredential = Buffer.from(
|
||||||
|
`x-access-token:${settings.authToken}`,
|
||||||
|
'utf8'
|
||||||
|
).toString('base64')
|
||||||
|
const credentialsContent = `[http "https://github.com/"]\n\textraheader = AUTHORIZATION: basic ${basicCredential}\n`
|
||||||
|
await fs.promises.writeFile(credentialsFilePath, credentialsContent)
|
||||||
|
|
||||||
|
// Add includeIf entries to local git config (simulating v6 configuration)
|
||||||
|
const hostGitDir = path.join(workspace, '.git').replace(/\\/g, '/')
|
||||||
|
await fs.promises.appendFile(
|
||||||
|
localGitConfigPath,
|
||||||
|
`[includeIf "gitdir:${hostGitDir}/"]\n\tpath = ${credentialsFilePath}\n`
|
||||||
|
)
|
||||||
|
await fs.promises.appendFile(
|
||||||
|
localGitConfigPath,
|
||||||
|
`[includeIf "gitdir:/github/workspace/.git/"]\n\tpath = /github/runner_temp/${credentialsFileName}\n`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify v6 style config exists
|
||||||
|
let gitConfigContent = (
|
||||||
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(gitConfigContent.indexOf('includeIf')).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
gitConfigContent.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
await fs.promises.stat(credentialsFilePath) // Verify file exists
|
||||||
|
|
||||||
|
// Mock the git methods to handle v6 cleanup
|
||||||
|
const mockTryGetConfigKeys = git.tryGetConfigKeys as jest.Mock<any, any>
|
||||||
|
mockTryGetConfigKeys.mockResolvedValue([
|
||||||
|
`includeIf.gitdir:${hostGitDir}/.path`,
|
||||||
|
'includeIf.gitdir:/github/workspace/.git/.path'
|
||||||
|
])
|
||||||
|
|
||||||
|
const mockTryGetConfigValues = git.tryGetConfigValues as jest.Mock<any, any>
|
||||||
|
mockTryGetConfigValues.mockImplementation(async (key: string) => {
|
||||||
|
if (key === `includeIf.gitdir:${hostGitDir}/.path`) {
|
||||||
|
return [credentialsFilePath]
|
||||||
|
}
|
||||||
|
if (key === 'includeIf.gitdir:/github/workspace/.git/.path') {
|
||||||
|
return [`/github/runner_temp/${credentialsFileName}`]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockTryConfigUnsetValue = git.tryConfigUnsetValue as jest.Mock<
|
||||||
|
any,
|
||||||
|
any
|
||||||
|
>
|
||||||
|
mockTryConfigUnsetValue.mockImplementation(
|
||||||
|
async (
|
||||||
|
key: string,
|
||||||
|
value: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configPath?: string
|
||||||
|
) => {
|
||||||
|
const targetPath = configPath || localGitConfigPath
|
||||||
|
let content = await fs.promises.readFile(targetPath, 'utf8')
|
||||||
|
// Remove the includeIf section
|
||||||
|
const lines = content
|
||||||
|
.split('\n')
|
||||||
|
.filter(line => !line.includes('includeIf') && !line.includes(value))
|
||||||
|
await fs.promises.writeFile(targetPath, lines.join('\n'))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authHelper.removeAuth()
|
||||||
|
|
||||||
|
// Assert includeIf entries removed from local git config
|
||||||
|
gitConfigContent = (
|
||||||
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(gitConfigContent.indexOf('includeIf')).toBeLessThan(0)
|
||||||
|
expect(gitConfigContent.indexOf(credentialsFilePath)).toBeLessThan(0)
|
||||||
|
|
||||||
|
// Assert credentials config file deleted
|
||||||
|
try {
|
||||||
|
await fs.promises.stat(credentialsFilePath)
|
||||||
|
throw new Error('Credentials file should have been deleted')
|
||||||
|
} catch (err) {
|
||||||
|
if ((err as any)?.code !== 'ENOENT') {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const removeAuth_removesV6StyleCredentialsFromSubmodules =
|
||||||
|
'removeAuth removes v6 style credentials from submodules'
|
||||||
|
it(removeAuth_removesV6StyleCredentialsFromSubmodules, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(removeAuth_removesV6StyleCredentialsFromSubmodules)
|
||||||
|
|
||||||
|
// Create fake submodule config paths
|
||||||
|
const submodule1Dir = path.join(workspace, '.git', 'modules', 'submodule-1')
|
||||||
|
const submodule1ConfigPath = path.join(submodule1Dir, 'config')
|
||||||
|
await fs.promises.mkdir(submodule1Dir, {recursive: true})
|
||||||
|
await fs.promises.writeFile(submodule1ConfigPath, '')
|
||||||
|
|
||||||
|
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
|
await authHelper.configureAuth()
|
||||||
|
|
||||||
|
// Create v6-style credentials file
|
||||||
|
const credentialsFileName =
|
||||||
|
'git-credentials-abcdef12-3456-7890-abcd-ef1234567890.config'
|
||||||
|
const credentialsFilePath = path.join(runnerTemp, credentialsFileName)
|
||||||
|
const basicCredential = Buffer.from(
|
||||||
|
`x-access-token:${settings.authToken}`,
|
||||||
|
'utf8'
|
||||||
|
).toString('base64')
|
||||||
|
const credentialsContent = `[http "https://github.com/"]\n\textraheader = AUTHORIZATION: basic ${basicCredential}\n`
|
||||||
|
await fs.promises.writeFile(credentialsFilePath, credentialsContent)
|
||||||
|
|
||||||
|
// Add includeIf entries to submodule config
|
||||||
|
const submodule1GitDir = submodule1Dir.replace(/\\/g, '/')
|
||||||
|
await fs.promises.appendFile(
|
||||||
|
submodule1ConfigPath,
|
||||||
|
`[includeIf "gitdir:${submodule1GitDir}/"]\n\tpath = ${credentialsFilePath}\n`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify submodule config has includeIf entry
|
||||||
|
let submoduleConfigContent = (
|
||||||
|
await fs.promises.readFile(submodule1ConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(submoduleConfigContent.indexOf('includeIf')).toBeGreaterThanOrEqual(
|
||||||
|
0
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
submoduleConfigContent.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Mock getSubmoduleConfigPaths
|
||||||
|
const mockGetSubmoduleConfigPaths =
|
||||||
|
git.getSubmoduleConfigPaths as jest.Mock<any, any>
|
||||||
|
mockGetSubmoduleConfigPaths.mockResolvedValue([submodule1ConfigPath])
|
||||||
|
|
||||||
|
// Mock tryGetConfigKeys for submodule
|
||||||
|
const mockTryGetConfigKeys = git.tryGetConfigKeys as jest.Mock<any, any>
|
||||||
|
mockTryGetConfigKeys.mockImplementation(
|
||||||
|
async (pattern: string, globalConfig?: boolean, configPath?: string) => {
|
||||||
|
if (configPath === submodule1ConfigPath) {
|
||||||
|
return [`includeIf.gitdir:${submodule1GitDir}/.path`]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mock tryGetConfigValues for submodule
|
||||||
|
const mockTryGetConfigValues = git.tryGetConfigValues as jest.Mock<any, any>
|
||||||
|
mockTryGetConfigValues.mockImplementation(
|
||||||
|
async (key: string, globalConfig?: boolean, configPath?: string) => {
|
||||||
|
if (
|
||||||
|
configPath === submodule1ConfigPath &&
|
||||||
|
key === `includeIf.gitdir:${submodule1GitDir}/.path`
|
||||||
|
) {
|
||||||
|
return [credentialsFilePath]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mock tryConfigUnsetValue for submodule
|
||||||
|
const mockTryConfigUnsetValue = git.tryConfigUnsetValue as jest.Mock<
|
||||||
|
any,
|
||||||
|
any
|
||||||
|
>
|
||||||
|
mockTryConfigUnsetValue.mockImplementation(
|
||||||
|
async (
|
||||||
|
key: string,
|
||||||
|
value: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configPath?: string
|
||||||
|
) => {
|
||||||
|
const targetPath = configPath || localGitConfigPath
|
||||||
|
let content = await fs.promises.readFile(targetPath, 'utf8')
|
||||||
|
const lines = content
|
||||||
|
.split('\n')
|
||||||
|
.filter(line => !line.includes('includeIf') && !line.includes(value))
|
||||||
|
await fs.promises.writeFile(targetPath, lines.join('\n'))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authHelper.removeAuth()
|
||||||
|
|
||||||
|
// Assert submodule includeIf entries removed
|
||||||
|
submoduleConfigContent = (
|
||||||
|
await fs.promises.readFile(submodule1ConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(submoduleConfigContent.indexOf('includeIf')).toBeLessThan(0)
|
||||||
|
expect(submoduleConfigContent.indexOf(credentialsFilePath)).toBeLessThan(0)
|
||||||
|
|
||||||
|
// Assert credentials file deleted
|
||||||
|
try {
|
||||||
|
await fs.promises.stat(credentialsFilePath)
|
||||||
|
throw new Error('Credentials file should have been deleted')
|
||||||
|
} catch (err) {
|
||||||
|
if ((err as any)?.code !== 'ENOENT') {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const removeAuth_skipsV6CleanupWhenEnvVarSet =
|
||||||
|
'removeAuth skips v6 cleanup when ACTIONS_CHECKOUT_SKIP_V6_CLEANUP is set'
|
||||||
|
it(removeAuth_skipsV6CleanupWhenEnvVarSet, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(removeAuth_skipsV6CleanupWhenEnvVarSet)
|
||||||
|
|
||||||
|
// Set the skip environment variable
|
||||||
|
process.env['ACTIONS_CHECKOUT_SKIP_V6_CLEANUP'] = '1'
|
||||||
|
|
||||||
|
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
|
await authHelper.configureAuth()
|
||||||
|
|
||||||
|
// Create v6-style credentials file in RUNNER_TEMP
|
||||||
|
const credentialsFileName = 'git-credentials-test-uuid-1234-5678.config'
|
||||||
|
const credentialsFilePath = path.join(runnerTemp, credentialsFileName)
|
||||||
|
const credentialsContent =
|
||||||
|
'[http "https://github.com/"]\n\textraheader = AUTHORIZATION: basic token\n'
|
||||||
|
await fs.promises.writeFile(credentialsFilePath, credentialsContent)
|
||||||
|
|
||||||
|
// Add includeIf section to local git config (separate from http.* config)
|
||||||
|
const includeIfSection = `\n[includeIf "gitdir:/some/path/.git/"]\n\tpath = ${credentialsFilePath}\n`
|
||||||
|
await fs.promises.appendFile(localGitConfigPath, includeIfSection)
|
||||||
|
|
||||||
|
// Verify v6 style config exists
|
||||||
|
let gitConfigContent = (
|
||||||
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(gitConfigContent.indexOf('includeIf')).toBeGreaterThanOrEqual(0)
|
||||||
|
await fs.promises.stat(credentialsFilePath) // Verify file exists
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await authHelper.removeAuth()
|
||||||
|
|
||||||
|
// Assert v5 cleanup still happened (http.* removed)
|
||||||
|
gitConfigContent = (
|
||||||
|
await fs.promises.readFile(localGitConfigPath)
|
||||||
|
).toString()
|
||||||
|
expect(
|
||||||
|
gitConfigContent.indexOf('http.https://github.com/.extraheader')
|
||||||
|
).toBeLessThan(0)
|
||||||
|
|
||||||
|
// Assert v6 cleanup was skipped - includeIf should still be present
|
||||||
|
expect(gitConfigContent.indexOf('includeIf')).toBeGreaterThanOrEqual(0)
|
||||||
|
expect(
|
||||||
|
gitConfigContent.indexOf(credentialsFilePath)
|
||||||
|
).toBeGreaterThanOrEqual(0)
|
||||||
|
|
||||||
|
// Assert credentials file still exists (wasn't deleted)
|
||||||
|
await fs.promises.stat(credentialsFilePath) // File should still exist
|
||||||
|
|
||||||
|
// Assert debug message was logged
|
||||||
|
expect(core.debug).toHaveBeenCalledWith(
|
||||||
|
'Skipping v6 style cleanup due to ACTIONS_CHECKOUT_SKIP_V6_CLEANUP'
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
delete process.env['ACTIONS_CHECKOUT_SKIP_V6_CLEANUP']
|
||||||
|
})
|
||||||
|
|
||||||
const removeGlobalConfig_removesOverride =
|
const removeGlobalConfig_removesOverride =
|
||||||
'removeGlobalConfig removes override'
|
'removeGlobalConfig removes override'
|
||||||
it(removeGlobalConfig_removesOverride, async () => {
|
it(removeGlobalConfig_removesOverride, async () => {
|
||||||
@@ -796,6 +1073,18 @@ async function setup(testName: string): Promise<void> {
|
|||||||
),
|
),
|
||||||
tryDisableAutomaticGarbageCollection: jest.fn(),
|
tryDisableAutomaticGarbageCollection: jest.fn(),
|
||||||
tryGetFetchUrl: jest.fn(),
|
tryGetFetchUrl: jest.fn(),
|
||||||
|
getSubmoduleConfigPaths: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
|
tryConfigUnsetValue: jest.fn(async () => {
|
||||||
|
return true
|
||||||
|
}),
|
||||||
|
tryGetConfigValues: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
|
tryGetConfigKeys: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
tryReset: jest.fn(),
|
tryReset: jest.fn(),
|
||||||
version: jest.fn()
|
version: jest.fn()
|
||||||
}
|
}
|
||||||
@@ -824,7 +1113,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
sshUser: '',
|
sshUser: '',
|
||||||
workflowOrganizationId: 123456,
|
workflowOrganizationId: 123456,
|
||||||
setSafeDirectory: true,
|
setSafeDirectory: true,
|
||||||
githubServerUrl: githubServerUrl
|
githubServerUrl: githubServerUrl,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -499,6 +499,18 @@ async function setup(testName: string): Promise<void> {
|
|||||||
await fs.promises.stat(path.join(repositoryPath, '.git'))
|
await fs.promises.stat(path.join(repositoryPath, '.git'))
|
||||||
return repositoryUrl
|
return repositoryUrl
|
||||||
}),
|
}),
|
||||||
|
getSubmoduleConfigPaths: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
|
tryConfigUnsetValue: jest.fn(async () => {
|
||||||
|
return true
|
||||||
|
}),
|
||||||
|
tryGetConfigValues: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
|
tryGetConfigKeys: jest.fn(async () => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
tryReset: jest.fn(async () => {
|
tryReset: jest.fn(async () => {
|
||||||
return true
|
return true
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ describe('input-helper tests', () => {
|
|||||||
expect(settings.repositoryOwner).toBe('some-owner')
|
expect(settings.repositoryOwner).toBe('some-owner')
|
||||||
expect(settings.repositoryPath).toBe(gitHubWorkspace)
|
expect(settings.repositoryPath).toBe(gitHubWorkspace)
|
||||||
expect(settings.setSafeDirectory).toBe(true)
|
expect(settings.setSafeDirectory).toBe(true)
|
||||||
|
expect(settings.allowUnsafePrCheckout).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('qualifies ref', async () => {
|
it('qualifies ref', async () => {
|
||||||
|
|||||||
267
__test__/unsafe-pr-checkout-helper.test.ts
Normal file
267
__test__/unsafe-pr-checkout-helper.test.ts
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
import * as github from '@actions/github'
|
||||||
|
import {assertSafePrCheckout} from '../lib/unsafe-pr-checkout-helper'
|
||||||
|
|
||||||
|
// Shallow clone original @actions/github context
|
||||||
|
const originalContext = {...github.context}
|
||||||
|
const originalEventName = github.context.eventName
|
||||||
|
const originalPayload = github.context.payload
|
||||||
|
|
||||||
|
const BASE_REPO_ID = 100
|
||||||
|
const FORK_REPO_ID = 200
|
||||||
|
const PR_HEAD_SHA = '1111111111111111111111111111111111111111'
|
||||||
|
const PR_MERGE_SHA = '2222222222222222222222222222222222222222'
|
||||||
|
const SAFE_BASE_SHA = '3333333333333333333333333333333333333333'
|
||||||
|
const WORKFLOW_RUN_HEAD_COMMIT_SHA = '4444444444444444444444444444444444444444'
|
||||||
|
const BASE_QUALIFIED_REPO = 'some-owner/some-repo'
|
||||||
|
const FORK_QUALIFIED_REPO = 'another-repo/fork'
|
||||||
|
|
||||||
|
function setContext(eventName: string, payload: object): void {
|
||||||
|
;(github.context as {eventName: string}).eventName = eventName
|
||||||
|
;(github.context as {payload: object}).payload = payload
|
||||||
|
}
|
||||||
|
|
||||||
|
function forkPullRequestTargetPayload(): object {
|
||||||
|
return {
|
||||||
|
repository: {id: BASE_REPO_ID},
|
||||||
|
pull_request: {
|
||||||
|
head: {
|
||||||
|
sha: PR_HEAD_SHA,
|
||||||
|
repo: {id: FORK_REPO_ID, full_name: FORK_QUALIFIED_REPO}
|
||||||
|
},
|
||||||
|
merge_commit_sha: PR_MERGE_SHA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sameRepoPullRequestTargetPayload(): object {
|
||||||
|
return {
|
||||||
|
repository: {id: BASE_REPO_ID},
|
||||||
|
pull_request: {
|
||||||
|
head: {
|
||||||
|
sha: PR_HEAD_SHA,
|
||||||
|
repo: {id: BASE_REPO_ID, full_name: BASE_QUALIFIED_REPO}
|
||||||
|
},
|
||||||
|
merge_commit_sha: PR_MERGE_SHA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function forkWorkflowRunPayload(): object {
|
||||||
|
return {
|
||||||
|
repository: {id: BASE_REPO_ID},
|
||||||
|
workflow_run: {
|
||||||
|
event: 'pull_request',
|
||||||
|
head_commit: {id: WORKFLOW_RUN_HEAD_COMMIT_SHA},
|
||||||
|
head_repository: {id: FORK_REPO_ID, full_name: FORK_QUALIFIED_REPO}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('unsafe-pr-checkout-helper', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
jest.spyOn(github.context, 'repo', 'get').mockReturnValue({
|
||||||
|
owner: 'some-owner',
|
||||||
|
repo: 'some-repo'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
;(github.context as {eventName: string}).eventName = originalEventName
|
||||||
|
;(github.context as {payload: object}).payload = originalPayload
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
;(github.context as {eventName: string}).eventName =
|
||||||
|
originalContext.eventName
|
||||||
|
;(github.context as {payload: object}).payload = originalContext.payload
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows pull_request events untouched', () => {
|
||||||
|
setContext('pull_request', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: 'attacker/fork',
|
||||||
|
ref: 'refs/pull/1/merge',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows pull_request_target default checkout (base branch)', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: 'refs/heads/main',
|
||||||
|
commit: SAFE_BASE_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows same-repo pull_request_target checkout of PR head', () => {
|
||||||
|
setContext('pull_request_target', sameRepoPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: PR_HEAD_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target fork PR head SHA checkout', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: PR_HEAD_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow(/Refusing to check out fork pull request code/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target fork PR merge_commit_sha checkout', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: PR_MERGE_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow(/allow-unsafe-pr-checkout/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target fork PR ref pattern (head)', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: 'refs/pull/42/head',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target fork PR ref pattern (merge)', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: 'refs/pull/42/merge',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target when repository points at the fork', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: FORK_QUALIFIED_REPO,
|
||||||
|
ref: 'refs/heads/main',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows pull_request_target checkout of an unrelated third-party repo', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: 'some-other/unrelated',
|
||||||
|
ref: 'refs/heads/main',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target ignoring repository case differences', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: FORK_QUALIFIED_REPO.toUpperCase(),
|
||||||
|
ref: '',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses pull_request_target ignoring commit SHA case differences', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: PR_HEAD_SHA.toUpperCase(),
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows pull_request_target fork PR checkout when opted in', () => {
|
||||||
|
setContext('pull_request_target', forkPullRequestTargetPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: 'refs/pull/42/merge',
|
||||||
|
commit: '',
|
||||||
|
allowUnsafePrCheckout: true
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses workflow_run fork PR head_commit.id checkout', () => {
|
||||||
|
setContext('workflow_run', forkWorkflowRunPayload())
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: WORKFLOW_RUN_HEAD_COMMIT_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('refuses workflow_run with pull_request_target underlying event', () => {
|
||||||
|
const payload = forkWorkflowRunPayload() as {
|
||||||
|
workflow_run: {event: string}
|
||||||
|
}
|
||||||
|
payload.workflow_run.event = 'pull_request_target'
|
||||||
|
setContext('workflow_run', payload)
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: WORKFLOW_RUN_HEAD_COMMIT_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows workflow_run same-repo PR (head_repository.id matches base)', () => {
|
||||||
|
const payload = forkWorkflowRunPayload() as {
|
||||||
|
workflow_run: {head_repository: {id: number}}
|
||||||
|
}
|
||||||
|
payload.workflow_run.head_repository.id = BASE_REPO_ID
|
||||||
|
setContext('workflow_run', payload)
|
||||||
|
expect(() =>
|
||||||
|
assertSafePrCheckout({
|
||||||
|
qualifiedRepository: BASE_QUALIFIED_REPO,
|
||||||
|
ref: '',
|
||||||
|
commit: WORKFLOW_RUN_HEAD_COMMIT_SHA,
|
||||||
|
allowUnsafePrCheckout: false
|
||||||
|
})
|
||||||
|
).not.toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
11
action.yml
11
action.yml
@@ -98,12 +98,21 @@ inputs:
|
|||||||
github-server-url:
|
github-server-url:
|
||||||
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
|
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
|
||||||
required: false
|
required: false
|
||||||
|
allow-unsafe-pr-checkout:
|
||||||
|
description: >
|
||||||
|
Required to check out fork pull request code from a workflow triggered by
|
||||||
|
`pull_request_target` or `workflow_run`. These workflows run with the
|
||||||
|
base repository's GITHUB_TOKEN, secrets, default-branch cache scope, and
|
||||||
|
runner access; fetching and executing a fork's code in that trusted
|
||||||
|
context commonly leads to "pwn request" vulnerabilities. Set to `true`
|
||||||
|
only after reviewing the risks at https://gh.io/securely-using-pull_request_target.
|
||||||
|
default: false
|
||||||
outputs:
|
outputs:
|
||||||
ref:
|
ref:
|
||||||
description: 'The branch, tag or SHA that was checked out'
|
description: 'The branch, tag or SHA that was checked out'
|
||||||
commit:
|
commit:
|
||||||
description: 'The commit SHA that was checked out'
|
description: 'The commit SHA that was checked out'
|
||||||
runs:
|
runs:
|
||||||
using: node20
|
using: node24
|
||||||
main: dist/index.js
|
main: dist/index.js
|
||||||
post: dist/index.js
|
post: dist/index.js
|
||||||
|
|||||||
361
dist/index.js
vendored
361
dist/index.js
vendored
@@ -411,8 +411,50 @@ class GitAuthHelper {
|
|||||||
}
|
}
|
||||||
removeToken() {
|
removeToken() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
// HTTP extra header
|
// Remove HTTP extra header from local git config and submodule configs
|
||||||
yield this.removeGitConfig(this.tokenConfigKey);
|
yield this.removeGitConfig(this.tokenConfigKey);
|
||||||
|
//
|
||||||
|
// Cleanup actions/checkout@v6 style credentials
|
||||||
|
//
|
||||||
|
const skipV6Cleanup = process.env['ACTIONS_CHECKOUT_SKIP_V6_CLEANUP'];
|
||||||
|
if (skipV6Cleanup === '1' || (skipV6Cleanup === null || skipV6Cleanup === void 0 ? void 0 : skipV6Cleanup.toLowerCase()) === 'true') {
|
||||||
|
core.debug('Skipping v6 style cleanup due to ACTIONS_CHECKOUT_SKIP_V6_CLEANUP');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Collect credentials config paths that need to be removed
|
||||||
|
const credentialsPaths = new Set();
|
||||||
|
// Remove includeIf entries that point to git-credentials-*.config files
|
||||||
|
const mainCredentialsPaths = yield this.removeIncludeIfCredentials();
|
||||||
|
mainCredentialsPaths.forEach(path => credentialsPaths.add(path));
|
||||||
|
// Remove submodule includeIf entries that point to git-credentials-*.config files
|
||||||
|
try {
|
||||||
|
const submoduleConfigPaths = yield this.git.getSubmoduleConfigPaths(true);
|
||||||
|
for (const configPath of submoduleConfigPaths) {
|
||||||
|
const submoduleCredentialsPaths = yield this.removeIncludeIfCredentials(configPath);
|
||||||
|
submoduleCredentialsPaths.forEach(path => credentialsPaths.add(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.debug(`Unable to get submodule config paths: ${err}`);
|
||||||
|
}
|
||||||
|
// Remove credentials config files
|
||||||
|
for (const credentialsPath of credentialsPaths) {
|
||||||
|
// Only remove credentials config files if they are under RUNNER_TEMP
|
||||||
|
const runnerTemp = process.env['RUNNER_TEMP'];
|
||||||
|
if (runnerTemp && credentialsPath.startsWith(runnerTemp)) {
|
||||||
|
try {
|
||||||
|
yield io.rmRF(credentialsPath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.debug(`Failed to remove credentials config '${credentialsPath}': ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.debug(`Failed to cleanup v6 style credentials: ${err}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
removeGitConfig(configKey_1) {
|
removeGitConfig(configKey_1) {
|
||||||
@@ -430,6 +472,49 @@ class GitAuthHelper {
|
|||||||
`sh -c "git config --local --name-only --get-regexp '${pattern}' && git config --local --unset-all '${configKey}' || :"`, true);
|
`sh -c "git config --local --name-only --get-regexp '${pattern}' && git config --local --unset-all '${configKey}' || :"`, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Removes includeIf entries that point to git-credentials-*.config files.
|
||||||
|
* This handles cleanup of credentials configured by newer versions of the action.
|
||||||
|
* @param configPath Optional path to a specific git config file to operate on
|
||||||
|
* @returns Array of unique credentials config file paths that were found and removed
|
||||||
|
*/
|
||||||
|
removeIncludeIfCredentials(configPath) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const credentialsPaths = new Set();
|
||||||
|
try {
|
||||||
|
// Get all includeIf.gitdir keys
|
||||||
|
const keys = yield this.git.tryGetConfigKeys('^includeIf\\.gitdir:', false, // globalConfig?
|
||||||
|
configPath);
|
||||||
|
for (const key of keys) {
|
||||||
|
// Get all values for this key
|
||||||
|
const values = yield this.git.tryGetConfigValues(key, false, // globalConfig?
|
||||||
|
configPath);
|
||||||
|
if (values.length > 0) {
|
||||||
|
// Remove only values that match git-credentials-<uuid>.config pattern
|
||||||
|
for (const value of values) {
|
||||||
|
if (this.testCredentialsConfigPath(value)) {
|
||||||
|
credentialsPaths.add(value);
|
||||||
|
yield this.git.tryConfigUnsetValue(key, value, false, configPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// Ignore errors - this is cleanup code
|
||||||
|
core.debug(`Error during includeIf cleanup${configPath ? ` for ${configPath}` : ''}: ${err}`);
|
||||||
|
}
|
||||||
|
return Array.from(credentialsPaths);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Tests if a path matches the git-credentials-*.config pattern used by newer versions.
|
||||||
|
* @param path The path to test
|
||||||
|
* @returns True if the path matches the credentials config pattern
|
||||||
|
*/
|
||||||
|
testCredentialsConfigPath(path) {
|
||||||
|
return /git-credentials-[0-9a-f-]+\.config$/i.test(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -706,6 +791,16 @@ class GitCommandManager {
|
|||||||
throw new Error('Unexpected output when retrieving default branch');
|
throw new Error('Unexpected output when retrieving default branch');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
getSubmoduleConfigPaths(recursive) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
// Get submodule config file paths.
|
||||||
|
// Use `--show-origin` to get the config file path for each submodule.
|
||||||
|
const output = yield this.submoduleForeach(`git config --local --show-origin --name-only --get-regexp remote.origin.url`, recursive);
|
||||||
|
// Extract config file paths from the output (lines starting with "file:").
|
||||||
|
const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
|
||||||
|
return configPaths;
|
||||||
|
});
|
||||||
|
}
|
||||||
getWorkingDirectory() {
|
getWorkingDirectory() {
|
||||||
return this.workingDirectory;
|
return this.workingDirectory;
|
||||||
}
|
}
|
||||||
@@ -836,6 +931,20 @@ class GitCommandManager {
|
|||||||
return output.exitCode === 0;
|
return output.exitCode === 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
tryConfigUnsetValue(configKey, configValue, globalConfig, configFile) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const args = ['config'];
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local');
|
||||||
|
}
|
||||||
|
args.push('--unset', configKey, configValue);
|
||||||
|
const output = yield this.execGit(args, true);
|
||||||
|
return output.exitCode === 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
tryDisableAutomaticGarbageCollection() {
|
tryDisableAutomaticGarbageCollection() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const output = yield this.execGit(['config', '--local', 'gc.auto', '0'], true);
|
const output = yield this.execGit(['config', '--local', 'gc.auto', '0'], true);
|
||||||
@@ -855,6 +964,46 @@ class GitCommandManager {
|
|||||||
return stdout;
|
return stdout;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
tryGetConfigValues(configKey, globalConfig, configFile) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const args = ['config'];
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local');
|
||||||
|
}
|
||||||
|
args.push('--get-all', configKey);
|
||||||
|
const output = yield this.execGit(args, true);
|
||||||
|
if (output.exitCode !== 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return output.stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter(value => value.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tryGetConfigKeys(pattern, globalConfig, configFile) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const args = ['config'];
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local');
|
||||||
|
}
|
||||||
|
args.push('--name-only', '--get-regexp', pattern);
|
||||||
|
const output = yield this.execGit(args, true);
|
||||||
|
if (output.exitCode !== 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return output.stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter(key => key.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
tryReset() {
|
tryReset() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const output = yield this.execGit(['reset', '--hard', 'HEAD'], true);
|
const output = yield this.execGit(['reset', '--hard', 'HEAD'], true);
|
||||||
@@ -1710,6 +1859,7 @@ const core = __importStar(__nccwpck_require__(2186));
|
|||||||
const fsHelper = __importStar(__nccwpck_require__(7219));
|
const fsHelper = __importStar(__nccwpck_require__(7219));
|
||||||
const github = __importStar(__nccwpck_require__(5438));
|
const github = __importStar(__nccwpck_require__(5438));
|
||||||
const path = __importStar(__nccwpck_require__(1017));
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
|
const unsafePrCheckoutHelper = __importStar(__nccwpck_require__(843));
|
||||||
const workflowContextHelper = __importStar(__nccwpck_require__(9568));
|
const workflowContextHelper = __importStar(__nccwpck_require__(9568));
|
||||||
function getInputs() {
|
function getInputs() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
@@ -1831,6 +1981,17 @@ function getInputs() {
|
|||||||
// Determine the GitHub URL that the repository is being hosted from
|
// Determine the GitHub URL that the repository is being hosted from
|
||||||
result.githubServerUrl = core.getInput('github-server-url');
|
result.githubServerUrl = core.getInput('github-server-url');
|
||||||
core.debug(`GitHub Host URL = ${result.githubServerUrl}`);
|
core.debug(`GitHub Host URL = ${result.githubServerUrl}`);
|
||||||
|
// Allow unsafe PR checkout (opt-in for pull_request_target / workflow_run fork PRs)
|
||||||
|
result.allowUnsafePrCheckout =
|
||||||
|
(core.getInput('allow-unsafe-pr-checkout') || 'false').toUpperCase() ===
|
||||||
|
'TRUE';
|
||||||
|
core.debug(`allow unsafe PR checkout = ${result.allowUnsafePrCheckout}`);
|
||||||
|
unsafePrCheckoutHelper.assertSafePrCheckout({
|
||||||
|
qualifiedRepository,
|
||||||
|
ref: result.ref,
|
||||||
|
commit: result.commit,
|
||||||
|
allowUnsafePrCheckout: result.allowUnsafePrCheckout
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1971,6 +2132,7 @@ exports.getRefSpecForAllHistory = getRefSpecForAllHistory;
|
|||||||
exports.getRefSpec = getRefSpec;
|
exports.getRefSpec = getRefSpec;
|
||||||
exports.testRef = testRef;
|
exports.testRef = testRef;
|
||||||
exports.checkCommitInfo = checkCommitInfo;
|
exports.checkCommitInfo = checkCommitInfo;
|
||||||
|
exports.fromPayload = fromPayload;
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const github = __importStar(__nccwpck_require__(5438));
|
const github = __importStar(__nccwpck_require__(5438));
|
||||||
const url_helper_1 = __nccwpck_require__(9437);
|
const url_helper_1 = __nccwpck_require__(9437);
|
||||||
@@ -2403,6 +2565,105 @@ if (!exports.IsPost) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 843:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.assertSafePrCheckout = assertSafePrCheckout;
|
||||||
|
const github = __importStar(__nccwpck_require__(5438));
|
||||||
|
const ref_helper_1 = __nccwpck_require__(8601);
|
||||||
|
const PR_REF_PATTERN = /^refs\/pull\/[0-9]+\/(?:head|merge)$/;
|
||||||
|
function assertSafePrCheckout(input) {
|
||||||
|
if (input.allowUnsafePrCheckout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const eventName = github.context.eventName;
|
||||||
|
if (eventName !== 'pull_request_target' && eventName !== 'workflow_run') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const baseRepoId = (0, ref_helper_1.fromPayload)('repository.id');
|
||||||
|
if (typeof baseRepoId !== 'number') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let prHeadRepoId;
|
||||||
|
let prHeadRepoFullName;
|
||||||
|
const prShas = [];
|
||||||
|
if (eventName === 'pull_request_target') {
|
||||||
|
prHeadRepoId = (0, ref_helper_1.fromPayload)('pull_request.head.repo.id');
|
||||||
|
prHeadRepoFullName = (0, ref_helper_1.fromPayload)('pull_request.head.repo.full_name');
|
||||||
|
pushIfSha(prShas, (0, ref_helper_1.fromPayload)('pull_request.head.sha'));
|
||||||
|
pushIfSha(prShas, (0, ref_helper_1.fromPayload)('pull_request.merge_commit_sha'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const wrEvent = (0, ref_helper_1.fromPayload)('workflow_run.event');
|
||||||
|
if (typeof wrEvent !== 'string' || !wrEvent.startsWith('pull_request')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prHeadRepoId = (0, ref_helper_1.fromPayload)('workflow_run.head_repository.id');
|
||||||
|
prHeadRepoFullName = (0, ref_helper_1.fromPayload)('workflow_run.head_repository.full_name');
|
||||||
|
pushIfSha(prShas, (0, ref_helper_1.fromPayload)('workflow_run.head_commit.id'));
|
||||||
|
// For `pull_request_target`-triggered workflow_run, `head_sha` is the base
|
||||||
|
// default branch SHA (not the PR head)
|
||||||
|
if (wrEvent !== 'pull_request_target') {
|
||||||
|
pushIfSha(prShas, (0, ref_helper_1.fromPayload)('workflow_run.head_sha'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// (A) Fork PR?
|
||||||
|
if (typeof prHeadRepoId !== 'number' || prHeadRepoId === baseRepoId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// (B) We cannot check for all fork PR refs so check to see
|
||||||
|
// if the resolved input points to the fork PR sha we have in the payload
|
||||||
|
const repositoryMatchesPrHead = typeof prHeadRepoFullName === 'string' &&
|
||||||
|
input.qualifiedRepository.toLowerCase() === prHeadRepoFullName.toLowerCase();
|
||||||
|
const refMatchesPullPattern = PR_REF_PATTERN.test(input.ref);
|
||||||
|
const commitMatchesPrHeadSha = !!input.commit && prShas.includes(input.commit.toLowerCase());
|
||||||
|
if (!repositoryMatchesPrHead &&
|
||||||
|
!refMatchesPullPattern &&
|
||||||
|
!commitMatchesPrHeadSha) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error(`Refusing to check out fork pull request code from a '${eventName}' workflow. ` +
|
||||||
|
`This workflow runs with the base repository's GITHUB_TOKEN, secrets, default-branch ` +
|
||||||
|
`cache scope, and runner access. Fetching and executing a fork's code in that trusted ` +
|
||||||
|
`context commonly leads to "pwn request" vulnerabilities. To opt in, review the risks ` +
|
||||||
|
`at https://gh.io/securely-using-pull_request_target and set 'allow-unsafe-pr-checkout: true' ` +
|
||||||
|
`on the actions/checkout step.`);
|
||||||
|
}
|
||||||
|
function pushIfSha(target, value) {
|
||||||
|
if (typeof value === 'string' && value.length > 0) {
|
||||||
|
target.push(value.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 9437:
|
/***/ 9437:
|
||||||
@@ -7802,7 +8063,7 @@ module.exports = __toCommonJS(dist_src_exports);
|
|||||||
var import_universal_user_agent = __nccwpck_require__(5030);
|
var import_universal_user_agent = __nccwpck_require__(5030);
|
||||||
|
|
||||||
// pkg/dist-src/version.js
|
// pkg/dist-src/version.js
|
||||||
var VERSION = "9.0.5";
|
var VERSION = "9.0.6";
|
||||||
|
|
||||||
// pkg/dist-src/defaults.js
|
// pkg/dist-src/defaults.js
|
||||||
var userAgent = `octokit-endpoint.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}`;
|
var userAgent = `octokit-endpoint.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}`;
|
||||||
@@ -7907,9 +8168,9 @@ function addQueryParameters(url, parameters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pkg/dist-src/util/extract-url-variable-names.js
|
// pkg/dist-src/util/extract-url-variable-names.js
|
||||||
var urlVariableRegex = /\{[^}]+\}/g;
|
var urlVariableRegex = /\{[^{}}]+\}/g;
|
||||||
function removeNonChars(variableName) {
|
function removeNonChars(variableName) {
|
||||||
return variableName.replace(/^\W+|\W+$/g, "").split(/,/);
|
return variableName.replace(/(?:^\W+)|(?:(?<!\W)\W+$)/g, "").split(/,/);
|
||||||
}
|
}
|
||||||
function extractUrlVariableNames(url) {
|
function extractUrlVariableNames(url) {
|
||||||
const matches = url.match(urlVariableRegex);
|
const matches = url.match(urlVariableRegex);
|
||||||
@@ -8095,7 +8356,7 @@ function parse(options) {
|
|||||||
}
|
}
|
||||||
if (url.endsWith("/graphql")) {
|
if (url.endsWith("/graphql")) {
|
||||||
if (options.mediaType.previews?.length) {
|
if (options.mediaType.previews?.length) {
|
||||||
const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || [];
|
const previewsFromAcceptHeader = headers.accept.match(/(?<![\w-])[\w-]+(?=-preview)/g) || [];
|
||||||
headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map((preview) => {
|
headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map((preview) => {
|
||||||
const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json";
|
const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json";
|
||||||
return `application/vnd.github.${preview}-preview${format}`;
|
return `application/vnd.github.${preview}-preview${format}`;
|
||||||
@@ -8344,7 +8605,7 @@ __export(dist_src_exports, {
|
|||||||
module.exports = __toCommonJS(dist_src_exports);
|
module.exports = __toCommonJS(dist_src_exports);
|
||||||
|
|
||||||
// pkg/dist-src/version.js
|
// pkg/dist-src/version.js
|
||||||
var VERSION = "9.2.1";
|
var VERSION = "9.2.2";
|
||||||
|
|
||||||
// pkg/dist-src/normalize-paginated-list-response.js
|
// pkg/dist-src/normalize-paginated-list-response.js
|
||||||
function normalizePaginatedListResponse(response) {
|
function normalizePaginatedListResponse(response) {
|
||||||
@@ -8392,7 +8653,7 @@ function iterator(octokit, route, parameters) {
|
|||||||
const response = await requestMethod({ method, url, headers });
|
const response = await requestMethod({ method, url, headers });
|
||||||
const normalizedResponse = normalizePaginatedListResponse(response);
|
const normalizedResponse = normalizePaginatedListResponse(response);
|
||||||
url = ((normalizedResponse.headers.link || "").match(
|
url = ((normalizedResponse.headers.link || "").match(
|
||||||
/<([^>]+)>;\s*rel="next"/
|
/<([^<>]+)>;\s*rel="next"/
|
||||||
) || [])[1];
|
) || [])[1];
|
||||||
return { value: normalizedResponse };
|
return { value: normalizedResponse };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -10944,7 +11205,7 @@ var RequestError = class extends Error {
|
|||||||
if (options.request.headers.authorization) {
|
if (options.request.headers.authorization) {
|
||||||
requestCopy.headers = Object.assign({}, options.request.headers, {
|
requestCopy.headers = Object.assign({}, options.request.headers, {
|
||||||
authorization: options.request.headers.authorization.replace(
|
authorization: options.request.headers.authorization.replace(
|
||||||
/ .*$/,
|
/(?<! ) .*$/,
|
||||||
" [REDACTED]"
|
" [REDACTED]"
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@@ -11012,7 +11273,7 @@ var import_endpoint = __nccwpck_require__(9440);
|
|||||||
var import_universal_user_agent = __nccwpck_require__(5030);
|
var import_universal_user_agent = __nccwpck_require__(5030);
|
||||||
|
|
||||||
// pkg/dist-src/version.js
|
// pkg/dist-src/version.js
|
||||||
var VERSION = "8.4.0";
|
var VERSION = "8.4.1";
|
||||||
|
|
||||||
// pkg/dist-src/is-plain-object.js
|
// pkg/dist-src/is-plain-object.js
|
||||||
function isPlainObject(value) {
|
function isPlainObject(value) {
|
||||||
@@ -11071,7 +11332,7 @@ function fetchWrapper(requestOptions) {
|
|||||||
headers[keyAndValue[0]] = keyAndValue[1];
|
headers[keyAndValue[0]] = keyAndValue[1];
|
||||||
}
|
}
|
||||||
if ("deprecation" in headers) {
|
if ("deprecation" in headers) {
|
||||||
const matches = headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/);
|
const matches = headers.link && headers.link.match(/<([^<>]+)>; rel="deprecation"/);
|
||||||
const deprecationLink = matches && matches.pop();
|
const deprecationLink = matches && matches.pop();
|
||||||
log.warn(
|
log.warn(
|
||||||
`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`
|
`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`
|
||||||
@@ -18725,7 +18986,7 @@ module.exports = {
|
|||||||
|
|
||||||
|
|
||||||
const { parseSetCookie } = __nccwpck_require__(4408)
|
const { parseSetCookie } = __nccwpck_require__(4408)
|
||||||
const { stringify, getHeadersList } = __nccwpck_require__(3121)
|
const { stringify } = __nccwpck_require__(3121)
|
||||||
const { webidl } = __nccwpck_require__(1744)
|
const { webidl } = __nccwpck_require__(1744)
|
||||||
const { Headers } = __nccwpck_require__(554)
|
const { Headers } = __nccwpck_require__(554)
|
||||||
|
|
||||||
@@ -18801,14 +19062,13 @@ function getSetCookies (headers) {
|
|||||||
|
|
||||||
webidl.brandCheck(headers, Headers, { strict: false })
|
webidl.brandCheck(headers, Headers, { strict: false })
|
||||||
|
|
||||||
const cookies = getHeadersList(headers).cookies
|
const cookies = headers.getSetCookie()
|
||||||
|
|
||||||
if (!cookies) {
|
if (!cookies) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
// In older versions of undici, cookies is a list of name:value.
|
return cookies.map((pair) => parseSetCookie(pair))
|
||||||
return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19236,14 +19496,15 @@ module.exports = {
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 3121:
|
/***/ 3121:
|
||||||
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
const assert = __nccwpck_require__(9491)
|
/**
|
||||||
const { kHeadersList } = __nccwpck_require__(2785)
|
* @param {string} value
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
function isCTLExcludingHtab (value) {
|
function isCTLExcludingHtab (value) {
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
return false
|
return false
|
||||||
@@ -19504,31 +19765,13 @@ function stringify (cookie) {
|
|||||||
return out.join('; ')
|
return out.join('; ')
|
||||||
}
|
}
|
||||||
|
|
||||||
let kHeadersListNode
|
|
||||||
|
|
||||||
function getHeadersList (headers) {
|
|
||||||
if (headers[kHeadersList]) {
|
|
||||||
return headers[kHeadersList]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!kHeadersListNode) {
|
|
||||||
kHeadersListNode = Object.getOwnPropertySymbols(headers).find(
|
|
||||||
(symbol) => symbol.description === 'headers list'
|
|
||||||
)
|
|
||||||
|
|
||||||
assert(kHeadersListNode, 'Headers cannot be parsed')
|
|
||||||
}
|
|
||||||
|
|
||||||
const headersList = headers[kHeadersListNode]
|
|
||||||
assert(headersList)
|
|
||||||
|
|
||||||
return headersList
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
isCTLExcludingHtab,
|
isCTLExcludingHtab,
|
||||||
stringify,
|
validateCookieName,
|
||||||
getHeadersList
|
validateCookiePath,
|
||||||
|
validateCookieValue,
|
||||||
|
toIMFDate,
|
||||||
|
stringify
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -21457,6 +21700,14 @@ const { isUint8Array, isArrayBuffer } = __nccwpck_require__(9830)
|
|||||||
const { File: UndiciFile } = __nccwpck_require__(8511)
|
const { File: UndiciFile } = __nccwpck_require__(8511)
|
||||||
const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(685)
|
const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(685)
|
||||||
|
|
||||||
|
let random
|
||||||
|
try {
|
||||||
|
const crypto = __nccwpck_require__(6005)
|
||||||
|
random = (max) => crypto.randomInt(0, max)
|
||||||
|
} catch {
|
||||||
|
random = (max) => Math.floor(Math.random(max))
|
||||||
|
}
|
||||||
|
|
||||||
let ReadableStream = globalThis.ReadableStream
|
let ReadableStream = globalThis.ReadableStream
|
||||||
|
|
||||||
/** @type {globalThis['File']} */
|
/** @type {globalThis['File']} */
|
||||||
@@ -21542,7 +21793,7 @@ function extractBody (object, keepalive = false) {
|
|||||||
// Set source to a copy of the bytes held by object.
|
// Set source to a copy of the bytes held by object.
|
||||||
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
|
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
|
||||||
} else if (util.isFormDataLike(object)) {
|
} else if (util.isFormDataLike(object)) {
|
||||||
const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}`
|
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}`
|
||||||
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
|
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
|
||||||
|
|
||||||
/*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
|
/*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
|
||||||
@@ -23524,6 +23775,7 @@ const {
|
|||||||
isValidHeaderName,
|
isValidHeaderName,
|
||||||
isValidHeaderValue
|
isValidHeaderValue
|
||||||
} = __nccwpck_require__(2538)
|
} = __nccwpck_require__(2538)
|
||||||
|
const util = __nccwpck_require__(3837)
|
||||||
const { webidl } = __nccwpck_require__(1744)
|
const { webidl } = __nccwpck_require__(1744)
|
||||||
const assert = __nccwpck_require__(9491)
|
const assert = __nccwpck_require__(9491)
|
||||||
|
|
||||||
@@ -24077,6 +24329,9 @@ Object.defineProperties(Headers.prototype, {
|
|||||||
[Symbol.toStringTag]: {
|
[Symbol.toStringTag]: {
|
||||||
value: 'Headers',
|
value: 'Headers',
|
||||||
configurable: true
|
configurable: true
|
||||||
|
},
|
||||||
|
[util.inspect.custom]: {
|
||||||
|
enumerable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -33253,6 +33508,20 @@ class Pool extends PoolBase {
|
|||||||
? { ...options.interceptors }
|
? { ...options.interceptors }
|
||||||
: undefined
|
: undefined
|
||||||
this[kFactory] = factory
|
this[kFactory] = factory
|
||||||
|
|
||||||
|
this.on('connectionError', (origin, targets, error) => {
|
||||||
|
// If a connection error occurs, we remove the client from the pool,
|
||||||
|
// and emit a connectionError event. They will not be re-used.
|
||||||
|
// Fixes https://github.com/nodejs/undici/issues/3895
|
||||||
|
for (const target of targets) {
|
||||||
|
// Do not use kRemoveClient here, as it will close the client,
|
||||||
|
// but the client cannot be closed in this state.
|
||||||
|
const idx = this[kClients].indexOf(target)
|
||||||
|
if (idx !== -1) {
|
||||||
|
this[kClients].splice(idx, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
[kGetDispatcher] () {
|
[kGetDispatcher] () {
|
||||||
@@ -36408,6 +36677,14 @@ module.exports = require("net");
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 6005:
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
module.exports = require("node:crypto");
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
/***/ 5673:
|
/***/ 5673:
|
||||||
/***/ ((module) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
|||||||
334
package-lock.json
generated
334
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "checkout",
|
"name": "checkout",
|
||||||
"version": "4.2.2",
|
"version": "5.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "checkout",
|
"name": "checkout",
|
||||||
"version": "4.2.2",
|
"version": "5.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^20.12.12",
|
"@types/node": "^24.1.0",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||||
"@typescript-eslint/parser": "^7.9.0",
|
"@typescript-eslint/parser": "^7.9.0",
|
||||||
@@ -129,13 +129,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.24.2",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||||
"integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==",
|
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/highlight": "^7.24.2",
|
"@babel/helper-validator-identifier": "^7.27.1",
|
||||||
"picocolors": "^1.0.0"
|
"js-tokens": "^4.0.0",
|
||||||
|
"picocolors": "^1.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -310,19 +312,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.24.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
"integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
|
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-identifier": {
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
"version": "7.22.20",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
|
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
@@ -337,110 +341,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.24.4",
|
"version": "7.28.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz",
|
||||||
"integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==",
|
"integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.24.0",
|
"@babel/template": "^7.27.2",
|
||||||
"@babel/traverse": "^7.24.1",
|
"@babel/types": "^7.28.2"
|
||||||
"@babel/types": "^7.24.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/highlight": {
|
|
||||||
"version": "7.24.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz",
|
|
||||||
"integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/helper-validator-identifier": "^7.22.20",
|
|
||||||
"chalk": "^2.4.2",
|
|
||||||
"js-tokens": "^4.0.0",
|
|
||||||
"picocolors": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/ansi-styles": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/color-convert": {
|
|
||||||
"version": "1.9.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
|
||||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "1.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/color-name": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/has-flag": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.24.4",
|
"version": "7.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
|
||||||
"integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==",
|
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.28.0"
|
||||||
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
},
|
},
|
||||||
@@ -626,26 +548,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.24.4",
|
"version": "7.28.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz",
|
||||||
"integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==",
|
"integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"license": "MIT",
|
||||||
"regenerator-runtime": "^0.14.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.24.0",
|
"version": "7.27.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
||||||
"integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==",
|
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.23.5",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/parser": "^7.24.0",
|
"@babel/parser": "^7.27.2",
|
||||||
"@babel/types": "^7.24.0"
|
"@babel/types": "^7.27.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -682,14 +603,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.24.0",
|
"version": "7.28.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
|
||||||
"integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
|
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.23.4",
|
"@babel/helper-string-parser": "^7.27.1",
|
||||||
"@babel/helper-validator-identifier": "^7.22.20",
|
"@babel/helper-validator-identifier": "^7.27.1"
|
||||||
"to-fast-properties": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -749,10 +670,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -808,10 +730,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
|
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -1343,9 +1266,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/endpoint": {
|
"node_modules/@octokit/endpoint": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||||
"integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==",
|
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/types": "^13.1.0",
|
"@octokit/types": "^13.1.0",
|
||||||
"universal-user-agent": "^6.0.0"
|
"universal-user-agent": "^6.0.0"
|
||||||
@@ -1373,9 +1297,10 @@
|
|||||||
"integrity": "sha512-pGUdSP+eEPfZiQHNkZI0U01HLipxncisdJQB4G//OAmfeO8sqTQ9KRa0KF03TUPCziNsoXUrTg4B2Q1EX++T0Q=="
|
"integrity": "sha512-pGUdSP+eEPfZiQHNkZI0U01HLipxncisdJQB4G//OAmfeO8sqTQ9KRa0KF03TUPCziNsoXUrTg4B2Q1EX++T0Q=="
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/plugin-paginate-rest": {
|
"node_modules/@octokit/plugin-paginate-rest": {
|
||||||
"version": "9.2.1",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
|
||||||
"integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
|
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/types": "^12.6.0"
|
"@octokit/types": "^12.6.0"
|
||||||
},
|
},
|
||||||
@@ -1427,12 +1352,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/request": {
|
"node_modules/@octokit/request": {
|
||||||
"version": "8.4.0",
|
"version": "8.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||||
"integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==",
|
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/endpoint": "^9.0.1",
|
"@octokit/endpoint": "^9.0.6",
|
||||||
"@octokit/request-error": "^5.1.0",
|
"@octokit/request-error": "^5.1.1",
|
||||||
"@octokit/types": "^13.1.0",
|
"@octokit/types": "^13.1.0",
|
||||||
"universal-user-agent": "^6.0.0"
|
"universal-user-agent": "^6.0.0"
|
||||||
},
|
},
|
||||||
@@ -1441,9 +1367,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/request-error": {
|
"node_modules/@octokit/request-error": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||||
"integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==",
|
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/types": "^13.1.0",
|
"@octokit/types": "^13.1.0",
|
||||||
"deprecation": "^2.0.0",
|
"deprecation": "^2.0.0",
|
||||||
@@ -1588,12 +1515,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.12.12",
|
"version": "24.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
|
||||||
"integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
|
"integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/stack-utils": {
|
"node_modules/@types/stack-utils": {
|
||||||
@@ -2238,10 +2165,11 @@
|
|||||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -2502,10 +2430,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"path-key": "^3.1.0",
|
"path-key": "^3.1.0",
|
||||||
"shebang-command": "^2.0.0",
|
"shebang-command": "^2.0.0",
|
||||||
@@ -3175,10 +3104,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -3273,10 +3203,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
|
"node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -3371,10 +3302,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint/node_modules/brace-expansion": {
|
"node_modules/eslint/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -3836,10 +3768,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/brace-expansion": {
|
"node_modules/glob/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -4635,10 +4568,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jake/node_modules/brace-expansion": {
|
"node_modules/jake/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -5248,7 +5182,8 @@
|
|||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
@@ -5528,12 +5463,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/micromatch": {
|
"node_modules/micromatch": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"braces": "^3.0.2",
|
"braces": "^3.0.3",
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -5869,10 +5805,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
@@ -6115,12 +6052,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/regenerator-runtime": {
|
|
||||||
"version": "0.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/regexp.prototype.flags": {
|
"node_modules/regexp.prototype.flags": {
|
||||||
"version": "1.5.2",
|
"version": "1.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
||||||
@@ -6622,10 +6553,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/brace-expansion": {
|
"node_modules/test-exclude/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -6655,15 +6587,6 @@
|
|||||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/to-fast-properties": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
@@ -6930,9 +6853,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.28.4",
|
"version": "5.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||||
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/busboy": "^2.0.0"
|
"@fastify/busboy": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -6941,9 +6865,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/universal-user-agent": {
|
"node_modules/universal-user-agent": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "checkout",
|
"name": "checkout",
|
||||||
"version": "4.2.2",
|
"version": "5.0.0",
|
||||||
"description": "checkout action",
|
"description": "checkout action",
|
||||||
"main": "lib/main.js",
|
"main": "lib/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^20.12.12",
|
"@types/node": "^24.1.0",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||||
"@typescript-eslint/parser": "^7.9.0",
|
"@typescript-eslint/parser": "^7.9.0",
|
||||||
|
|||||||
@@ -346,8 +346,58 @@ class GitAuthHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async removeToken(): Promise<void> {
|
private async removeToken(): Promise<void> {
|
||||||
// HTTP extra header
|
// Remove HTTP extra header from local git config and submodule configs
|
||||||
await this.removeGitConfig(this.tokenConfigKey)
|
await this.removeGitConfig(this.tokenConfigKey)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cleanup actions/checkout@v6 style credentials
|
||||||
|
//
|
||||||
|
const skipV6Cleanup = process.env['ACTIONS_CHECKOUT_SKIP_V6_CLEANUP']
|
||||||
|
if (skipV6Cleanup === '1' || skipV6Cleanup?.toLowerCase() === 'true') {
|
||||||
|
core.debug(
|
||||||
|
'Skipping v6 style cleanup due to ACTIONS_CHECKOUT_SKIP_V6_CLEANUP'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Collect credentials config paths that need to be removed
|
||||||
|
const credentialsPaths = new Set<string>()
|
||||||
|
|
||||||
|
// Remove includeIf entries that point to git-credentials-*.config files
|
||||||
|
const mainCredentialsPaths = await this.removeIncludeIfCredentials()
|
||||||
|
mainCredentialsPaths.forEach(path => credentialsPaths.add(path))
|
||||||
|
|
||||||
|
// Remove submodule includeIf entries that point to git-credentials-*.config files
|
||||||
|
try {
|
||||||
|
const submoduleConfigPaths =
|
||||||
|
await this.git.getSubmoduleConfigPaths(true)
|
||||||
|
for (const configPath of submoduleConfigPaths) {
|
||||||
|
const submoduleCredentialsPaths =
|
||||||
|
await this.removeIncludeIfCredentials(configPath)
|
||||||
|
submoduleCredentialsPaths.forEach(path => credentialsPaths.add(path))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
core.debug(`Unable to get submodule config paths: ${err}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove credentials config files
|
||||||
|
for (const credentialsPath of credentialsPaths) {
|
||||||
|
// Only remove credentials config files if they are under RUNNER_TEMP
|
||||||
|
const runnerTemp = process.env['RUNNER_TEMP']
|
||||||
|
if (runnerTemp && credentialsPath.startsWith(runnerTemp)) {
|
||||||
|
try {
|
||||||
|
await io.rmRF(credentialsPath)
|
||||||
|
} catch (err) {
|
||||||
|
core.debug(
|
||||||
|
`Failed to remove credentials config '${credentialsPath}': ${err}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
core.debug(`Failed to cleanup v6 style credentials: ${err}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async removeGitConfig(
|
private async removeGitConfig(
|
||||||
@@ -371,4 +421,59 @@ class GitAuthHelper {
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes includeIf entries that point to git-credentials-*.config files.
|
||||||
|
* This handles cleanup of credentials configured by newer versions of the action.
|
||||||
|
* @param configPath Optional path to a specific git config file to operate on
|
||||||
|
* @returns Array of unique credentials config file paths that were found and removed
|
||||||
|
*/
|
||||||
|
private async removeIncludeIfCredentials(
|
||||||
|
configPath?: string
|
||||||
|
): Promise<string[]> {
|
||||||
|
const credentialsPaths = new Set<string>()
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get all includeIf.gitdir keys
|
||||||
|
const keys = await this.git.tryGetConfigKeys(
|
||||||
|
'^includeIf\\.gitdir:',
|
||||||
|
false, // globalConfig?
|
||||||
|
configPath
|
||||||
|
)
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
// Get all values for this key
|
||||||
|
const values = await this.git.tryGetConfigValues(
|
||||||
|
key,
|
||||||
|
false, // globalConfig?
|
||||||
|
configPath
|
||||||
|
)
|
||||||
|
if (values.length > 0) {
|
||||||
|
// Remove only values that match git-credentials-<uuid>.config pattern
|
||||||
|
for (const value of values) {
|
||||||
|
if (this.testCredentialsConfigPath(value)) {
|
||||||
|
credentialsPaths.add(value)
|
||||||
|
await this.git.tryConfigUnsetValue(key, value, false, configPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Ignore errors - this is cleanup code
|
||||||
|
core.debug(
|
||||||
|
`Error during includeIf cleanup${configPath ? ` for ${configPath}` : ''}: ${err}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(credentialsPaths)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a path matches the git-credentials-*.config pattern used by newer versions.
|
||||||
|
* @param path The path to test
|
||||||
|
* @returns True if the path matches the credentials config pattern
|
||||||
|
*/
|
||||||
|
private testCredentialsConfigPath(path: string): boolean {
|
||||||
|
return /git-credentials-[0-9a-f-]+\.config$/i.test(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export interface IGitCommandManager {
|
|||||||
}
|
}
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
getDefaultBranch(repositoryUrl: string): Promise<string>
|
getDefaultBranch(repositoryUrl: string): Promise<string>
|
||||||
|
getSubmoduleConfigPaths(recursive: boolean): Promise<string[]>
|
||||||
getWorkingDirectory(): string
|
getWorkingDirectory(): string
|
||||||
init(): Promise<void>
|
init(): Promise<void>
|
||||||
isDetached(): Promise<boolean>
|
isDetached(): Promise<boolean>
|
||||||
@@ -59,8 +60,24 @@ export interface IGitCommandManager {
|
|||||||
tagExists(pattern: string): Promise<boolean>
|
tagExists(pattern: string): Promise<boolean>
|
||||||
tryClean(): Promise<boolean>
|
tryClean(): Promise<boolean>
|
||||||
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
|
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||||
|
tryConfigUnsetValue(
|
||||||
|
configKey: string,
|
||||||
|
configValue: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<boolean>
|
||||||
tryDisableAutomaticGarbageCollection(): Promise<boolean>
|
tryDisableAutomaticGarbageCollection(): Promise<boolean>
|
||||||
tryGetFetchUrl(): Promise<string>
|
tryGetFetchUrl(): Promise<string>
|
||||||
|
tryGetConfigValues(
|
||||||
|
configKey: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<string[]>
|
||||||
|
tryGetConfigKeys(
|
||||||
|
pattern: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<string[]>
|
||||||
tryReset(): Promise<boolean>
|
tryReset(): Promise<boolean>
|
||||||
version(): Promise<GitVersion>
|
version(): Promise<GitVersion>
|
||||||
}
|
}
|
||||||
@@ -323,6 +340,21 @@ class GitCommandManager {
|
|||||||
throw new Error('Unexpected output when retrieving default branch')
|
throw new Error('Unexpected output when retrieving default branch')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSubmoduleConfigPaths(recursive: boolean): Promise<string[]> {
|
||||||
|
// Get submodule config file paths.
|
||||||
|
// Use `--show-origin` to get the config file path for each submodule.
|
||||||
|
const output = await this.submoduleForeach(
|
||||||
|
`git config --local --show-origin --name-only --get-regexp remote.origin.url`,
|
||||||
|
recursive
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extract config file paths from the output (lines starting with "file:").
|
||||||
|
const configPaths =
|
||||||
|
output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || []
|
||||||
|
|
||||||
|
return configPaths
|
||||||
|
}
|
||||||
|
|
||||||
getWorkingDirectory(): string {
|
getWorkingDirectory(): string {
|
||||||
return this.workingDirectory
|
return this.workingDirectory
|
||||||
}
|
}
|
||||||
@@ -455,6 +487,24 @@ class GitCommandManager {
|
|||||||
return output.exitCode === 0
|
return output.exitCode === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tryConfigUnsetValue(
|
||||||
|
configKey: string,
|
||||||
|
configValue: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<boolean> {
|
||||||
|
const args = ['config']
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile)
|
||||||
|
} else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local')
|
||||||
|
}
|
||||||
|
args.push('--unset', configKey, configValue)
|
||||||
|
|
||||||
|
const output = await this.execGit(args, true)
|
||||||
|
return output.exitCode === 0
|
||||||
|
}
|
||||||
|
|
||||||
async tryDisableAutomaticGarbageCollection(): Promise<boolean> {
|
async tryDisableAutomaticGarbageCollection(): Promise<boolean> {
|
||||||
const output = await this.execGit(
|
const output = await this.execGit(
|
||||||
['config', '--local', 'gc.auto', '0'],
|
['config', '--local', 'gc.auto', '0'],
|
||||||
@@ -481,6 +531,56 @@ class GitCommandManager {
|
|||||||
return stdout
|
return stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tryGetConfigValues(
|
||||||
|
configKey: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<string[]> {
|
||||||
|
const args = ['config']
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile)
|
||||||
|
} else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local')
|
||||||
|
}
|
||||||
|
args.push('--get-all', configKey)
|
||||||
|
|
||||||
|
const output = await this.execGit(args, true)
|
||||||
|
|
||||||
|
if (output.exitCode !== 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter(value => value.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
async tryGetConfigKeys(
|
||||||
|
pattern: string,
|
||||||
|
globalConfig?: boolean,
|
||||||
|
configFile?: string
|
||||||
|
): Promise<string[]> {
|
||||||
|
const args = ['config']
|
||||||
|
if (configFile) {
|
||||||
|
args.push('--file', configFile)
|
||||||
|
} else {
|
||||||
|
args.push(globalConfig ? '--global' : '--local')
|
||||||
|
}
|
||||||
|
args.push('--name-only', '--get-regexp', pattern)
|
||||||
|
|
||||||
|
const output = await this.execGit(args, true)
|
||||||
|
|
||||||
|
if (output.exitCode !== 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter(key => key.trim())
|
||||||
|
}
|
||||||
|
|
||||||
async tryReset(): Promise<boolean> {
|
async tryReset(): Promise<boolean> {
|
||||||
const output = await this.execGit(['reset', '--hard', 'HEAD'], true)
|
const output = await this.execGit(['reset', '--hard', 'HEAD'], true)
|
||||||
return output.exitCode === 0
|
return output.exitCode === 0
|
||||||
|
|||||||
@@ -118,4 +118,10 @@ export interface IGitSourceSettings {
|
|||||||
* User override on the GitHub Server/Host URL that hosts the repository to be cloned
|
* User override on the GitHub Server/Host URL that hosts the repository to be cloned
|
||||||
*/
|
*/
|
||||||
githubServerUrl: string | undefined
|
githubServerUrl: string | undefined
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opt-in to allow checking out fork pull request code from a workflow
|
||||||
|
* triggered by pull_request_target or workflow_run.
|
||||||
|
*/
|
||||||
|
allowUnsafePrCheckout: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
|
|||||||
import * as fsHelper from './fs-helper'
|
import * as fsHelper from './fs-helper'
|
||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import * as unsafePrCheckoutHelper from './unsafe-pr-checkout-helper'
|
||||||
import * as workflowContextHelper from './workflow-context-helper'
|
import * as workflowContextHelper from './workflow-context-helper'
|
||||||
import {IGitSourceSettings} from './git-source-settings'
|
import {IGitSourceSettings} from './git-source-settings'
|
||||||
|
|
||||||
@@ -161,5 +162,18 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||||||
result.githubServerUrl = core.getInput('github-server-url')
|
result.githubServerUrl = core.getInput('github-server-url')
|
||||||
core.debug(`GitHub Host URL = ${result.githubServerUrl}`)
|
core.debug(`GitHub Host URL = ${result.githubServerUrl}`)
|
||||||
|
|
||||||
|
// Allow unsafe PR checkout (opt-in for pull_request_target / workflow_run fork PRs)
|
||||||
|
result.allowUnsafePrCheckout =
|
||||||
|
(core.getInput('allow-unsafe-pr-checkout') || 'false').toUpperCase() ===
|
||||||
|
'TRUE'
|
||||||
|
core.debug(`allow unsafe PR checkout = ${result.allowUnsafePrCheckout}`)
|
||||||
|
|
||||||
|
unsafePrCheckoutHelper.assertSafePrCheckout({
|
||||||
|
qualifiedRepository,
|
||||||
|
ref: result.ref,
|
||||||
|
commit: result.commit,
|
||||||
|
allowUnsafePrCheckout: result.allowUnsafePrCheckout
|
||||||
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ function updateUsage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateUsage(
|
updateUsage(
|
||||||
'actions/checkout@v4',
|
'actions/checkout@v5',
|
||||||
path.join(__dirname, '..', '..', 'action.yml'),
|
path.join(__dirname, '..', '..', 'action.yml'),
|
||||||
path.join(__dirname, '..', '..', 'README.md')
|
path.join(__dirname, '..', '..', 'README.md')
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ export async function checkCommitInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromPayload(path: string): any {
|
export function fromPayload(path: string): any {
|
||||||
return select(github.context.payload, path)
|
return select(github.context.payload, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
88
src/unsafe-pr-checkout-helper.ts
Normal file
88
src/unsafe-pr-checkout-helper.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import * as github from '@actions/github'
|
||||||
|
import {fromPayload} from './ref-helper'
|
||||||
|
|
||||||
|
const PR_REF_PATTERN = /^refs\/pull\/[0-9]+\/(?:head|merge)$/
|
||||||
|
|
||||||
|
export interface IUnsafePrCheckoutInput {
|
||||||
|
qualifiedRepository: string
|
||||||
|
ref: string
|
||||||
|
commit: string | undefined
|
||||||
|
allowUnsafePrCheckout: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function assertSafePrCheckout(input: IUnsafePrCheckoutInput): void {
|
||||||
|
if (input.allowUnsafePrCheckout) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventName = github.context.eventName
|
||||||
|
if (eventName !== 'pull_request_target' && eventName !== 'workflow_run') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseRepoId = fromPayload('repository.id')
|
||||||
|
if (typeof baseRepoId !== 'number') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let prHeadRepoId: unknown
|
||||||
|
let prHeadRepoFullName: unknown
|
||||||
|
const prShas: string[] = []
|
||||||
|
|
||||||
|
if (eventName === 'pull_request_target') {
|
||||||
|
prHeadRepoId = fromPayload('pull_request.head.repo.id')
|
||||||
|
prHeadRepoFullName = fromPayload('pull_request.head.repo.full_name')
|
||||||
|
pushIfSha(prShas, fromPayload('pull_request.head.sha'))
|
||||||
|
pushIfSha(prShas, fromPayload('pull_request.merge_commit_sha'))
|
||||||
|
} else {
|
||||||
|
const wrEvent = fromPayload('workflow_run.event')
|
||||||
|
if (typeof wrEvent !== 'string' || !wrEvent.startsWith('pull_request')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
prHeadRepoId = fromPayload('workflow_run.head_repository.id')
|
||||||
|
prHeadRepoFullName = fromPayload('workflow_run.head_repository.full_name')
|
||||||
|
pushIfSha(prShas, fromPayload('workflow_run.head_commit.id'))
|
||||||
|
// For `pull_request_target`-triggered workflow_run, `head_sha` is the base
|
||||||
|
// default branch SHA (not the PR head)
|
||||||
|
if (wrEvent !== 'pull_request_target') {
|
||||||
|
pushIfSha(prShas, fromPayload('workflow_run.head_sha'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// (A) Fork PR?
|
||||||
|
if (typeof prHeadRepoId !== 'number' || prHeadRepoId === baseRepoId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// (B) We cannot check for all fork PR refs so check to see
|
||||||
|
// if the resolved input points to the fork PR sha we have in the payload
|
||||||
|
const repositoryMatchesPrHead =
|
||||||
|
typeof prHeadRepoFullName === 'string' &&
|
||||||
|
input.qualifiedRepository.toLowerCase() === prHeadRepoFullName.toLowerCase()
|
||||||
|
const refMatchesPullPattern = PR_REF_PATTERN.test(input.ref)
|
||||||
|
const commitMatchesPrHeadSha =
|
||||||
|
!!input.commit && prShas.includes(input.commit.toLowerCase())
|
||||||
|
|
||||||
|
if (
|
||||||
|
!repositoryMatchesPrHead &&
|
||||||
|
!refMatchesPullPattern &&
|
||||||
|
!commitMatchesPrHeadSha
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Refusing to check out fork pull request code from a '${eventName}' workflow. ` +
|
||||||
|
`This workflow runs with the base repository's GITHUB_TOKEN, secrets, default-branch ` +
|
||||||
|
`cache scope, and runner access. Fetching and executing a fork's code in that trusted ` +
|
||||||
|
`context commonly leads to "pwn request" vulnerabilities. To opt in, review the risks ` +
|
||||||
|
`at https://gh.io/securely-using-pull_request_target and set 'allow-unsafe-pr-checkout: true' ` +
|
||||||
|
`on the actions/checkout step.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushIfSha(target: string[], value: unknown): void {
|
||||||
|
if (typeof value === 'string' && value.length > 0) {
|
||||||
|
target.push(value.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user