Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e204e9a92 | |||
| 0299a0d2b6 | |||
| be0f448456 | |||
| 56c00a7b1f | |||
| 85e47d1a2b | |||
| 3fc17f8645 | |||
| e3bc06d986 | |||
| 442567ba57 | |||
| 7f00b66d06 | |||
| eccf386318 | |||
| 2bd2911be9 | |||
| afe4af09a7 | |||
| 25a956c84d | |||
| 5a4ac9002d | |||
| c952173edf | |||
| a81bbbf829 | |||
| 21dc310f19 | |||
| be6c44d969 | |||
| dac8cc78a1 | |||
| 2036a08e25 | |||
| 592cf69a22 | |||
| a4b69b4886 | |||
| 1433f62caa | |||
| 61b9e3751b | |||
| 28c7f3d2b5 | |||
| fb6f360df2 | |||
| b4483adec3 | |||
| 00a3be8934 | |||
| 453ee27fca | |||
| 65865e15a1 | |||
| aabbfeb2ce | |||
| e52d022eb5 | |||
| 2ff2fbdea4 | |||
| df86c829eb | |||
| 97b30c411c |
@@ -27,6 +27,7 @@
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.licenses/** -diff linguist-generated=true
|
||||
@@ -0,0 +1,51 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process
|
||||
# from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js 12.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Rebuild the index.js file
|
||||
run: npm run build
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If dist/ was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Licensed
|
||||
|
||||
on:
|
||||
push: {branches: main}
|
||||
pull_request: {branches: main}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: npm ci
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- releases/*
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
sources:
|
||||
npm: true
|
||||
|
||||
allowed:
|
||||
- apache-2.0
|
||||
- bsd-2-clause
|
||||
- bsd-3-clause
|
||||
- isc
|
||||
- mit
|
||||
- cc0-1.0
|
||||
- unlicense
|
||||
|
||||
reviewed:
|
||||
npm:
|
||||
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
@@ -1,6 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## v2.3.1
|
||||
|
||||
- [Fix default branch resolution for .wiki and when using SSH](https://github.com/actions/checkout/pull/284)
|
||||
|
||||
|
||||
## v2.3.0
|
||||
|
||||
- [Fallback to the default branch](https://github.com/actions/checkout/pull/278)
|
||||
|
||||
## v2.2.0
|
||||
|
||||
- [Fetch all history for all tags and branches when fetch-depth=0](https://github.com/actions/checkout/pull/258)
|
||||
|
||||
## v2.1.1
|
||||
|
||||
- Changes to support GHES ([here](https://github.com/actions/checkout/pull/236) and [here](https://github.com/actions/checkout/pull/248))
|
||||
|
||||
## v2.1.0
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
* @actions/actions-runtime
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
|
||||
|
||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth` to fetch more history. Refer [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events.
|
||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth: 0` to fetch all history for all branches and tags. Refer [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events.
|
||||
|
||||
The auth token is persisted in the local git config. This enables your scripts to run authenticated git commands. The token is removed during post-job cleanup. Set `persist-credentials: false` to opt-out.
|
||||
|
||||
@@ -42,7 +42,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
|
||||
|
||||
# The branch, tag or SHA to checkout. When checking out the repository that
|
||||
# triggered a workflow, this defaults to the reference or SHA for that event.
|
||||
# Otherwise, defaults to `master`.
|
||||
# Otherwise, uses the default branch.
|
||||
ref: ''
|
||||
|
||||
# Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
@@ -89,7 +89,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
|
||||
# Default: true
|
||||
clean: ''
|
||||
|
||||
# Number of commits to fetch. 0 indicates all history.
|
||||
# Number of commits to fetch. 0 indicates all history for all branches and tags.
|
||||
# Default: 1
|
||||
fetch-depth: ''
|
||||
|
||||
@@ -110,6 +110,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
|
||||
|
||||
# Scenarios
|
||||
|
||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
||||
- [Checkout a different branch](#Checkout-a-different-branch)
|
||||
- [Checkout HEAD^](#Checkout-HEAD)
|
||||
- [Checkout multiple repos (side by side)](#Checkout-multiple-repos-side-by-side)
|
||||
@@ -117,9 +118,15 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
|
||||
- [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)
|
||||
- [Fetch all tags](#Fetch-all-tags)
|
||||
- [Fetch all branches](#Fetch-all-branches)
|
||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
||||
- [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
|
||||
|
||||
## Fetch all history for all tags and branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
```
|
||||
|
||||
## Checkout a different branch
|
||||
|
||||
@@ -198,7 +205,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
types: [opened, synchronize, closed]
|
||||
jobs:
|
||||
build:
|
||||
@@ -207,27 +214,22 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
```
|
||||
|
||||
## Fetch all tags
|
||||
## Push a commit using the built-in token
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
```
|
||||
|
||||
## Fetch all branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
|
||||
```
|
||||
|
||||
## Fetch all history for all tags and branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
git fetch --prune --unshallow
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
date > generated.txt
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git add .
|
||||
git commit -m "generated"
|
||||
git push
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
@@ -714,6 +714,7 @@ async function setup(testName: string): Promise<void> {
|
||||
),
|
||||
env: {},
|
||||
fetch: jest.fn(),
|
||||
getDefaultBranch: jest.fn(),
|
||||
getWorkingDirectory: jest.fn(() => workspace),
|
||||
init: jest.fn(),
|
||||
isDetached: jest.fn(),
|
||||
@@ -722,9 +723,11 @@ async function setup(testName: string): Promise<void> {
|
||||
log1: jest.fn(),
|
||||
remoteAdd: jest.fn(),
|
||||
removeEnvironmentVariable: jest.fn((name: string) => delete git.env[name]),
|
||||
revParse: jest.fn(),
|
||||
setEnvironmentVariable: jest.fn((name: string, value: string) => {
|
||||
git.env[name] = value
|
||||
}),
|
||||
shaExists: jest.fn(),
|
||||
submoduleForeach: jest.fn(async () => {
|
||||
return ''
|
||||
}),
|
||||
@@ -761,7 +764,7 @@ async function setup(testName: string): Promise<void> {
|
||||
submodules: false,
|
||||
nestedSubmodules: false,
|
||||
persistCredentials: true,
|
||||
ref: 'refs/heads/master',
|
||||
ref: 'refs/heads/main',
|
||||
repositoryName: 'my-repo',
|
||||
repositoryOwner: 'my-org',
|
||||
repositoryPath: '',
|
||||
|
||||
@@ -9,6 +9,7 @@ const testWorkspace = path.join(__dirname, '_temp', 'git-directory-helper')
|
||||
let repositoryPath: string
|
||||
let repositoryUrl: string
|
||||
let clean: boolean
|
||||
let ref: string
|
||||
let git: IGitCommandManager
|
||||
|
||||
describe('git-directory-helper tests', () => {
|
||||
@@ -41,7 +42,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -63,7 +65,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -88,7 +91,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -109,7 +113,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -137,7 +142,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -163,7 +169,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
differentRepositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -187,7 +194,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -212,7 +220,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -236,7 +245,8 @@ describe('git-directory-helper tests', () => {
|
||||
undefined,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -260,7 +270,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -290,7 +301,8 @@ describe('git-directory-helper tests', () => {
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
@@ -305,29 +317,66 @@ describe('git-directory-helper tests', () => {
|
||||
expect(git.tryReset).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const removesRemoteBranches = 'removes local branches'
|
||||
it(removesRemoteBranches, async () => {
|
||||
const removesAncestorRemoteBranch = 'removes ancestor remote branch'
|
||||
it(removesAncestorRemoteBranch, async () => {
|
||||
// Arrange
|
||||
await setup(removesRemoteBranches)
|
||||
await setup(removesAncestorRemoteBranch)
|
||||
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
|
||||
const mockBranchList = git.branchList as jest.Mock<any, any>
|
||||
mockBranchList.mockImplementation(async (remote: boolean) => {
|
||||
return remote ? ['remote-branch-1', 'remote-branch-2'] : []
|
||||
return remote ? ['origin/remote-branch-1', 'origin/remote-branch-2'] : []
|
||||
})
|
||||
ref = 'remote-branch-1/conflict'
|
||||
|
||||
// Act
|
||||
await gitDirectoryHelper.prepareExistingDirectory(
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
const files = await fs.promises.readdir(repositoryPath)
|
||||
expect(files.sort()).toEqual(['.git', 'my-file'])
|
||||
expect(git.branchDelete).toHaveBeenCalledWith(true, 'remote-branch-1')
|
||||
expect(git.branchDelete).toHaveBeenCalledWith(true, 'remote-branch-2')
|
||||
expect(git.branchDelete).toHaveBeenCalledTimes(1)
|
||||
expect(git.branchDelete).toHaveBeenCalledWith(
|
||||
true,
|
||||
'origin/remote-branch-1'
|
||||
)
|
||||
})
|
||||
|
||||
const removesDescendantRemoteBranches = 'removes descendant remote branch'
|
||||
it(removesDescendantRemoteBranches, async () => {
|
||||
// Arrange
|
||||
await setup(removesDescendantRemoteBranches)
|
||||
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
|
||||
const mockBranchList = git.branchList as jest.Mock<any, any>
|
||||
mockBranchList.mockImplementation(async (remote: boolean) => {
|
||||
return remote
|
||||
? ['origin/remote-branch-1/conflict', 'origin/remote-branch-2']
|
||||
: []
|
||||
})
|
||||
ref = 'remote-branch-1'
|
||||
|
||||
// Act
|
||||
await gitDirectoryHelper.prepareExistingDirectory(
|
||||
git,
|
||||
repositoryPath,
|
||||
repositoryUrl,
|
||||
clean,
|
||||
ref
|
||||
)
|
||||
|
||||
// Assert
|
||||
const files = await fs.promises.readdir(repositoryPath)
|
||||
expect(files.sort()).toEqual(['.git', 'my-file'])
|
||||
expect(git.branchDelete).toHaveBeenCalledTimes(1)
|
||||
expect(git.branchDelete).toHaveBeenCalledWith(
|
||||
true,
|
||||
'origin/remote-branch-1/conflict'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -344,6 +393,9 @@ async function setup(testName: string): Promise<void> {
|
||||
// Clean
|
||||
clean = true
|
||||
|
||||
// Ref
|
||||
ref = ''
|
||||
|
||||
// Git command manager
|
||||
git = {
|
||||
branchDelete: jest.fn(),
|
||||
@@ -356,6 +408,7 @@ async function setup(testName: string): Promise<void> {
|
||||
config: jest.fn(),
|
||||
configExists: jest.fn(),
|
||||
fetch: jest.fn(),
|
||||
getDefaultBranch: jest.fn(),
|
||||
getWorkingDirectory: jest.fn(() => repositoryPath),
|
||||
init: jest.fn(),
|
||||
isDetached: jest.fn(),
|
||||
@@ -364,7 +417,9 @@ async function setup(testName: string): Promise<void> {
|
||||
log1: jest.fn(),
|
||||
remoteAdd: jest.fn(),
|
||||
removeEnvironmentVariable: jest.fn(),
|
||||
revParse: jest.fn(),
|
||||
setEnvironmentVariable: jest.fn(),
|
||||
shaExists: jest.fn(),
|
||||
submoduleForeach: jest.fn(),
|
||||
submoduleSync: jest.fn(),
|
||||
submoduleUpdate: jest.fn(),
|
||||
|
||||
@@ -110,13 +110,6 @@ describe('input-helper tests', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('sets correct default ref/sha for other repo', () => {
|
||||
inputs.repository = 'some-owner/some-other-repo'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings.ref).toBe('refs/heads/master')
|
||||
expect(settings.commit).toBeFalsy()
|
||||
})
|
||||
|
||||
it('sets ref to empty when explicit sha', () => {
|
||||
inputs.ref = '1111111111222222222233333333334444444444'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
mkdir override-git-version
|
||||
cd override-git-version
|
||||
echo @echo override git version 1.2.3 > git.cmd
|
||||
echo ::add-path::%CD%
|
||||
echo "%CD%" >> $GITHUB_PATH
|
||||
cd ..
|
||||
|
||||
@@ -5,5 +5,5 @@ cd override-git-version
|
||||
echo "#!/bin/sh" > git
|
||||
echo "echo override git version 1.2.3" >> git
|
||||
chmod +x git
|
||||
echo "::add-path::$(pwd)"
|
||||
echo "$(pwd)" >> $GITHUB_PATH
|
||||
cd ..
|
||||
|
||||
@@ -20,5 +20,5 @@ else
|
||||
|
||||
# Verify auth token
|
||||
cd basic
|
||||
git fetch --no-tags --depth=1 origin +refs/heads/master:refs/remotes/origin/master
|
||||
git fetch --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main
|
||||
fi
|
||||
|
||||
@@ -12,6 +12,6 @@ if [[ "$(git status --porcelain)" != "" ]]; then
|
||||
echo ----------------------------------------
|
||||
echo Troubleshooting
|
||||
echo ----------------------------------------
|
||||
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run all"
|
||||
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run format && npm run build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ inputs:
|
||||
description: >
|
||||
The branch, tag or SHA to checkout. When checking out the repository that
|
||||
triggered a workflow, this defaults to the reference or SHA for that
|
||||
event. Otherwise, defaults to `master`.
|
||||
event. Otherwise, uses the default branch.
|
||||
token:
|
||||
description: >
|
||||
Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
@@ -54,7 +54,7 @@ inputs:
|
||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
default: true
|
||||
fetch-depth:
|
||||
description: 'Number of commits to fetch. 0 indicates all history.'
|
||||
description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
|
||||
default: 1
|
||||
lfs:
|
||||
description: 'Whether to download Git-LFS files'
|
||||
|
||||
@@ -24,7 +24,7 @@ We want to take this opportunity to make behavioral changes, from v1. This docum
|
||||
description: >
|
||||
The branch, tag or SHA to checkout. When checking out the repository that
|
||||
triggered a workflow, this defaults to the reference or SHA for that
|
||||
event. Otherwise, defaults to `master`.
|
||||
event. Otherwise, uses the default branch.
|
||||
token:
|
||||
description: >
|
||||
Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
@@ -70,7 +70,7 @@ We want to take this opportunity to make behavioral changes, from v1. This docum
|
||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
default: true
|
||||
fetch-depth:
|
||||
description: 'Number of commits to fetch. 0 indicates all history.'
|
||||
description: 'Number of commits to fetch. 0 indicates all history for all tags and branches.'
|
||||
default: 1
|
||||
lfs:
|
||||
description: 'Whether to download Git-LFS files'
|
||||
@@ -277,7 +277,7 @@ Note:
|
||||
### Branching strategy and release tags
|
||||
|
||||
- Create a servicing branch for V1: `releases/v1`
|
||||
- Merge the changes into `master`
|
||||
- Merge the changes into the default branch
|
||||
- Release using a new tag `preview`
|
||||
- When stable, release using a new tag `v2`
|
||||
|
||||
|
||||
Vendored
+472
-61
@@ -1408,6 +1408,32 @@ function getServerUrl() {
|
||||
exports.getServerUrl = getServerUrl;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 82:
|
||||
/***/ (function(__unusedmodule, exports) {
|
||||
|
||||
"use strict";
|
||||
|
||||
// We use any as a valid input type
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Sanitizes an input into a string so it can be passed into issueCommand safely
|
||||
* @param input input to sanitize into a string
|
||||
*/
|
||||
function toCommandValue(input) {
|
||||
if (input === null || input === undefined) {
|
||||
return '';
|
||||
}
|
||||
else if (typeof input === 'string' || input instanceof String) {
|
||||
return input;
|
||||
}
|
||||
return JSON.stringify(input);
|
||||
}
|
||||
exports.toCommandValue = toCommandValue;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 87:
|
||||
@@ -1417,6 +1443,42 @@ module.exports = require("os");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 102:
|
||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
// For internal use, subject to change.
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// We use any as a valid input type
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const fs = __importStar(__webpack_require__(747));
|
||||
const os = __importStar(__webpack_require__(87));
|
||||
const utils_1 = __webpack_require__(82);
|
||||
function issueCommand(command, message) {
|
||||
const filePath = process.env[`GITHUB_${command}`];
|
||||
if (!filePath) {
|
||||
throw new Error(`Unable to find environment variable for file command ${command}`);
|
||||
}
|
||||
if (!fs.existsSync(filePath)) {
|
||||
throw new Error(`Missing file at path: ${filePath}`);
|
||||
}
|
||||
fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
}
|
||||
exports.issueCommand = issueCommand;
|
||||
//# sourceMappingURL=file-command.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 118:
|
||||
/***/ (function(module, __unusedexports, __webpack_require__) {
|
||||
|
||||
@@ -3359,7 +3421,7 @@ module.exports = {"name":"@octokit/rest","version":"16.43.1","publishConfig":{"a
|
||||
/***/ }),
|
||||
|
||||
/***/ 227:
|
||||
/***/ (function(__unusedmodule, exports) {
|
||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
@@ -3372,7 +3434,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const url_1 = __webpack_require__(835);
|
||||
const core = __importStar(__webpack_require__(470));
|
||||
const github = __importStar(__webpack_require__(469));
|
||||
exports.tagsRefSpec = '+refs/tags/*:refs/tags/*';
|
||||
function getCheckoutInfo(git, ref, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!git) {
|
||||
@@ -3419,6 +3492,15 @@ function getCheckoutInfo(git, ref, commit) {
|
||||
});
|
||||
}
|
||||
exports.getCheckoutInfo = getCheckoutInfo;
|
||||
function getRefSpecForAllHistory(ref, commit) {
|
||||
const result = ['+refs/heads/*:refs/remotes/origin/*', exports.tagsRefSpec];
|
||||
if (ref && ref.toUpperCase().startsWith('REFS/PULL/')) {
|
||||
const branch = ref.substring('refs/pull/'.length);
|
||||
result.push(`+${commit || ref}:refs/remotes/pull/${branch}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.getRefSpecForAllHistory = getRefSpecForAllHistory;
|
||||
function getRefSpec(ref, commit) {
|
||||
if (!ref && !commit) {
|
||||
throw new Error('Args ref and commit cannot both be empty');
|
||||
@@ -3468,6 +3550,129 @@ function getRefSpec(ref, commit) {
|
||||
}
|
||||
}
|
||||
exports.getRefSpec = getRefSpec;
|
||||
/**
|
||||
* Tests whether the initial fetch created the ref at the expected commit
|
||||
*/
|
||||
function testRef(git, ref, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!git) {
|
||||
throw new Error('Arg git cannot be empty');
|
||||
}
|
||||
if (!ref && !commit) {
|
||||
throw new Error('Args ref and commit cannot both be empty');
|
||||
}
|
||||
// No SHA? Nothing to test
|
||||
if (!commit) {
|
||||
return true;
|
||||
}
|
||||
// SHA only?
|
||||
else if (!ref) {
|
||||
return yield git.shaExists(commit);
|
||||
}
|
||||
const upperRef = ref.toUpperCase();
|
||||
// refs/heads/
|
||||
if (upperRef.startsWith('REFS/HEADS/')) {
|
||||
const branch = ref.substring('refs/heads/'.length);
|
||||
return ((yield git.branchExists(true, `origin/${branch}`)) &&
|
||||
commit === (yield git.revParse(`refs/remotes/origin/${branch}`)));
|
||||
}
|
||||
// refs/pull/
|
||||
else if (upperRef.startsWith('REFS/PULL/')) {
|
||||
// Assume matches because fetched using the commit
|
||||
return true;
|
||||
}
|
||||
// refs/tags/
|
||||
else if (upperRef.startsWith('REFS/TAGS/')) {
|
||||
const tagName = ref.substring('refs/tags/'.length);
|
||||
return ((yield git.tagExists(tagName)) && commit === (yield git.revParse(ref)));
|
||||
}
|
||||
// Unexpected
|
||||
else {
|
||||
core.debug(`Unexpected ref format '${ref}' when testing ref info`);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.testRef = testRef;
|
||||
function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
// GHES?
|
||||
if (isGhes()) {
|
||||
return;
|
||||
}
|
||||
// Auth token?
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
// Public PR synchronize, for workflow repo?
|
||||
if (fromPayload('repository.private') !== false ||
|
||||
github.context.eventName !== 'pull_request' ||
|
||||
fromPayload('action') !== 'synchronize' ||
|
||||
repositoryOwner !== github.context.repo.owner ||
|
||||
repositoryName !== github.context.repo.repo ||
|
||||
ref !== github.context.ref ||
|
||||
!ref.startsWith('refs/pull/') ||
|
||||
commit !== github.context.sha) {
|
||||
return;
|
||||
}
|
||||
// Head SHA
|
||||
const expectedHeadSha = fromPayload('after');
|
||||
if (!expectedHeadSha) {
|
||||
core.debug('Unable to determine head sha');
|
||||
return;
|
||||
}
|
||||
// Base SHA
|
||||
const expectedBaseSha = fromPayload('pull_request.base.sha');
|
||||
if (!expectedBaseSha) {
|
||||
core.debug('Unable to determine base sha');
|
||||
return;
|
||||
}
|
||||
// Expected message?
|
||||
const expectedMessage = `Merge ${expectedHeadSha} into ${expectedBaseSha}`;
|
||||
if (commitInfo.indexOf(expectedMessage) >= 0) {
|
||||
return;
|
||||
}
|
||||
// Extract details from message
|
||||
const match = commitInfo.match(/Merge ([0-9a-f]{40}) into ([0-9a-f]{40})/);
|
||||
if (!match) {
|
||||
core.debug('Unexpected message format');
|
||||
return;
|
||||
}
|
||||
// Post telemetry
|
||||
const actualHeadSha = match[1];
|
||||
if (actualHeadSha !== expectedHeadSha) {
|
||||
core.debug(`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`);
|
||||
const octokit = new github.GitHub(token, {
|
||||
userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload('number')};run_id=${process.env['GITHUB_RUN_ID']};expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})`
|
||||
});
|
||||
yield octokit.repos.get({ owner: repositoryOwner, repo: repositoryName });
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
core.debug(`Error when validating commit info: ${err.stack}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.checkCommitInfo = checkCommitInfo;
|
||||
function fromPayload(path) {
|
||||
return select(github.context.payload, path);
|
||||
}
|
||||
function select(obj, path) {
|
||||
if (!obj) {
|
||||
return undefined;
|
||||
}
|
||||
const i = path.indexOf('.');
|
||||
if (i < 0) {
|
||||
return obj[path];
|
||||
}
|
||||
const key = path.substr(0, i);
|
||||
return select(obj[key], path.substr(i + 1));
|
||||
}
|
||||
function isGhes() {
|
||||
const ghUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
@@ -5355,7 +5560,7 @@ class GitAuthHelper {
|
||||
const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
|
||||
for (const configPath of configPaths) {
|
||||
core.debug(`Replacing token placeholder in '${configPath}'`);
|
||||
this.replaceTokenPlaceholder(configPath);
|
||||
yield this.replaceTokenPlaceholder(configPath);
|
||||
}
|
||||
if (this.settings.sshKey) {
|
||||
// Configure core.sshCommand
|
||||
@@ -5545,6 +5750,7 @@ const exec = __importStar(__webpack_require__(986));
|
||||
const fshelper = __importStar(__webpack_require__(618));
|
||||
const io = __importStar(__webpack_require__(1));
|
||||
const path = __importStar(__webpack_require__(622));
|
||||
const refHelper = __importStar(__webpack_require__(227));
|
||||
const regexpHelper = __importStar(__webpack_require__(528));
|
||||
const retryHelper = __importStar(__webpack_require__(587));
|
||||
const git_version_1 = __webpack_require__(559);
|
||||
@@ -5660,18 +5866,14 @@ class GitCommandManager {
|
||||
return output.exitCode === 0;
|
||||
});
|
||||
}
|
||||
fetch(fetchDepth, refSpec) {
|
||||
fetch(refSpec, fetchDepth) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const args = [
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'fetch',
|
||||
'--no-tags',
|
||||
'--prune',
|
||||
'--progress',
|
||||
'--no-recurse-submodules'
|
||||
];
|
||||
if (fetchDepth > 0) {
|
||||
const args = ['-c', 'protocol.version=2', 'fetch'];
|
||||
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
|
||||
args.push('--no-tags');
|
||||
}
|
||||
args.push('--prune', '--progress', '--no-recurse-submodules');
|
||||
if (fetchDepth && fetchDepth > 0) {
|
||||
args.push(`--depth=${fetchDepth}`);
|
||||
}
|
||||
else if (fshelper.fileExistsSync(path.join(this.workingDirectory, '.git', 'shallow'))) {
|
||||
@@ -5687,6 +5889,33 @@ class GitCommandManager {
|
||||
}));
|
||||
});
|
||||
}
|
||||
getDefaultBranch(repositoryUrl) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let output;
|
||||
yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||
output = yield this.execGit([
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
repositoryUrl,
|
||||
'HEAD'
|
||||
]);
|
||||
}));
|
||||
if (output) {
|
||||
// Satisfy compiler, will always be set
|
||||
for (let line of output.stdout.trim().split('\n')) {
|
||||
line = line.trim();
|
||||
if (line.startsWith('ref:') || line.endsWith('HEAD')) {
|
||||
return line
|
||||
.substr('ref:'.length, line.length - 'ref:'.length - 'HEAD'.length)
|
||||
.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error('Unexpected output when retrieving default branch');
|
||||
});
|
||||
}
|
||||
getWorkingDirectory() {
|
||||
return this.workingDirectory;
|
||||
}
|
||||
@@ -5716,9 +5945,12 @@ class GitCommandManager {
|
||||
yield this.execGit(['lfs', 'install', '--local']);
|
||||
});
|
||||
}
|
||||
log1() {
|
||||
log1(format) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.execGit(['log', '-1']);
|
||||
var args = format ? ['log', '-1', format] : ['log', '-1'];
|
||||
var silent = format ? false : true;
|
||||
const output = yield this.execGit(args, false, silent);
|
||||
return output.stdout;
|
||||
});
|
||||
}
|
||||
remoteAdd(remoteName, remoteUrl) {
|
||||
@@ -5729,9 +5961,28 @@ class GitCommandManager {
|
||||
removeEnvironmentVariable(name) {
|
||||
delete this.gitEnv[name];
|
||||
}
|
||||
/**
|
||||
* Resolves a ref to a SHA. For a branch or lightweight tag, the commit SHA is returned.
|
||||
* For an annotated tag, the tag SHA is returned.
|
||||
* @param {string} ref For example: 'refs/heads/main' or '/refs/tags/v1'
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
revParse(ref) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const output = yield this.execGit(['rev-parse', ref]);
|
||||
return output.stdout.trim();
|
||||
});
|
||||
}
|
||||
setEnvironmentVariable(name, value) {
|
||||
this.gitEnv[name] = value;
|
||||
}
|
||||
shaExists(sha) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const args = ['rev-parse', '--verify', '--quiet', `${sha}^{object}`];
|
||||
const output = yield this.execGit(args, true);
|
||||
return output.exitCode === 0;
|
||||
});
|
||||
}
|
||||
submoduleForeach(command, recursive) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const args = ['submodule', 'foreach'];
|
||||
@@ -5820,7 +6071,7 @@ class GitCommandManager {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
execGit(args, allowAllExitCodes = false) {
|
||||
execGit(args, allowAllExitCodes = false, silent = false) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
fshelper.directoryExistsSync(this.workingDirectory, true);
|
||||
const result = new GitOutput();
|
||||
@@ -5835,6 +6086,7 @@ class GitCommandManager {
|
||||
const options = {
|
||||
cwd: this.workingDirectory,
|
||||
env,
|
||||
silent,
|
||||
ignoreReturnCode: allowAllExitCodes,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
@@ -5970,7 +6222,7 @@ function getSource(settings) {
|
||||
core.endGroup();
|
||||
// Prepare existing directory, otherwise recreate
|
||||
if (isExisting) {
|
||||
yield gitDirectoryHelper.prepareExistingDirectory(git, settings.repositoryPath, repositoryUrl, settings.clean);
|
||||
yield gitDirectoryHelper.prepareExistingDirectory(git, settings.repositoryPath, repositoryUrl, settings.clean, settings.ref);
|
||||
}
|
||||
if (!git) {
|
||||
// Downloading using REST API
|
||||
@@ -6006,14 +6258,38 @@ function getSource(settings) {
|
||||
core.startGroup('Setting up auth');
|
||||
yield authHelper.configureAuth();
|
||||
core.endGroup();
|
||||
// Determine the default branch
|
||||
if (!settings.ref && !settings.commit) {
|
||||
core.startGroup('Determining the default branch');
|
||||
if (settings.sshKey) {
|
||||
settings.ref = yield git.getDefaultBranch(repositoryUrl);
|
||||
}
|
||||
else {
|
||||
settings.ref = yield githubApiHelper.getDefaultBranch(settings.authToken, settings.repositoryOwner, settings.repositoryName);
|
||||
}
|
||||
core.endGroup();
|
||||
}
|
||||
// LFS install
|
||||
if (settings.lfs) {
|
||||
yield git.lfsInstall();
|
||||
}
|
||||
// Fetch
|
||||
core.startGroup('Fetching the repository');
|
||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
|
||||
yield git.fetch(settings.fetchDepth, refSpec);
|
||||
if (settings.fetchDepth <= 0) {
|
||||
// Fetch all branches and tags
|
||||
let refSpec = refHelper.getRefSpecForAllHistory(settings.ref, settings.commit);
|
||||
yield git.fetch(refSpec);
|
||||
// When all history is fetched, the ref we're interested in may have moved to a different
|
||||
// commit (push or force push). If so, fetch again with a targeted refspec.
|
||||
if (!(yield refHelper.testRef(git, settings.ref, settings.commit))) {
|
||||
refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
|
||||
yield git.fetch(refSpec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
|
||||
yield git.fetch(refSpec, settings.fetchDepth);
|
||||
}
|
||||
core.endGroup();
|
||||
// Checkout info
|
||||
core.startGroup('Determining the checkout info');
|
||||
@@ -6056,8 +6332,12 @@ function getSource(settings) {
|
||||
yield authHelper.removeGlobalAuth();
|
||||
}
|
||||
}
|
||||
// Dump some info about the checked out commit
|
||||
yield git.log1();
|
||||
// Get commit information
|
||||
const commitInfo = yield git.log1();
|
||||
// Log commit sha
|
||||
yield git.log1("--format='%H'");
|
||||
// Check for incorrect pull request merge commit
|
||||
yield refHelper.checkCommitInfo(settings.authToken, commitInfo, settings.repositoryOwner, settings.repositoryName, settings.ref, settings.commit);
|
||||
}
|
||||
finally {
|
||||
// Remove auth
|
||||
@@ -7266,17 +7546,25 @@ function octokitValidate(octokit) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const os = __webpack_require__(87);
|
||||
const os = __importStar(__webpack_require__(87));
|
||||
const utils_1 = __webpack_require__(82);
|
||||
/**
|
||||
* Commands
|
||||
*
|
||||
* Command Format:
|
||||
* ##[name key=value;key=value]message
|
||||
* ::name key=value,key=value::message
|
||||
*
|
||||
* Examples:
|
||||
* ##[warning]This is the user warning message
|
||||
* ##[set-secret name=mypassword]definitelyNotAPassword!
|
||||
* ::warning::This is the message
|
||||
* ::set-env name=MY_VAR::some value
|
||||
*/
|
||||
function issueCommand(command, properties, message) {
|
||||
const cmd = new Command(command, properties, message);
|
||||
@@ -7301,34 +7589,39 @@ class Command {
|
||||
let cmdStr = CMD_STRING + this.command;
|
||||
if (this.properties && Object.keys(this.properties).length > 0) {
|
||||
cmdStr += ' ';
|
||||
let first = true;
|
||||
for (const key in this.properties) {
|
||||
if (this.properties.hasOwnProperty(key)) {
|
||||
const val = this.properties[key];
|
||||
if (val) {
|
||||
// safely append the val - avoid blowing up when attempting to
|
||||
// call .replace() if message is not a string for some reason
|
||||
cmdStr += `${key}=${escape(`${val || ''}`)},`;
|
||||
if (first) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
cmdStr += ',';
|
||||
}
|
||||
cmdStr += `${key}=${escapeProperty(val)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cmdStr += CMD_STRING;
|
||||
// safely append the message - avoid blowing up when attempting to
|
||||
// call .replace() if message is not a string for some reason
|
||||
const message = `${this.message || ''}`;
|
||||
cmdStr += escapeData(message);
|
||||
cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
|
||||
return cmdStr;
|
||||
}
|
||||
}
|
||||
function escapeData(s) {
|
||||
return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A');
|
||||
return utils_1.toCommandValue(s)
|
||||
.replace(/%/g, '%25')
|
||||
.replace(/\r/g, '%0D')
|
||||
.replace(/\n/g, '%0A');
|
||||
}
|
||||
function escape(s) {
|
||||
return s
|
||||
function escapeProperty(s) {
|
||||
return utils_1.toCommandValue(s)
|
||||
.replace(/%/g, '%25')
|
||||
.replace(/\r/g, '%0D')
|
||||
.replace(/\n/g, '%0A')
|
||||
.replace(/]/g, '%5D')
|
||||
.replace(/;/g, '%3B');
|
||||
.replace(/:/g, '%3A')
|
||||
.replace(/,/g, '%2C');
|
||||
}
|
||||
//# sourceMappingURL=command.js.map
|
||||
|
||||
@@ -7362,7 +7655,7 @@ const fs = __importStar(__webpack_require__(747));
|
||||
const fsHelper = __importStar(__webpack_require__(618));
|
||||
const io = __importStar(__webpack_require__(1));
|
||||
const path = __importStar(__webpack_require__(622));
|
||||
function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean) {
|
||||
function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean, ref) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
assert.ok(repositoryPath, 'Expected repositoryPath to be defined');
|
||||
assert.ok(repositoryUrl, 'Expected repositoryUrl to be defined');
|
||||
@@ -7402,10 +7695,24 @@ function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean) {
|
||||
for (const branch of branches) {
|
||||
yield git.branchDelete(false, branch);
|
||||
}
|
||||
// Remove all refs/remotes/origin/* to avoid conflicts
|
||||
branches = yield git.branchList(true);
|
||||
for (const branch of branches) {
|
||||
yield git.branchDelete(true, branch);
|
||||
// Remove any conflicting refs/remotes/origin/*
|
||||
// Example 1: Consider ref is refs/heads/foo and previously fetched refs/remotes/origin/foo/bar
|
||||
// Example 2: Consider ref is refs/heads/foo/bar and previously fetched refs/remotes/origin/foo
|
||||
if (ref) {
|
||||
ref = ref.startsWith('refs/') ? ref : `refs/heads/${ref}`;
|
||||
if (ref.startsWith('refs/heads/')) {
|
||||
const upperName1 = ref.toUpperCase().substr('REFS/HEADS/'.length);
|
||||
const upperName1Slash = `${upperName1}/`;
|
||||
branches = yield git.branchList(true);
|
||||
for (const branch of branches) {
|
||||
const upperName2 = branch.substr('origin/'.length).toUpperCase();
|
||||
const upperName2Slash = `${upperName2}/`;
|
||||
if (upperName1.startsWith(upperName2Slash) ||
|
||||
upperName2.startsWith(upperName1Slash)) {
|
||||
yield git.branchDelete(true, branch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
core.endGroup();
|
||||
// Clean
|
||||
@@ -9336,6 +9643,11 @@ const v4_1 = __importDefault(__webpack_require__(826));
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
function downloadRepository(authToken, owner, repo, ref, commit, repositoryPath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// Determine the default branch
|
||||
if (!ref && !commit) {
|
||||
core.info('Determining the default branch');
|
||||
ref = yield getDefaultBranch(authToken, owner, repo);
|
||||
}
|
||||
// Download the archive
|
||||
let archiveData = yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Downloading the archive');
|
||||
@@ -9357,7 +9669,7 @@ function downloadRepository(authToken, owner, repo, ref, commit, repositoryPath)
|
||||
else {
|
||||
yield toolCache.extractTar(archivePath, extractPath);
|
||||
}
|
||||
io.rmRF(archivePath);
|
||||
yield io.rmRF(archivePath);
|
||||
// Determine the path of the repository content. The archive contains
|
||||
// a top-level folder and the repository content is inside.
|
||||
const archiveFileNames = yield fs.promises.readdir(extractPath);
|
||||
@@ -9376,10 +9688,46 @@ function downloadRepository(authToken, owner, repo, ref, commit, repositoryPath)
|
||||
yield io.mv(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
io.rmRF(extractPath);
|
||||
yield io.rmRF(extractPath);
|
||||
});
|
||||
}
|
||||
exports.downloadRepository = downloadRepository;
|
||||
/**
|
||||
* Looks up the default branch name
|
||||
*/
|
||||
function getDefaultBranch(authToken, owner, repo) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Retrieving the default branch name');
|
||||
const octokit = new github.GitHub(authToken);
|
||||
let result;
|
||||
try {
|
||||
// Get the default branch from the repo info
|
||||
const response = yield octokit.repos.get({ owner, repo });
|
||||
result = response.data.default_branch;
|
||||
assert.ok(result, 'default_branch cannot be empty');
|
||||
}
|
||||
catch (err) {
|
||||
// Handle .wiki repo
|
||||
if (err['status'] === 404 && repo.toUpperCase().endsWith('.WIKI')) {
|
||||
result = 'master';
|
||||
}
|
||||
// Otherwise error
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// Print the default branch
|
||||
core.info(`Default branch '${result}'`);
|
||||
// Prefix with 'refs/heads'
|
||||
if (!result.startsWith('refs/')) {
|
||||
result = `refs/heads/${result}`;
|
||||
}
|
||||
return result;
|
||||
}));
|
||||
});
|
||||
}
|
||||
exports.getDefaultBranch = getDefaultBranch;
|
||||
function downloadArchive(authToken, owner, repo, ref, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const octokit = new github.GitHub(authToken);
|
||||
@@ -9529,10 +9877,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const command_1 = __webpack_require__(431);
|
||||
const os = __webpack_require__(87);
|
||||
const path = __webpack_require__(622);
|
||||
const file_command_1 = __webpack_require__(102);
|
||||
const utils_1 = __webpack_require__(82);
|
||||
const os = __importStar(__webpack_require__(87));
|
||||
const path = __importStar(__webpack_require__(622));
|
||||
/**
|
||||
* The code to exit an action
|
||||
*/
|
||||
@@ -9553,11 +9910,21 @@ var ExitCode;
|
||||
/**
|
||||
* Sets env variable for this action and future actions in the job
|
||||
* @param name the name of the variable to set
|
||||
* @param val the value of the variable
|
||||
* @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function exportVariable(name, val) {
|
||||
process.env[name] = val;
|
||||
command_1.issueCommand('set-env', { name }, val);
|
||||
const convertedVal = utils_1.toCommandValue(val);
|
||||
process.env[name] = convertedVal;
|
||||
const filePath = process.env['GITHUB_ENV'] || '';
|
||||
if (filePath) {
|
||||
const delimiter = '_GitHubActionsFileCommandDelimeter_';
|
||||
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
|
||||
file_command_1.issueCommand('ENV', commandValue);
|
||||
}
|
||||
else {
|
||||
command_1.issueCommand('set-env', { name }, convertedVal);
|
||||
}
|
||||
}
|
||||
exports.exportVariable = exportVariable;
|
||||
/**
|
||||
@@ -9573,7 +9940,13 @@ exports.setSecret = setSecret;
|
||||
* @param inputPath
|
||||
*/
|
||||
function addPath(inputPath) {
|
||||
command_1.issueCommand('add-path', {}, inputPath);
|
||||
const filePath = process.env['GITHUB_PATH'] || '';
|
||||
if (filePath) {
|
||||
file_command_1.issueCommand('PATH', inputPath);
|
||||
}
|
||||
else {
|
||||
command_1.issueCommand('add-path', {}, inputPath);
|
||||
}
|
||||
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
|
||||
}
|
||||
exports.addPath = addPath;
|
||||
@@ -9596,12 +9969,22 @@ exports.getInput = getInput;
|
||||
* Sets the value of an output.
|
||||
*
|
||||
* @param name name of the output to set
|
||||
* @param value value to store
|
||||
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function setOutput(name, value) {
|
||||
command_1.issueCommand('set-output', { name }, value);
|
||||
}
|
||||
exports.setOutput = setOutput;
|
||||
/**
|
||||
* Enables or disables the echoing of commands into stdout for the rest of the step.
|
||||
* Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
|
||||
*
|
||||
*/
|
||||
function setCommandEcho(enabled) {
|
||||
command_1.issue('echo', enabled ? 'on' : 'off');
|
||||
}
|
||||
exports.setCommandEcho = setCommandEcho;
|
||||
//-----------------------------------------------------------------------
|
||||
// Results
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -9618,6 +10001,13 @@ exports.setFailed = setFailed;
|
||||
//-----------------------------------------------------------------------
|
||||
// Logging Commands
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets whether Actions Step Debug is on or not
|
||||
*/
|
||||
function isDebug() {
|
||||
return process.env['RUNNER_DEBUG'] === '1';
|
||||
}
|
||||
exports.isDebug = isDebug;
|
||||
/**
|
||||
* Writes debug message to user log
|
||||
* @param message debug message
|
||||
@@ -9628,18 +10018,18 @@ function debug(message) {
|
||||
exports.debug = debug;
|
||||
/**
|
||||
* Adds an error issue
|
||||
* @param message error issue message
|
||||
* @param message error issue message. Errors will be converted to string via toString()
|
||||
*/
|
||||
function error(message) {
|
||||
command_1.issue('error', message);
|
||||
command_1.issue('error', message instanceof Error ? message.toString() : message);
|
||||
}
|
||||
exports.error = error;
|
||||
/**
|
||||
* Adds an warning issue
|
||||
* @param message warning issue message
|
||||
* @param message warning issue message. Errors will be converted to string via toString()
|
||||
*/
|
||||
function warning(message) {
|
||||
command_1.issue('warning', message);
|
||||
command_1.issue('warning', message instanceof Error ? message.toString() : message);
|
||||
}
|
||||
exports.warning = warning;
|
||||
/**
|
||||
@@ -9690,6 +10080,30 @@ function group(name, fn) {
|
||||
});
|
||||
}
|
||||
exports.group = group;
|
||||
//-----------------------------------------------------------------------
|
||||
// Wrapper action state
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Saves state for current action, the state can only be retrieved by this action's post job execution.
|
||||
*
|
||||
* @param name name of the state to store
|
||||
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function saveState(name, value) {
|
||||
command_1.issueCommand('save-state', { name }, value);
|
||||
}
|
||||
exports.saveState = saveState;
|
||||
/**
|
||||
* Gets the value of an state set by this action's main execution.
|
||||
*
|
||||
* @param name name of the state to get
|
||||
* @returns string
|
||||
*/
|
||||
function getState(name) {
|
||||
return process.env[`STATE_${name}`] || '';
|
||||
}
|
||||
exports.getState = getState;
|
||||
//# sourceMappingURL=core.js.map
|
||||
|
||||
/***/ }),
|
||||
@@ -14277,14 +14691,11 @@ function getInputs() {
|
||||
result.ref = github.context.ref;
|
||||
result.commit = github.context.sha;
|
||||
// Some events have an unqualifed ref. For example when a PR is merged (pull_request closed event),
|
||||
// the ref is unqualifed like "master" instead of "refs/heads/master".
|
||||
// the ref is unqualifed like "main" instead of "refs/heads/main".
|
||||
if (result.commit && result.ref && !result.ref.startsWith('refs/')) {
|
||||
result.ref = `refs/heads/${result.ref}`;
|
||||
}
|
||||
}
|
||||
if (!result.ref && !result.commit) {
|
||||
result.ref = 'refs/heads/master';
|
||||
}
|
||||
}
|
||||
// SHA?
|
||||
else if (result.ref.match(/^[0-9a-fA-F]{40}$/)) {
|
||||
@@ -14319,7 +14730,7 @@ function getInputs() {
|
||||
core.debug(`submodules = ${result.submodules}`);
|
||||
core.debug(`recursive submodules = ${result.nestedSubmodules}`);
|
||||
// Auth token
|
||||
result.authToken = core.getInput('token');
|
||||
result.authToken = core.getInput('token', { required: true });
|
||||
// SSH
|
||||
result.sshKey = core.getInput('ssh-key');
|
||||
result.sshKnownHosts = core.getInput('ssh-known-hosts');
|
||||
|
||||
Generated
+45
-48
@@ -5,9 +5,9 @@
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.3.tgz",
|
||||
"integrity": "sha512-2BIib53Jh4Cfm+1XNuZYYGTeRo8yiWEAUMoliMh1qQGMaqTF4VUlhhcsBylTu4qWmUx45DrY0y0XskimAHSqhw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
||||
},
|
||||
"@actions/exec": {
|
||||
"version": "1.0.1",
|
||||
@@ -984,9 +984,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
|
||||
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
|
||||
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-globals": {
|
||||
@@ -3630,22 +3630,35 @@
|
||||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
|
||||
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"optimist": "^0.6.1",
|
||||
"source-map": "^0.6.1",
|
||||
"uglify-js": "^3.1.4"
|
||||
"uglify-js": "^3.1.4",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3727,9 +3740,9 @@
|
||||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
|
||||
"integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"html-encoding-sniffer": {
|
||||
@@ -4717,9 +4730,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
|
||||
"version": "5.7.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
|
||||
"integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -4856,9 +4869,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.get": {
|
||||
@@ -5353,16 +5366,6 @@
|
||||
"mimic-fn": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
|
||||
@@ -5490,9 +5493,9 @@
|
||||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
@@ -6573,9 +6576,9 @@
|
||||
}
|
||||
},
|
||||
"tmpl": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||
"dev": true
|
||||
},
|
||||
"to-fast-properties": {
|
||||
@@ -6971,12 +6974,6 @@
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
|
||||
"dev": true
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
|
||||
@@ -7027,9 +7024,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
|
||||
"integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
@@ -7042,9 +7039,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
|
||||
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
|
||||
+3
-3
@@ -5,8 +5,8 @@
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build && node lib/misc/generate-docs.js",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"format": "prettier --write '**/*.ts'",
|
||||
"format-check": "prettier --check '**/*.ts'",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"test": "jest"
|
||||
},
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/actions/checkout#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.1.3",
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/github": "^2.2.0",
|
||||
"@actions/io": "^1.0.1",
|
||||
|
||||
@@ -148,7 +148,7 @@ class GitAuthHelper {
|
||||
output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || []
|
||||
for (const configPath of configPaths) {
|
||||
core.debug(`Replacing token placeholder in '${configPath}'`)
|
||||
this.replaceTokenPlaceholder(configPath)
|
||||
await this.replaceTokenPlaceholder(configPath)
|
||||
}
|
||||
|
||||
if (this.settings.sshKey) {
|
||||
|
||||
+67
-16
@@ -3,6 +3,7 @@ import * as exec from '@actions/exec'
|
||||
import * as fshelper from './fs-helper'
|
||||
import * as io from '@actions/io'
|
||||
import * as path from 'path'
|
||||
import * as refHelper from './ref-helper'
|
||||
import * as regexpHelper from './regexp-helper'
|
||||
import * as retryHelper from './retry-helper'
|
||||
import {GitVersion} from './git-version'
|
||||
@@ -23,16 +24,19 @@ export interface IGitCommandManager {
|
||||
globalConfig?: boolean
|
||||
): Promise<void>
|
||||
configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||
fetch(fetchDepth: number, refSpec: string[]): Promise<void>
|
||||
fetch(refSpec: string[], fetchDepth?: number): Promise<void>
|
||||
getDefaultBranch(repositoryUrl: string): Promise<string>
|
||||
getWorkingDirectory(): string
|
||||
init(): Promise<void>
|
||||
isDetached(): Promise<boolean>
|
||||
lfsFetch(ref: string): Promise<void>
|
||||
lfsInstall(): Promise<void>
|
||||
log1(): Promise<void>
|
||||
log1(format?: string): Promise<string>
|
||||
remoteAdd(remoteName: string, remoteUrl: string): Promise<void>
|
||||
removeEnvironmentVariable(name: string): void
|
||||
revParse(ref: string): Promise<string>
|
||||
setEnvironmentVariable(name: string, value: string): void
|
||||
shaExists(sha: string): Promise<boolean>
|
||||
submoduleForeach(command: string, recursive: boolean): Promise<string>
|
||||
submoduleSync(recursive: boolean): Promise<void>
|
||||
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
|
||||
@@ -164,17 +168,14 @@ class GitCommandManager {
|
||||
return output.exitCode === 0
|
||||
}
|
||||
|
||||
async fetch(fetchDepth: number, refSpec: string[]): Promise<void> {
|
||||
const args = [
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'fetch',
|
||||
'--no-tags',
|
||||
'--prune',
|
||||
'--progress',
|
||||
'--no-recurse-submodules'
|
||||
]
|
||||
if (fetchDepth > 0) {
|
||||
async fetch(refSpec: string[], fetchDepth?: number): Promise<void> {
|
||||
const args = ['-c', 'protocol.version=2', 'fetch']
|
||||
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
|
||||
args.push('--no-tags')
|
||||
}
|
||||
|
||||
args.push('--prune', '--progress', '--no-recurse-submodules')
|
||||
if (fetchDepth && fetchDepth > 0) {
|
||||
args.push(`--depth=${fetchDepth}`)
|
||||
} else if (
|
||||
fshelper.fileExistsSync(
|
||||
@@ -195,6 +196,34 @@ class GitCommandManager {
|
||||
})
|
||||
}
|
||||
|
||||
async getDefaultBranch(repositoryUrl: string): Promise<string> {
|
||||
let output: GitOutput | undefined
|
||||
await retryHelper.execute(async () => {
|
||||
output = await this.execGit([
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
repositoryUrl,
|
||||
'HEAD'
|
||||
])
|
||||
})
|
||||
|
||||
if (output) {
|
||||
// Satisfy compiler, will always be set
|
||||
for (let line of output.stdout.trim().split('\n')) {
|
||||
line = line.trim()
|
||||
if (line.startsWith('ref:') || line.endsWith('HEAD')) {
|
||||
return line
|
||||
.substr('ref:'.length, line.length - 'ref:'.length - 'HEAD'.length)
|
||||
.trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Unexpected output when retrieving default branch')
|
||||
}
|
||||
|
||||
getWorkingDirectory(): string {
|
||||
return this.workingDirectory
|
||||
}
|
||||
@@ -225,8 +254,11 @@ class GitCommandManager {
|
||||
await this.execGit(['lfs', 'install', '--local'])
|
||||
}
|
||||
|
||||
async log1(): Promise<void> {
|
||||
await this.execGit(['log', '-1'])
|
||||
async log1(format?: string): Promise<string> {
|
||||
var args = format ? ['log', '-1', format] : ['log', '-1']
|
||||
var silent = format ? false : true
|
||||
const output = await this.execGit(args, false, silent)
|
||||
return output.stdout
|
||||
}
|
||||
|
||||
async remoteAdd(remoteName: string, remoteUrl: string): Promise<void> {
|
||||
@@ -237,10 +269,27 @@ class GitCommandManager {
|
||||
delete this.gitEnv[name]
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a ref to a SHA. For a branch or lightweight tag, the commit SHA is returned.
|
||||
* For an annotated tag, the tag SHA is returned.
|
||||
* @param {string} ref For example: 'refs/heads/main' or '/refs/tags/v1'
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async revParse(ref: string): Promise<string> {
|
||||
const output = await this.execGit(['rev-parse', ref])
|
||||
return output.stdout.trim()
|
||||
}
|
||||
|
||||
setEnvironmentVariable(name: string, value: string): void {
|
||||
this.gitEnv[name] = value
|
||||
}
|
||||
|
||||
async shaExists(sha: string): Promise<boolean> {
|
||||
const args = ['rev-parse', '--verify', '--quiet', `${sha}^{object}`]
|
||||
const output = await this.execGit(args, true)
|
||||
return output.exitCode === 0
|
||||
}
|
||||
|
||||
async submoduleForeach(command: string, recursive: boolean): Promise<string> {
|
||||
const args = ['submodule', 'foreach']
|
||||
if (recursive) {
|
||||
@@ -343,7 +392,8 @@ class GitCommandManager {
|
||||
|
||||
private async execGit(
|
||||
args: string[],
|
||||
allowAllExitCodes = false
|
||||
allowAllExitCodes = false,
|
||||
silent = false
|
||||
): Promise<GitOutput> {
|
||||
fshelper.directoryExistsSync(this.workingDirectory, true)
|
||||
|
||||
@@ -362,6 +412,7 @@ class GitCommandManager {
|
||||
const options = {
|
||||
cwd: this.workingDirectory,
|
||||
env,
|
||||
silent,
|
||||
ignoreReturnCode: allowAllExitCodes,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
|
||||
@@ -5,13 +5,13 @@ import * as fsHelper from './fs-helper'
|
||||
import * as io from '@actions/io'
|
||||
import * as path from 'path'
|
||||
import {IGitCommandManager} from './git-command-manager'
|
||||
import {IGitSourceSettings} from './git-source-settings'
|
||||
|
||||
export async function prepareExistingDirectory(
|
||||
git: IGitCommandManager | undefined,
|
||||
repositoryPath: string,
|
||||
repositoryUrl: string,
|
||||
clean: boolean
|
||||
clean: boolean,
|
||||
ref: string
|
||||
): Promise<void> {
|
||||
assert.ok(repositoryPath, 'Expected repositoryPath to be defined')
|
||||
assert.ok(repositoryUrl, 'Expected repositoryUrl to be defined')
|
||||
@@ -56,10 +56,26 @@ export async function prepareExistingDirectory(
|
||||
await git.branchDelete(false, branch)
|
||||
}
|
||||
|
||||
// Remove all refs/remotes/origin/* to avoid conflicts
|
||||
branches = await git.branchList(true)
|
||||
for (const branch of branches) {
|
||||
await git.branchDelete(true, branch)
|
||||
// Remove any conflicting refs/remotes/origin/*
|
||||
// Example 1: Consider ref is refs/heads/foo and previously fetched refs/remotes/origin/foo/bar
|
||||
// Example 2: Consider ref is refs/heads/foo/bar and previously fetched refs/remotes/origin/foo
|
||||
if (ref) {
|
||||
ref = ref.startsWith('refs/') ? ref : `refs/heads/${ref}`
|
||||
if (ref.startsWith('refs/heads/')) {
|
||||
const upperName1 = ref.toUpperCase().substr('REFS/HEADS/'.length)
|
||||
const upperName1Slash = `${upperName1}/`
|
||||
branches = await git.branchList(true)
|
||||
for (const branch of branches) {
|
||||
const upperName2 = branch.substr('origin/'.length).toUpperCase()
|
||||
const upperName2Slash = `${upperName2}/`
|
||||
if (
|
||||
upperName1.startsWith(upperName2Slash) ||
|
||||
upperName2.startsWith(upperName1Slash)
|
||||
) {
|
||||
await git.branchDelete(true, branch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
core.endGroup()
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
git,
|
||||
settings.repositoryPath,
|
||||
repositoryUrl,
|
||||
settings.clean
|
||||
settings.clean,
|
||||
settings.ref
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,6 +103,21 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
await authHelper.configureAuth()
|
||||
core.endGroup()
|
||||
|
||||
// Determine the default branch
|
||||
if (!settings.ref && !settings.commit) {
|
||||
core.startGroup('Determining the default branch')
|
||||
if (settings.sshKey) {
|
||||
settings.ref = await git.getDefaultBranch(repositoryUrl)
|
||||
} else {
|
||||
settings.ref = await githubApiHelper.getDefaultBranch(
|
||||
settings.authToken,
|
||||
settings.repositoryOwner,
|
||||
settings.repositoryName
|
||||
)
|
||||
}
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
// LFS install
|
||||
if (settings.lfs) {
|
||||
await git.lfsInstall()
|
||||
@@ -109,8 +125,24 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
|
||||
// Fetch
|
||||
core.startGroup('Fetching the repository')
|
||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||
await git.fetch(settings.fetchDepth, refSpec)
|
||||
if (settings.fetchDepth <= 0) {
|
||||
// Fetch all branches and tags
|
||||
let refSpec = refHelper.getRefSpecForAllHistory(
|
||||
settings.ref,
|
||||
settings.commit
|
||||
)
|
||||
await git.fetch(refSpec)
|
||||
|
||||
// When all history is fetched, the ref we're interested in may have moved to a different
|
||||
// commit (push or force push). If so, fetch again with a targeted refspec.
|
||||
if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
|
||||
refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||
await git.fetch(refSpec)
|
||||
}
|
||||
} else {
|
||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||
await git.fetch(refSpec, settings.fetchDepth)
|
||||
}
|
||||
core.endGroup()
|
||||
|
||||
// Checkout info
|
||||
@@ -169,8 +201,21 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// Dump some info about the checked out commit
|
||||
await git.log1()
|
||||
// Get commit information
|
||||
const commitInfo = await git.log1()
|
||||
|
||||
// Log commit sha
|
||||
await git.log1("--format='%H'")
|
||||
|
||||
// Check for incorrect pull request merge commit
|
||||
await refHelper.checkCommitInfo(
|
||||
settings.authToken,
|
||||
commitInfo,
|
||||
settings.repositoryOwner,
|
||||
settings.repositoryName,
|
||||
settings.ref,
|
||||
settings.commit
|
||||
)
|
||||
} finally {
|
||||
// Remove auth
|
||||
if (!settings.persistCredentials) {
|
||||
|
||||
@@ -19,6 +19,12 @@ export async function downloadRepository(
|
||||
commit: string,
|
||||
repositoryPath: string
|
||||
): Promise<void> {
|
||||
// Determine the default branch
|
||||
if (!ref && !commit) {
|
||||
core.info('Determining the default branch')
|
||||
ref = await getDefaultBranch(authToken, owner, repo)
|
||||
}
|
||||
|
||||
// Download the archive
|
||||
let archiveData = await retryHelper.execute(async () => {
|
||||
core.info('Downloading the archive')
|
||||
@@ -41,7 +47,7 @@ export async function downloadRepository(
|
||||
} else {
|
||||
await toolCache.extractTar(archivePath, extractPath)
|
||||
}
|
||||
io.rmRF(archivePath)
|
||||
await io.rmRF(archivePath)
|
||||
|
||||
// Determine the path of the repository content. The archive contains
|
||||
// a top-level folder and the repository content is inside.
|
||||
@@ -64,7 +70,47 @@ export async function downloadRepository(
|
||||
await io.mv(sourcePath, targetPath)
|
||||
}
|
||||
}
|
||||
io.rmRF(extractPath)
|
||||
await io.rmRF(extractPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the default branch name
|
||||
*/
|
||||
export async function getDefaultBranch(
|
||||
authToken: string,
|
||||
owner: string,
|
||||
repo: string
|
||||
): Promise<string> {
|
||||
return await retryHelper.execute(async () => {
|
||||
core.info('Retrieving the default branch name')
|
||||
const octokit = new github.GitHub(authToken)
|
||||
let result: string
|
||||
try {
|
||||
// Get the default branch from the repo info
|
||||
const response = await octokit.repos.get({owner, repo})
|
||||
result = response.data.default_branch
|
||||
assert.ok(result, 'default_branch cannot be empty')
|
||||
} catch (err) {
|
||||
// Handle .wiki repo
|
||||
if (err['status'] === 404 && repo.toUpperCase().endsWith('.WIKI')) {
|
||||
result = 'master'
|
||||
}
|
||||
// Otherwise error
|
||||
else {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Print the default branch
|
||||
core.info(`Default branch '${result}'`)
|
||||
|
||||
// Prefix with 'refs/heads'
|
||||
if (!result.startsWith('refs/')) {
|
||||
result = `refs/heads/${result}`
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
async function downloadArchive(
|
||||
|
||||
+2
-6
@@ -63,15 +63,11 @@ export function getInputs(): IGitSourceSettings {
|
||||
result.commit = github.context.sha
|
||||
|
||||
// Some events have an unqualifed ref. For example when a PR is merged (pull_request closed event),
|
||||
// the ref is unqualifed like "master" instead of "refs/heads/master".
|
||||
// the ref is unqualifed like "main" instead of "refs/heads/main".
|
||||
if (result.commit && result.ref && !result.ref.startsWith('refs/')) {
|
||||
result.ref = `refs/heads/${result.ref}`
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.ref && !result.commit) {
|
||||
result.ref = 'refs/heads/master'
|
||||
}
|
||||
}
|
||||
// SHA?
|
||||
else if (result.ref.match(/^[0-9a-fA-F]{40}$/)) {
|
||||
@@ -110,7 +106,7 @@ export function getInputs(): IGitSourceSettings {
|
||||
core.debug(`recursive submodules = ${result.nestedSubmodules}`)
|
||||
|
||||
// Auth token
|
||||
result.authToken = core.getInput('token')
|
||||
result.authToken = core.getInput('token', {required: true})
|
||||
|
||||
// SSH
|
||||
result.sshKey = core.getInput('ssh-key')
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import {URL} from 'url'
|
||||
import {IGitCommandManager} from './git-command-manager'
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
|
||||
export const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
||||
|
||||
export interface ICheckoutInfo {
|
||||
ref: string
|
||||
@@ -57,6 +62,16 @@ export async function getCheckoutInfo(
|
||||
return result
|
||||
}
|
||||
|
||||
export function getRefSpecForAllHistory(ref: string, commit: string): string[] {
|
||||
const result = ['+refs/heads/*:refs/remotes/origin/*', tagsRefSpec]
|
||||
if (ref && ref.toUpperCase().startsWith('REFS/PULL/')) {
|
||||
const branch = ref.substring('refs/pull/'.length)
|
||||
result.push(`+${commit || ref}:refs/remotes/pull/${branch}`)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export function getRefSpec(ref: string, commit: string): string[] {
|
||||
if (!ref && !commit) {
|
||||
throw new Error('Args ref and commit cannot both be empty')
|
||||
@@ -107,3 +122,162 @@ export function getRefSpec(ref: string, commit: string): string[] {
|
||||
return [`+${ref}:${ref}`]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the initial fetch created the ref at the expected commit
|
||||
*/
|
||||
export async function testRef(
|
||||
git: IGitCommandManager,
|
||||
ref: string,
|
||||
commit: string
|
||||
): Promise<boolean> {
|
||||
if (!git) {
|
||||
throw new Error('Arg git cannot be empty')
|
||||
}
|
||||
|
||||
if (!ref && !commit) {
|
||||
throw new Error('Args ref and commit cannot both be empty')
|
||||
}
|
||||
|
||||
// No SHA? Nothing to test
|
||||
if (!commit) {
|
||||
return true
|
||||
}
|
||||
// SHA only?
|
||||
else if (!ref) {
|
||||
return await git.shaExists(commit)
|
||||
}
|
||||
|
||||
const upperRef = ref.toUpperCase()
|
||||
|
||||
// refs/heads/
|
||||
if (upperRef.startsWith('REFS/HEADS/')) {
|
||||
const branch = ref.substring('refs/heads/'.length)
|
||||
return (
|
||||
(await git.branchExists(true, `origin/${branch}`)) &&
|
||||
commit === (await git.revParse(`refs/remotes/origin/${branch}`))
|
||||
)
|
||||
}
|
||||
// refs/pull/
|
||||
else if (upperRef.startsWith('REFS/PULL/')) {
|
||||
// Assume matches because fetched using the commit
|
||||
return true
|
||||
}
|
||||
// refs/tags/
|
||||
else if (upperRef.startsWith('REFS/TAGS/')) {
|
||||
const tagName = ref.substring('refs/tags/'.length)
|
||||
return (
|
||||
(await git.tagExists(tagName)) && commit === (await git.revParse(ref))
|
||||
)
|
||||
}
|
||||
// Unexpected
|
||||
else {
|
||||
core.debug(`Unexpected ref format '${ref}' when testing ref info`)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export async function checkCommitInfo(
|
||||
token: string,
|
||||
commitInfo: string,
|
||||
repositoryOwner: string,
|
||||
repositoryName: string,
|
||||
ref: string,
|
||||
commit: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
// GHES?
|
||||
if (isGhes()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Auth token?
|
||||
if (!token) {
|
||||
return
|
||||
}
|
||||
|
||||
// Public PR synchronize, for workflow repo?
|
||||
if (
|
||||
fromPayload('repository.private') !== false ||
|
||||
github.context.eventName !== 'pull_request' ||
|
||||
fromPayload('action') !== 'synchronize' ||
|
||||
repositoryOwner !== github.context.repo.owner ||
|
||||
repositoryName !== github.context.repo.repo ||
|
||||
ref !== github.context.ref ||
|
||||
!ref.startsWith('refs/pull/') ||
|
||||
commit !== github.context.sha
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// Head SHA
|
||||
const expectedHeadSha = fromPayload('after')
|
||||
if (!expectedHeadSha) {
|
||||
core.debug('Unable to determine head sha')
|
||||
return
|
||||
}
|
||||
|
||||
// Base SHA
|
||||
const expectedBaseSha = fromPayload('pull_request.base.sha')
|
||||
if (!expectedBaseSha) {
|
||||
core.debug('Unable to determine base sha')
|
||||
return
|
||||
}
|
||||
|
||||
// Expected message?
|
||||
const expectedMessage = `Merge ${expectedHeadSha} into ${expectedBaseSha}`
|
||||
if (commitInfo.indexOf(expectedMessage) >= 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Extract details from message
|
||||
const match = commitInfo.match(/Merge ([0-9a-f]{40}) into ([0-9a-f]{40})/)
|
||||
if (!match) {
|
||||
core.debug('Unexpected message format')
|
||||
return
|
||||
}
|
||||
|
||||
// Post telemetry
|
||||
const actualHeadSha = match[1]
|
||||
if (actualHeadSha !== expectedHeadSha) {
|
||||
core.debug(
|
||||
`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`
|
||||
)
|
||||
const octokit = new github.GitHub(token, {
|
||||
userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload(
|
||||
'number'
|
||||
)};run_id=${
|
||||
process.env['GITHUB_RUN_ID']
|
||||
};expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})`
|
||||
})
|
||||
await octokit.repos.get({owner: repositoryOwner, repo: repositoryName})
|
||||
}
|
||||
} catch (err) {
|
||||
core.debug(`Error when validating commit info: ${err.stack}`)
|
||||
}
|
||||
}
|
||||
|
||||
function fromPayload(path: string): any {
|
||||
return select(github.context.payload, path)
|
||||
}
|
||||
|
||||
function select(obj: any, path: string): any {
|
||||
if (!obj) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const i = path.indexOf('.')
|
||||
if (i < 0) {
|
||||
return obj[path]
|
||||
}
|
||||
|
||||
const key = path.substr(0, i)
|
||||
return select(obj[key], path.substr(i + 1))
|
||||
}
|
||||
|
||||
function isGhes(): boolean {
|
||||
const ghUrl = new URL(
|
||||
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
|
||||
)
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user