mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
67 Commits
Duplicated
...
v2.309.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdfef34557 | ||
|
|
2617455be7 | ||
|
|
7b703d667d | ||
|
|
d2f0a46865 | ||
|
|
143639ddac | ||
|
|
474d0fb354 | ||
|
|
15c0fe6c1d | ||
|
|
2b66cbe699 | ||
|
|
0e9e9f1e8d | ||
|
|
be65955a9d | ||
|
|
e419ae3c7e | ||
|
|
bb40cd2788 | ||
|
|
e0acb14bfc | ||
|
|
1ff8ad7860 | ||
|
|
8dd2cec3af | ||
|
|
7b53c38294 | ||
|
|
e22452c2d6 | ||
|
|
9bbfed0740 | ||
|
|
cf5afc63da | ||
|
|
a00db53b0d | ||
|
|
73ef82ff85 | ||
|
|
7892066256 | ||
|
|
8b9a81c952 | ||
|
|
460d9ae5a8 | ||
|
|
e94e744bed | ||
|
|
94080812f7 | ||
|
|
1183100ab8 | ||
|
|
4f40f29cff | ||
|
|
d88823c634 | ||
|
|
a8783c023f | ||
|
|
2606425cc5 | ||
|
|
8fb038b0e0 | ||
|
|
8b30f9381b | ||
|
|
8206cf4e73 | ||
|
|
6680a3b142 | ||
|
|
b882f6696a | ||
|
|
e76de55cda | ||
|
|
9eb4b96713 | ||
|
|
719348e0bf | ||
|
|
9fe5aa2a9a | ||
|
|
765a5c3efc | ||
|
|
e752edf7b5 | ||
|
|
e350f35217 | ||
|
|
8fa970a1e6 | ||
|
|
8eefd849c1 | ||
|
|
f6e9809844 | ||
|
|
5b2e4049bc | ||
|
|
7cb61925b0 | ||
|
|
a61d3f37dc | ||
|
|
e30b9d6d12 | ||
|
|
496904c0b7 | ||
|
|
b91ad56f92 | ||
|
|
f25c9dfba3 | ||
|
|
7d432fb24c | ||
|
|
e8ee6f7b1b | ||
|
|
d4bbbb8419 | ||
|
|
4ffd081aea | ||
|
|
c05e6748c3 | ||
|
|
a2b7856c9c | ||
|
|
5f1c6f4708 | ||
|
|
8415f13bab | ||
|
|
471e3ae2d9 | ||
|
|
1096b975e4 | ||
|
|
282ba4cfc8 | ||
|
|
b737a5ac5c | ||
|
|
20721bc950 | ||
|
|
fde86b0666 |
@@ -1,11 +1,10 @@
|
|||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
|
||||||
{
|
{
|
||||||
"name": "Actions Runner Devcontainer",
|
"name": "Actions Runner Devcontainer",
|
||||||
"image": "mcr.microsoft.com/devcontainers/base:focal",
|
"image": "mcr.microsoft.com/devcontainers/base:focal",
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/docker-in-docker:1": {},
|
"ghcr.io/devcontainers/features/docker-in-docker:1": {},
|
||||||
"ghcr.io/devcontainers/features/dotnet": {
|
"ghcr.io/devcontainers/features/dotnet": {
|
||||||
"version": "6.0.405"
|
"version": "6.0.412"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "16"
|
"version": "16"
|
||||||
@@ -20,8 +19,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// dotnet restore to install dependencies so OmniSharp works out of the box
|
|
||||||
// src/Test restores all other projects it references, src/Runner.PluginHost is not one of them
|
|
||||||
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost",
|
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost",
|
||||||
"remoteUser": "vscode"
|
"remoteUser": "vscode"
|
||||||
}
|
}
|
||||||
20
.github/dependabot.yml
vendored
Normal file
20
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "docker"
|
||||||
|
directory: "/images"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
target-branch: "main"
|
||||||
|
- package-ecosystem: "nuget"
|
||||||
|
directory: "/src"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
target-branch: "main"
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/src/Misc/expressionFunc/hashFiles"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
target-branch: "main"
|
||||||
|
allow:
|
||||||
|
- dependency-type: direct
|
||||||
|
- dependency-type: production # check only dependencies, which are going to the compiled app, not supporting tools like @vue-cli
|
||||||
306
.github/workflows/dotnet-upgrade.yml
vendored
Normal file
306
.github/workflows/dotnet-upgrade.yml
vendored
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
name: "DotNet SDK Upgrade"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 1'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dotnet-update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
SHOULD_UPDATE: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE }}
|
||||||
|
BRANCH_EXISTS: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS }}
|
||||||
|
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Get current major minor version
|
||||||
|
id: fetch_current_version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
current_major_minor_patch_version=$(jq .sdk.version ./src/global.json | xargs)
|
||||||
|
current_major_minor_version=$(cut -d '.' -f 1,2 <<< "$current_major_minor_patch_version")
|
||||||
|
|
||||||
|
echo "DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION=${current_major_minor_patch_version}" >> $GITHUB_OUTPUT
|
||||||
|
echo "DOTNET_CURRENT_MAJOR_MINOR_VERSION=${current_major_minor_version}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Check patch version
|
||||||
|
id: fetch_latest_version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
latest_patch_version=$(curl -sb -H "Accept: application/json" "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version")
|
||||||
|
current_patch_version=${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
|
||||||
|
should_update=0
|
||||||
|
[ "$current_patch_version" != "$latest_patch_version" ] && should_update=1
|
||||||
|
|
||||||
|
# check if git branch already exists for the upgrade
|
||||||
|
branch_already_exists=0
|
||||||
|
|
||||||
|
if git ls-remote --heads --exit-code origin refs/heads/feature/dotnetsdk-upgrade/${latest_patch_version};
|
||||||
|
then
|
||||||
|
branch_already_exists=1
|
||||||
|
should_update=0
|
||||||
|
fi
|
||||||
|
echo "DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION=${latest_patch_version}" >> $GITHUB_OUTPUT
|
||||||
|
echo "SHOULD_UPDATE=${should_update}" >> $GITHUB_OUTPUT
|
||||||
|
echo "BRANCH_EXISTS=${branch_already_exists}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Create an error annotation if branch exists
|
||||||
|
if: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS == 1 }}
|
||||||
|
run: echo "::error links::feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} https://github.com/actions/runner/tree/feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}::Branch feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} already exists. Please take a look and delete that branch if you wish to recreate"
|
||||||
|
- name: Create a warning annotation if no need to update
|
||||||
|
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 0 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
||||||
|
run: echo "::warning ::Latest DotNet SDK patch is ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}, and we are on ${{ steps.fetch_latest_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}. No need to update"
|
||||||
|
- name: Update patch version
|
||||||
|
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
patch_version="${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
||||||
|
current_version="${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}"
|
||||||
|
|
||||||
|
# Update globals
|
||||||
|
echo Updating globals
|
||||||
|
globals_temp=$(mktemp)
|
||||||
|
jq --unbuffered --arg patch_version "$patch_version" '.sdk.version = $patch_version' ./src/global.json > "$globals_temp" && mv "$globals_temp" ./src/global.json
|
||||||
|
|
||||||
|
# Update devcontainer
|
||||||
|
echo Updating devcontainer
|
||||||
|
devcontainer_temp=$(mktemp)
|
||||||
|
jq --unbuffered --arg patch_version "$patch_version" '.features."ghcr.io/devcontainers/features/dotnet".version = $patch_version' ./.devcontainer/devcontainer.json > "$devcontainer_temp" && mv "$devcontainer_temp" ./.devcontainer/devcontainer.json
|
||||||
|
|
||||||
|
# Update dev.sh
|
||||||
|
echo Updating start script
|
||||||
|
sed -i "s/DOTNETSDK_VERSION=\"$current_version\"/DOTNETSDK_VERSION=\"$patch_version\"/g" ./src/dev.sh
|
||||||
|
- name: GIT commit and push all changed files
|
||||||
|
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
||||||
|
id: create_branch
|
||||||
|
run: |
|
||||||
|
branch_name="feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
||||||
|
|
||||||
|
git checkout -b $branch_name
|
||||||
|
git commit -a -m "Upgrade dotnet sdk to v${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
||||||
|
git push --set-upstream origin $branch_name
|
||||||
|
|
||||||
|
build-hashes:
|
||||||
|
if: ${{ needs.dotnet-update.outputs.SHOULD_UPDATE == 1 && needs.dotnet-update.outputs.BRANCH_EXISTS == 0 }}
|
||||||
|
needs: [dotnet-update]
|
||||||
|
outputs:
|
||||||
|
# pass outputs from this job to create-pr for use
|
||||||
|
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ needs.dotnet-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
||||||
|
NEEDS_HASH_UPDATE: ${{ steps.compute-hash.outputs.NEED_UPDATE }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ]
|
||||||
|
include:
|
||||||
|
- runtime: linux-x64
|
||||||
|
os: ubuntu-latest
|
||||||
|
devScript: ./dev.sh
|
||||||
|
|
||||||
|
- runtime: linux-arm64
|
||||||
|
os: ubuntu-latest
|
||||||
|
devScript: ./dev.sh
|
||||||
|
|
||||||
|
- runtime: linux-arm
|
||||||
|
os: ubuntu-latest
|
||||||
|
devScript: ./dev.sh
|
||||||
|
|
||||||
|
- runtime: osx-x64
|
||||||
|
os: macOS-latest
|
||||||
|
devScript: ./dev.sh
|
||||||
|
|
||||||
|
- runtime: osx-arm64
|
||||||
|
os: macOS-latest
|
||||||
|
devScript: ./dev.sh
|
||||||
|
|
||||||
|
- runtime: win-x64
|
||||||
|
os: windows-2019
|
||||||
|
devScript: ./dev
|
||||||
|
|
||||||
|
- runtime: win-arm64
|
||||||
|
os: windows-latest
|
||||||
|
devScript: ./dev
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
|
||||||
|
# Build runner layout
|
||||||
|
- name: Build & Layout Release
|
||||||
|
run: |
|
||||||
|
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||||
|
working-directory: src
|
||||||
|
|
||||||
|
# Check runtime/externals hash
|
||||||
|
- name: Compute/Compare runtime and externals Hash
|
||||||
|
id: compute-hash
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Current dotnet runtime hash result: $DOTNET_RUNTIME_HASH"
|
||||||
|
echo "Current Externals hash result: $EXTERNALS_HASH"
|
||||||
|
|
||||||
|
NeedUpdate=0
|
||||||
|
if [ "$EXTERNALS_HASH" != "$(cat ./src/Misc/contentHash/externals/${{ matrix.runtime }})" ] ;then
|
||||||
|
echo Hash mismatch, Update ./src/Misc/contentHash/externals/${{ matrix.runtime }} to $EXTERNALS_HASH
|
||||||
|
|
||||||
|
echo "EXTERNAL_HASH=$EXTERNALS_HASH" >> $GITHUB_OUTPUT
|
||||||
|
NeedUpdate=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DOTNET_RUNTIME_HASH" != "$(cat ./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }})" ] ;then
|
||||||
|
echo Hash mismatch, Update ./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }} to $DOTNET_RUNTIME_HASH
|
||||||
|
|
||||||
|
echo "DOTNET_RUNTIME_HASH=$DOTNET_RUNTIME_HASH" >> $GITHUB_OUTPUT
|
||||||
|
NeedUpdate=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "NEED_UPDATE=$NeedUpdate" >> $GITHUB_OUTPUT
|
||||||
|
env:
|
||||||
|
DOTNET_RUNTIME_HASH: ${{hashFiles('**/_layout_trims/runtime/**/*')}}
|
||||||
|
EXTERNALS_HASH: ${{hashFiles('**/_layout_trims/externals/**/*')}}
|
||||||
|
- name: update hash
|
||||||
|
if: ${{ steps.compute-hash.outputs.NEED_UPDATE == 1 }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
ExternalHash=${{ steps.compute-hash.outputs.EXTERNAL_HASH }}
|
||||||
|
DotNetRuntimeHash=${{ steps.compute-hash.outputs.DOTNET_RUNTIME_HASH }}
|
||||||
|
|
||||||
|
if [ -n "$ExternalHash" ]; then
|
||||||
|
echo "$ExternalHash" > ./src/Misc/contentHash/externals/${{ matrix.runtime }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$DotNetRuntimeHash" ]; then
|
||||||
|
echo "$DotNetRuntimeHash" > ./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }}
|
||||||
|
fi
|
||||||
|
- name: cache updated hashes
|
||||||
|
if: ${{ steps.compute-hash.outputs.NEED_UPDATE == 1 }}
|
||||||
|
uses: actions/cache/save@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/${{ matrix.runtime }}
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }}
|
||||||
|
key: compute-hashes-${{ matrix.runtime }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
|
||||||
|
|
||||||
|
hash-update:
|
||||||
|
needs: [build-hashes]
|
||||||
|
if: ${{ needs.build-hashes.outputs.NEEDS_HASH_UPDATE == 1 }}
|
||||||
|
outputs:
|
||||||
|
# pass outputs from this job to create-pr for use
|
||||||
|
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ needs.build-hashes.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ needs.build-hashes.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: feature/dotnetsdk-upgrade/${{ needs.build-hashes.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
- name: Restore cached hashes - linux-x64
|
||||||
|
id: cache-restore-linux-x64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/linux-x64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/linux-x64
|
||||||
|
key: compute-hashes-linux-x64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - linux-arm64
|
||||||
|
id: cache-restore-linux-arm64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/linux-arm64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/linux-arm64
|
||||||
|
key: compute-hashes-linux-arm64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - linux-arm
|
||||||
|
id: cache-restore-linux-arm
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/linux-arm
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/linux-arm
|
||||||
|
key: compute-hashes-linux-arm-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - osx-x64
|
||||||
|
id: cache-restore-osx-x64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/osx-x64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/osx-x64
|
||||||
|
key: compute-hashes-osx-x64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - osx-arm64
|
||||||
|
id: cache-restore-osx-arm64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/osx-arm64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/osx-arm64
|
||||||
|
key: compute-hashes-osx-arm64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - win-x64
|
||||||
|
id: cache-restore-win-x64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/win-x64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/win-x64
|
||||||
|
key: compute-hashes-win-x64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Restore cached hashes - win-arm64
|
||||||
|
id: cache-restore-win-arm64
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
path: |
|
||||||
|
./src/Misc/contentHash/externals/win-arm64
|
||||||
|
./src/Misc/contentHash/dotnetRuntime/win-arm64
|
||||||
|
key: compute-hashes-win-arm64-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||||
|
- name: Fetch cached computed hashes
|
||||||
|
if: steps.cache-restore-linux-x64.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-linux-arm64.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-linux-arm.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-win-x64.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-win-arm64.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-osx-x64.outputs.cache-hit == 'true' ||
|
||||||
|
steps.cache-restore-osx-arm64.outputs.cache-hit == 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
Environments=( "linux-x64" "linux-arm64" "linux-arm" "win-x64" "win-arm64" "osx-x64" "osx-arm64" )
|
||||||
|
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git commit -a -m "Update computed hashes"
|
||||||
|
git push --set-upstream origin feature/dotnetsdk-upgrade/${{ needs.build-hashes.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
|
||||||
|
create-pr:
|
||||||
|
needs: [hash-update]
|
||||||
|
outputs:
|
||||||
|
# pass outputs from this job to run-tests for use
|
||||||
|
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ needs.hash-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ needs.hash-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: feature/dotnetsdk-upgrade/${{ needs.hash-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
||||||
|
- name: Create Pull Request
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
gh pr create -B main -H feature/dotnetsdk-upgrade/${{ needs.hash-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} --title "Update dotnet sdk to latest version @${{ needs.hash-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}" --body "
|
||||||
|
https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ needs.hash-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Autogenerated by [DotNet SDK Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/dotnet-upgrade.yml)"
|
||||||
3
.github/workflows/publish-image.yml
vendored
3
.github/workflows/publish-image.yml
vendored
@@ -53,6 +53,9 @@ jobs:
|
|||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: ./images
|
context: ./images
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
|||||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -699,6 +699,9 @@ jobs:
|
|||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: ./images
|
context: ./images
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
|||||||
17
.github/workflows/stale-bot.yml
vendored
Normal file
17
.github/workflows/stale-bot.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: ‘Close stale Runner issues’
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 1' # every monday at midnight
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v8
|
||||||
|
with:
|
||||||
|
stale-issue-message: ‘This issue is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 15 days.’
|
||||||
|
close-issue-message: ‘This issue was closed because it has been stalled for 15 days with no activity.’
|
||||||
|
exempt-issue-labels: ‘keep’
|
||||||
|
days-before-stale: 365
|
||||||
|
days-before-close: 15
|
||||||
|
debug-only: true
|
||||||
6
.husky/pre-commit
Executable file
6
.husky/pre-commit
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
cd src/Misc/expressionFunc/hashFiles
|
||||||
|
|
||||||
|
npx lint-staged
|
||||||
@@ -9,6 +9,8 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
- The runner needs to access `https://api.github.com` for downloading actions.
|
- The runner needs to access `https://api.github.com` for downloading actions.
|
||||||
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
||||||
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
||||||
|
---
|
||||||
|
**NOTE:** for the full list of domains that are required to be in the firewall allow list refer to the [GitHub self-hosted runners requirements documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github).
|
||||||
|
|
||||||
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
- A Proxy may try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
- A Proxy may try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
||||||
|
|
||||||
- Firewall rules that block action runner from accessing certain hosts, ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
|
- Firewall rules that block action runner from accessing [certain hosts](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github), ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
|
||||||
|
|
||||||
|
|
||||||
### Identify and solve these problems
|
### Identify and solve these problems
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
|
# Source: https://github.com/dotnet/dotnet-docker
|
||||||
|
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy as build
|
||||||
|
|
||||||
|
ARG TARGETOS
|
||||||
|
ARG TARGETARCH
|
||||||
ARG RUNNER_VERSION
|
ARG RUNNER_VERSION
|
||||||
ARG RUNNER_ARCH="x64"
|
|
||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.2
|
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.2
|
||||||
ARG DOCKER_VERSION=20.10.23
|
ARG DOCKER_VERSION=23.0.6
|
||||||
|
|
||||||
RUN apt update -y && apt install curl unzip -y
|
RUN apt update -y && apt install curl unzip -y
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
WORKDIR /actions-runner
|
||||||
RUN curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
RUN export RUNNER_ARCH=${TARGETARCH} \
|
||||||
|
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export RUNNER_ARCH=x64 ; fi \
|
||||||
|
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-${TARGETOS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
||||||
&& tar xzf ./runner.tar.gz \
|
&& tar xzf ./runner.tar.gz \
|
||||||
&& rm runner.tar.gz
|
&& rm runner.tar.gz
|
||||||
|
|
||||||
@@ -16,13 +20,14 @@ RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-c
|
|||||||
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
||||||
&& rm runner-container-hooks.zip
|
&& rm runner-container-hooks.zip
|
||||||
|
|
||||||
RUN export DOCKER_ARCH=x86_64 \
|
RUN export RUNNER_ARCH=${TARGETARCH} \
|
||||||
|
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
|
||||||
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
|
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
|
||||||
&& curl -fLo docker.tgz https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
|
&& curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
|
||||||
&& tar zxvf docker.tgz \
|
&& tar zxvf docker.tgz \
|
||||||
&& rm -rf docker.tgz
|
&& rm -rf docker.tgz
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0
|
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
ENV RUNNER_MANUALLY_TRAP_SIG=1
|
ENV RUNNER_MANUALLY_TRAP_SIG=1
|
||||||
@@ -31,6 +36,7 @@ ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
|
|||||||
RUN apt-get update -y \
|
RUN apt-get update -y \
|
||||||
&& apt-get install -y --no-install-recommends \
|
&& apt-get install -y --no-install-recommends \
|
||||||
sudo \
|
sudo \
|
||||||
|
lsb-release \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
|
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
|
||||||
|
|||||||
@@ -1,18 +1,37 @@
|
|||||||
## Features
|
## What's Changed
|
||||||
- Runner changes for communication with Results service (#2510, #2531, #2535, #2516)
|
* Bump @types/node from 12.12.14 to 20.4.10 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2759
|
||||||
- Add `*.ghe.localhost` domains to hosted server check (#2536)
|
* Trace x-github-request-id when download action tarball. by @TingluoHuang in https://github.com/actions/runner/pull/2755
|
||||||
- Add `OrchestrationId` to user-agent for better telemetry correlation. (#2568)
|
* Fix typo by @kyanny in https://github.com/actions/runner/pull/2741
|
||||||
|
* Bump prettier from 3.0.1 to 3.0.2 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2772
|
||||||
|
* Bump @types/node from 20.4.10 to 20.5.0 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2773
|
||||||
|
* Revert "Fixed a bug where a misplaced `=` character could bypass here… by @cory-miller in https://github.com/actions/runner/pull/2774
|
||||||
|
* Filter NODE_OPTIONS from env for file output by @cory-miller in https://github.com/actions/runner/pull/2775
|
||||||
|
* Bump @types/node from 20.5.0 to 20.5.1 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2781
|
||||||
|
* Update Docker Version in Images by @ajschmidt8 in https://github.com/actions/runner/pull/2694
|
||||||
|
* Bump @types/node from 20.5.1 to 20.5.4 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2789
|
||||||
|
* Bump @typescript-eslint/parser from 6.4.0 to 6.4.1 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2785
|
||||||
|
* Bump Microsoft.AspNet.WebApi.Client from 5.2.4 to 5.2.9 in /src by @dependabot in https://github.com/actions/runner/pull/2751
|
||||||
|
* Bump System.Buffers from 4.3.0 to 4.5.1 in /src by @dependabot in https://github.com/actions/runner/pull/2749
|
||||||
|
* Bump dotnet/runtime-deps from 6.0-jammy to 7.0-jammy in /images by @dependabot in https://github.com/actions/runner/pull/2745
|
||||||
|
* Remove need to manually compile JS binary for hashFiles utility by @vanZeben in https://github.com/actions/runner/pull/2770
|
||||||
|
* Revert "Bump dotnet/runtime-deps from 6.0-jammy to 7.0-jammy in /images" by @TingluoHuang in https://github.com/actions/runner/pull/2790
|
||||||
|
* Query runner by name on server side. by @TingluoHuang in https://github.com/actions/runner/pull/2771
|
||||||
|
* Bump typescript from 5.1.6 to 5.2.2 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2795
|
||||||
|
* Bump @types/node from 20.5.4 to 20.5.6 in /src/Misc/expressionFunc/hashFiles by @dependabot in https://github.com/actions/runner/pull/2796
|
||||||
|
* Bump Newtonsoft.Json from 13.0.1 to 13.0.3 in /src by @dependabot in https://github.com/actions/runner/pull/2797
|
||||||
|
* Support replacing runners in v2 flow by @luketomlinson in https://github.com/actions/runner/pull/2791
|
||||||
|
* Delegating handler for Http redirects by @paveliak in https://github.com/actions/runner/pull/2814
|
||||||
|
* Add references to the firewall requirements docs by @paveliak in https://github.com/actions/runner/pull/2815
|
||||||
|
* Create automated workflow that will auto-generate dotnet sdk patches by @vanZeben in https://github.com/actions/runner/pull/2776
|
||||||
|
* Fixes minor issues with using proper output varaibles by @vanZeben in https://github.com/actions/runner/pull/2818
|
||||||
|
* Throw NonRetryableException on GetNextMessage from broker as needed. by @TingluoHuang in https://github.com/actions/runner/pull/2828
|
||||||
|
* Mark action download failures as infra failures by @cory-miller in https://github.com/actions/runner/pull/2827
|
||||||
|
|
||||||
## Bugs
|
## New Contributors
|
||||||
- Fix JIT configurations on Windows (#2497)
|
* @kyanny made their first contribution in https://github.com/actions/runner/pull/2741
|
||||||
- Guard against NullReference while creating HostContext (#2343)
|
* @ajschmidt8 made their first contribution in https://github.com/actions/runner/pull/2694
|
||||||
- Handles broken symlink in `Which` (#2150, #2196)
|
|
||||||
- Adding curl retry for external tool downloads (#2552, #2557)
|
|
||||||
- Limit the time we wait for waiting websocket to connect. (#2554)
|
|
||||||
|
|
||||||
## Misc
|
**Full Changelog**: https://github.com/actions/runner/compare/v2.308.0...v2.309.0
|
||||||
- Bump container hooks version to 0.3.1 in runner image (#2496)
|
|
||||||
- Runner changes to communicate with vNext services (#2487, #2500, #2505, #2541, #2547)
|
|
||||||
|
|
||||||
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
||||||
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<Update to ./src/runnerversion when creating release>
|
2.309.0
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
39f2a931565d6a10e695ac8ed14bb9dcbb568151410349b32dbf9c27bae29602
|
7b78ca2997fbe048642d3717ab7321cdd359752b97158f3c67eb3df8786e21d3
|
||||||
@@ -1 +1 @@
|
|||||||
29ffb303537d8ba674fbebc7729292c21c4ebd17b3198f91ed593ef4cbbb67b5
|
6f34c1d501c87c2e22c2278df7152999aca628c66ee4176d32325773487da6d7
|
||||||
@@ -1 +1 @@
|
|||||||
de6868a836fa3cb9e5ddddbc079da1c25e819aa2d2fc193cc9931c353687c57c
|
921ca58050be56e0b84af05e544cab4a151cb66405e815e19c0e0928ef7313f5
|
||||||
@@ -1 +1 @@
|
|||||||
339d3e1a5fd28450c0fe6cb820cc7aae291f0f9e2d153ac34e1f7b080e35d30e
|
50f5c147074fc4943b4198b2d9b57c5e94344ab21350b0880ec8e2b85d27152b
|
||||||
@@ -1 +1 @@
|
|||||||
dcb7f606c1d7d290381e5020ee73e7f16dcbd2f20ac9b431362ccbb5120d449c
|
16269548335b1f2add41a409aa3558c56581b63f280a9a26956707b6370558bd
|
||||||
@@ -1 +1 @@
|
|||||||
1bbcb0e9a2cf4be4b1fce77458de139b70ac58efcbb415a6db028b9373ae1673
|
e4aa6003ec77a2b21f3021927fed48727bde379fafff300f39565ff2fff4dd87
|
||||||
@@ -1 +1 @@
|
|||||||
44cd25f3c104d0abb44d262397a80e0b2c4f206465c5d899a22eec043dac0fb3
|
16ab4c166c58bc4c5600ff055be7ce0a9bb0dd993388114a76efea51e4ea14cb
|
||||||
2
src/Misc/contentHash/externals/linux-arm
vendored
2
src/Misc/contentHash/externals/linux-arm
vendored
@@ -1 +1 @@
|
|||||||
3807dcbf947e840c33535fb466b096d76bf09e5c0254af8fc8cbbb24c6388222
|
5bdddd32bab1e57af252b470579083049496e9e39b6e4f50de01232581f9a2d8
|
||||||
2
src/Misc/contentHash/externals/linux-arm64
vendored
2
src/Misc/contentHash/externals/linux-arm64
vendored
@@ -1 +1 @@
|
|||||||
ee01eee80cd8a460a4b9780ee13fdd20f25c59e754b4ccd99df55fbba2a85634
|
54b3b3a72da93db0fa38708c759fceadddb70cacdd3620a079084a242126dd78
|
||||||
2
src/Misc/contentHash/externals/linux-x64
vendored
2
src/Misc/contentHash/externals/linux-x64
vendored
@@ -1 +1 @@
|
|||||||
a9fb9c14e24e79aec97d4da197dd7bfc6364297d6fce573afb2df48cc9a931f8
|
e7f2da271abb174285c3a757503538b3e9792e9d731b0382b6d1f21bb59a79ba
|
||||||
2
src/Misc/contentHash/externals/osx-arm64
vendored
2
src/Misc/contentHash/externals/osx-arm64
vendored
@@ -1 +1 @@
|
|||||||
a4e0e8fc62eba0967a39c7d693dcd0aeb8b2bed0765f9c38df80d42884f65341
|
2481c5b0d06b2b5621635f2568b86a43b0e5b259fed1298167ba4f33d4c464c7
|
||||||
2
src/Misc/contentHash/externals/osx-x64
vendored
2
src/Misc/contentHash/externals/osx-x64
vendored
@@ -1 +1 @@
|
|||||||
17ac17fbe785b3d6fa2868d8d17185ebfe0c90b4b0ddf6b67eac70e42bcd989b
|
85de7677165e65ec69b8a9e344c0811efa51b7fe5376a1aa083505c560ea6f57
|
||||||
2
src/Misc/contentHash/externals/win-arm64
vendored
2
src/Misc/contentHash/externals/win-arm64
vendored
@@ -1 +1 @@
|
|||||||
89f24657a550f1e818b0e9975e5b80edcf4dd22b7d4bccbb9e48e37f45d30fb1
|
763d18de11c11fd299c0e75e98fefc8a0e6605ae0ad6aba3bbc110db2262ab41
|
||||||
2
src/Misc/contentHash/externals/win-x64
vendored
2
src/Misc/contentHash/externals/win-x64
vendored
@@ -1 +1 @@
|
|||||||
24fd131b5dce33ef16038b771407bc0507da8682a72fb3b7780607235f76db0b
|
16f3cc545dfe10e84df43746073fc64d3c44d1891782532805aeb2118869a55d
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"bracketSpacing": false,
|
"bracketSpacing": false,
|
||||||
"arrowParens": "avoid",
|
"arrowParens": "avoid",
|
||||||
"parser": "typescript"
|
"overrides": [
|
||||||
}
|
{
|
||||||
|
"files": "*.{js,ts,json}",
|
||||||
|
"options": {
|
||||||
|
"tabWidth": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run all`.
|
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run prepare && npm run all`.
|
||||||
|
|
||||||
> Note: this package also needs to be recompiled for dependabot PRs updating one of
|
When you commit changes to the JSON or Typescript file, the javascript binary will be automatically re-compiled and added to the latest commit.
|
||||||
> its dependencies.
|
|
||||||
|
|||||||
4779
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
4779
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,9 @@
|
|||||||
"format-check": "prettier --check **/*.ts",
|
"format-check": "prettier --check **/*.ts",
|
||||||
"lint": "eslint src/**/*.ts",
|
"lint": "eslint src/**/*.ts",
|
||||||
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
||||||
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
"all": "npm run format && npm run lint && npm run build && npm run pack",
|
||||||
|
"prepare": "cd ../../../../ && husky install"
|
||||||
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -18,18 +20,32 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"actions"
|
"actions"
|
||||||
],
|
],
|
||||||
|
"lint-staged": {
|
||||||
|
"*.md": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add ."
|
||||||
|
],
|
||||||
|
"*.{ts,json}": [
|
||||||
|
"sh -c 'npm run all'",
|
||||||
|
"git add ."
|
||||||
|
]
|
||||||
|
},
|
||||||
"author": "GitHub Actions",
|
"author": "GitHub Actions",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/glob": "^0.1.0"
|
"@actions/glob": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12.7.12",
|
"@types/node": "^20.5.6",
|
||||||
"@typescript-eslint/parser": "^5.15.0",
|
"@typescript-eslint/eslint-plugin": "^6.4.0",
|
||||||
"@vercel/ncc": "^0.36.0",
|
"@typescript-eslint/parser": "^6.4.1",
|
||||||
"eslint": "^8.11.0",
|
"@vercel/ncc": "^0.36.1",
|
||||||
"eslint-plugin-github": "^4.3.5",
|
"eslint": "^8.47.0",
|
||||||
"prettier": "^1.19.1",
|
"eslint-plugin-github": "^4.9.2",
|
||||||
"typescript": "^3.6.4"
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
|
"prettier": "^3.0.1",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"lint-staged": "^14.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,12 +52,13 @@ async function run(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run()
|
;(async () => {
|
||||||
.then(out => {
|
try {
|
||||||
|
const out = await run()
|
||||||
console.log(out)
|
console.log(out)
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
})
|
} catch (err) {
|
||||||
.catch(err => {
|
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
}
|
||||||
|
})()
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ PRECACHE=$2
|
|||||||
|
|
||||||
NODE_URL=https://nodejs.org/dist
|
NODE_URL=https://nodejs.org/dist
|
||||||
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
|
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
|
||||||
NODE12_VERSION="12.22.7"
|
NODE16_VERSION="16.20.1"
|
||||||
NODE16_VERSION="16.16.0"
|
NODE20_VERSION="20.5.0"
|
||||||
|
# used only for win-arm64, remove node16 unofficial version when official version is available
|
||||||
|
NODE16_UNOFFICIAL_VERSION="16.20.0"
|
||||||
|
|
||||||
get_abs_path() {
|
get_abs_path() {
|
||||||
# exploits the fact that pwd will print abs path when no args
|
# exploits the fact that pwd will print abs path when no args
|
||||||
@@ -137,10 +139,10 @@ function acquireExternalTool() {
|
|||||||
|
|
||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -149,8 +151,10 @@ fi
|
|||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
|
||||||
# todo: replace these with official release when available
|
# todo: replace these with official release when available
|
||||||
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||||
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -158,29 +162,30 @@ fi
|
|||||||
|
|
||||||
# Download the external tools only for OSX.
|
# Download the external tools only for OSX.
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-x64.tar.gz" node20 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
||||||
# node.js v12 doesn't support macOS on arm64.
|
# node.js v12 doesn't support macOS on arm64.
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-arm64.tar.gz" node20 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
|
||||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-v${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-x64.tar.gz" node20 fix_nested_dir
|
||||||
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE20_VERSION}/alpine/x64/node-v${NODE20_VERSION}-alpine-x64.tar.gz" node20_alpine
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-arm64.tar.gz" node20 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -6,6 +6,29 @@
|
|||||||
|
|
||||||
"use strict";
|
"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;
|
||||||
|
};
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
@@ -22,13 +45,6 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|||||||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
||||||
};
|
};
|
||||||
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 }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const crypto = __importStar(__nccwpck_require__(6113));
|
const crypto = __importStar(__nccwpck_require__(6113));
|
||||||
const fs = __importStar(__nccwpck_require__(7147));
|
const fs = __importStar(__nccwpck_require__(7147));
|
||||||
@@ -37,7 +53,7 @@ const path = __importStar(__nccwpck_require__(1017));
|
|||||||
const stream = __importStar(__nccwpck_require__(2781));
|
const stream = __importStar(__nccwpck_require__(2781));
|
||||||
const util = __importStar(__nccwpck_require__(3837));
|
const util = __importStar(__nccwpck_require__(3837));
|
||||||
function run() {
|
function run() {
|
||||||
var e_1, _a;
|
var _a, e_1, _b, _c;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
// arg0 -> node
|
// arg0 -> node
|
||||||
// arg1 -> hashFiles.js
|
// arg1 -> hashFiles.js
|
||||||
@@ -56,8 +72,10 @@ function run() {
|
|||||||
let count = 0;
|
let count = 0;
|
||||||
const globber = yield glob.create(matchPatterns, { followSymbolicLinks });
|
const globber = yield glob.create(matchPatterns, { followSymbolicLinks });
|
||||||
try {
|
try {
|
||||||
for (var _b = __asyncValues(globber.globGenerator()), _c; _c = yield _b.next(), !_c.done;) {
|
for (var _d = true, _e = __asyncValues(globber.globGenerator()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
||||||
const file = _c.value;
|
_c = _f.value;
|
||||||
|
_d = false;
|
||||||
|
const file = _c;
|
||||||
console.log(file);
|
console.log(file);
|
||||||
if (!file.startsWith(`${githubWorkspace}${path.sep}`)) {
|
if (!file.startsWith(`${githubWorkspace}${path.sep}`)) {
|
||||||
console.log(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`);
|
console.log(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`);
|
||||||
@@ -80,7 +98,7 @@ function run() {
|
|||||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
|
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
||||||
}
|
}
|
||||||
finally { if (e_1) throw e_1.error; }
|
finally { if (e_1) throw e_1.error; }
|
||||||
}
|
}
|
||||||
@@ -94,15 +112,18 @@ function run() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
run()
|
;
|
||||||
.then(out => {
|
(() => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
console.log(out);
|
try {
|
||||||
process.exit(0);
|
const out = yield run();
|
||||||
})
|
console.log(out);
|
||||||
.catch(err => {
|
process.exit(0);
|
||||||
console.error(err);
|
}
|
||||||
process.exit(1);
|
catch (err) {
|
||||||
});
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}))();
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -246,7 +267,6 @@ const file_command_1 = __nccwpck_require__(717);
|
|||||||
const utils_1 = __nccwpck_require__(5278);
|
const utils_1 = __nccwpck_require__(5278);
|
||||||
const os = __importStar(__nccwpck_require__(2037));
|
const os = __importStar(__nccwpck_require__(2037));
|
||||||
const path = __importStar(__nccwpck_require__(1017));
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const uuid_1 = __nccwpck_require__(5840);
|
|
||||||
const oidc_utils_1 = __nccwpck_require__(8041);
|
const oidc_utils_1 = __nccwpck_require__(8041);
|
||||||
/**
|
/**
|
||||||
* The code to exit an action
|
* The code to exit an action
|
||||||
@@ -276,20 +296,9 @@ function exportVariable(name, val) {
|
|||||||
process.env[name] = convertedVal;
|
process.env[name] = convertedVal;
|
||||||
const filePath = process.env['GITHUB_ENV'] || '';
|
const filePath = process.env['GITHUB_ENV'] || '';
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
|
return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val));
|
||||||
// These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter.
|
|
||||||
if (name.includes(delimiter)) {
|
|
||||||
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
|
|
||||||
}
|
|
||||||
if (convertedVal.includes(delimiter)) {
|
|
||||||
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
|
|
||||||
}
|
|
||||||
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
|
|
||||||
file_command_1.issueCommand('ENV', commandValue);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
command_1.issueCommand('set-env', { name }, convertedVal);
|
|
||||||
}
|
}
|
||||||
|
command_1.issueCommand('set-env', { name }, convertedVal);
|
||||||
}
|
}
|
||||||
exports.exportVariable = exportVariable;
|
exports.exportVariable = exportVariable;
|
||||||
/**
|
/**
|
||||||
@@ -307,7 +316,7 @@ exports.setSecret = setSecret;
|
|||||||
function addPath(inputPath) {
|
function addPath(inputPath) {
|
||||||
const filePath = process.env['GITHUB_PATH'] || '';
|
const filePath = process.env['GITHUB_PATH'] || '';
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
file_command_1.issueCommand('PATH', inputPath);
|
file_command_1.issueFileCommand('PATH', inputPath);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
command_1.issueCommand('add-path', {}, inputPath);
|
command_1.issueCommand('add-path', {}, inputPath);
|
||||||
@@ -347,7 +356,10 @@ function getMultilineInput(name, options) {
|
|||||||
const inputs = getInput(name, options)
|
const inputs = getInput(name, options)
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter(x => x !== '');
|
.filter(x => x !== '');
|
||||||
return inputs;
|
if (options && options.trimWhitespace === false) {
|
||||||
|
return inputs;
|
||||||
|
}
|
||||||
|
return inputs.map(input => input.trim());
|
||||||
}
|
}
|
||||||
exports.getMultilineInput = getMultilineInput;
|
exports.getMultilineInput = getMultilineInput;
|
||||||
/**
|
/**
|
||||||
@@ -380,8 +392,12 @@ exports.getBooleanInput = getBooleanInput;
|
|||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function setOutput(name, value) {
|
function setOutput(name, value) {
|
||||||
|
const filePath = process.env['GITHUB_OUTPUT'] || '';
|
||||||
|
if (filePath) {
|
||||||
|
return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value));
|
||||||
|
}
|
||||||
process.stdout.write(os.EOL);
|
process.stdout.write(os.EOL);
|
||||||
command_1.issueCommand('set-output', { name }, value);
|
command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value));
|
||||||
}
|
}
|
||||||
exports.setOutput = setOutput;
|
exports.setOutput = setOutput;
|
||||||
/**
|
/**
|
||||||
@@ -510,7 +526,11 @@ exports.group = group;
|
|||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function saveState(name, value) {
|
function saveState(name, value) {
|
||||||
command_1.issueCommand('save-state', { name }, value);
|
const filePath = process.env['GITHUB_STATE'] || '';
|
||||||
|
if (filePath) {
|
||||||
|
return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value));
|
||||||
|
}
|
||||||
|
command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value));
|
||||||
}
|
}
|
||||||
exports.saveState = saveState;
|
exports.saveState = saveState;
|
||||||
/**
|
/**
|
||||||
@@ -576,13 +596,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.issueCommand = void 0;
|
exports.prepareKeyValueMessage = exports.issueFileCommand = void 0;
|
||||||
// We use any as a valid input type
|
// We use any as a valid input type
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
const fs = __importStar(__nccwpck_require__(7147));
|
const fs = __importStar(__nccwpck_require__(7147));
|
||||||
const os = __importStar(__nccwpck_require__(2037));
|
const os = __importStar(__nccwpck_require__(2037));
|
||||||
|
const uuid_1 = __nccwpck_require__(5840);
|
||||||
const utils_1 = __nccwpck_require__(5278);
|
const utils_1 = __nccwpck_require__(5278);
|
||||||
function issueCommand(command, message) {
|
function issueFileCommand(command, message) {
|
||||||
const filePath = process.env[`GITHUB_${command}`];
|
const filePath = process.env[`GITHUB_${command}`];
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
throw new Error(`Unable to find environment variable for file command ${command}`);
|
throw new Error(`Unable to find environment variable for file command ${command}`);
|
||||||
@@ -594,7 +615,22 @@ function issueCommand(command, message) {
|
|||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.issueCommand = issueCommand;
|
exports.issueFileCommand = issueFileCommand;
|
||||||
|
function prepareKeyValueMessage(key, value) {
|
||||||
|
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
|
||||||
|
const convertedValue = utils_1.toCommandValue(value);
|
||||||
|
// These should realistically never happen, but just in case someone finds a
|
||||||
|
// way to exploit uuid generation let's not allow keys or values that contain
|
||||||
|
// the delimiter.
|
||||||
|
if (key.includes(delimiter)) {
|
||||||
|
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
|
||||||
|
}
|
||||||
|
if (convertedValue.includes(delimiter)) {
|
||||||
|
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
|
||||||
|
}
|
||||||
|
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;
|
||||||
|
}
|
||||||
|
exports.prepareKeyValueMessage = prepareKeyValueMessage;
|
||||||
//# sourceMappingURL=file-command.js.map
|
//# sourceMappingURL=file-command.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -1100,7 +1136,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.hashFiles = exports.create = void 0;
|
||||||
const internal_globber_1 = __nccwpck_require__(8298);
|
const internal_globber_1 = __nccwpck_require__(8298);
|
||||||
|
const internal_hash_files_1 = __nccwpck_require__(2448);
|
||||||
/**
|
/**
|
||||||
* Constructs a globber
|
* Constructs a globber
|
||||||
*
|
*
|
||||||
@@ -1113,17 +1151,56 @@ function create(patterns, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.create = create;
|
exports.create = create;
|
||||||
|
/**
|
||||||
|
* Computes the sha256 hash of a glob
|
||||||
|
*
|
||||||
|
* @param patterns Patterns separated by newlines
|
||||||
|
* @param currentWorkspace Workspace used when matching files
|
||||||
|
* @param options Glob options
|
||||||
|
* @param verbose Enables verbose logging
|
||||||
|
*/
|
||||||
|
function hashFiles(patterns, currentWorkspace = '', options, verbose = false) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let followSymbolicLinks = true;
|
||||||
|
if (options && typeof options.followSymbolicLinks === 'boolean') {
|
||||||
|
followSymbolicLinks = options.followSymbolicLinks;
|
||||||
|
}
|
||||||
|
const globber = yield create(patterns, { followSymbolicLinks });
|
||||||
|
return internal_hash_files_1.hashFiles(globber, currentWorkspace, verbose);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.hashFiles = hashFiles;
|
||||||
//# sourceMappingURL=glob.js.map
|
//# sourceMappingURL=glob.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 1026:
|
/***/ 1026:
|
||||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const core = __nccwpck_require__(2186);
|
exports.getOptions = void 0;
|
||||||
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
/**
|
/**
|
||||||
* Returns a copy with defaults filled in.
|
* Returns a copy with defaults filled in.
|
||||||
*/
|
*/
|
||||||
@@ -1131,6 +1208,7 @@ function getOptions(copy) {
|
|||||||
const result = {
|
const result = {
|
||||||
followSymbolicLinks: true,
|
followSymbolicLinks: true,
|
||||||
implicitDescendants: true,
|
implicitDescendants: true,
|
||||||
|
matchDirectories: true,
|
||||||
omitBrokenSymbolicLinks: true
|
omitBrokenSymbolicLinks: true
|
||||||
};
|
};
|
||||||
if (copy) {
|
if (copy) {
|
||||||
@@ -1142,6 +1220,10 @@ function getOptions(copy) {
|
|||||||
result.implicitDescendants = copy.implicitDescendants;
|
result.implicitDescendants = copy.implicitDescendants;
|
||||||
core.debug(`implicitDescendants '${result.implicitDescendants}'`);
|
core.debug(`implicitDescendants '${result.implicitDescendants}'`);
|
||||||
}
|
}
|
||||||
|
if (typeof copy.matchDirectories === 'boolean') {
|
||||||
|
result.matchDirectories = copy.matchDirectories;
|
||||||
|
core.debug(`matchDirectories '${result.matchDirectories}'`);
|
||||||
|
}
|
||||||
if (typeof copy.omitBrokenSymbolicLinks === 'boolean') {
|
if (typeof copy.omitBrokenSymbolicLinks === 'boolean') {
|
||||||
result.omitBrokenSymbolicLinks = copy.omitBrokenSymbolicLinks;
|
result.omitBrokenSymbolicLinks = copy.omitBrokenSymbolicLinks;
|
||||||
core.debug(`omitBrokenSymbolicLinks '${result.omitBrokenSymbolicLinks}'`);
|
core.debug(`omitBrokenSymbolicLinks '${result.omitBrokenSymbolicLinks}'`);
|
||||||
@@ -1159,6 +1241,25 @@ exports.getOptions = getOptions;
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
@@ -1188,11 +1289,12 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|||||||
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const core = __nccwpck_require__(2186);
|
exports.DefaultGlobber = void 0;
|
||||||
const fs = __nccwpck_require__(7147);
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const globOptionsHelper = __nccwpck_require__(1026);
|
const fs = __importStar(__nccwpck_require__(7147));
|
||||||
const path = __nccwpck_require__(1017);
|
const globOptionsHelper = __importStar(__nccwpck_require__(1026));
|
||||||
const patternHelper = __nccwpck_require__(9005);
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
|
const patternHelper = __importStar(__nccwpck_require__(9005));
|
||||||
const internal_match_kind_1 = __nccwpck_require__(1063);
|
const internal_match_kind_1 = __nccwpck_require__(1063);
|
||||||
const internal_pattern_1 = __nccwpck_require__(4536);
|
const internal_pattern_1 = __nccwpck_require__(4536);
|
||||||
const internal_search_state_1 = __nccwpck_require__(9117);
|
const internal_search_state_1 = __nccwpck_require__(9117);
|
||||||
@@ -1238,7 +1340,7 @@ class DefaultGlobber {
|
|||||||
if (options.implicitDescendants &&
|
if (options.implicitDescendants &&
|
||||||
(pattern.trailingSeparator ||
|
(pattern.trailingSeparator ||
|
||||||
pattern.segments[pattern.segments.length - 1] !== '**')) {
|
pattern.segments[pattern.segments.length - 1] !== '**')) {
|
||||||
patterns.push(new internal_pattern_1.Pattern(pattern.negate, pattern.segments.concat('**')));
|
patterns.push(new internal_pattern_1.Pattern(pattern.negate, true, pattern.segments.concat('**')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Push the search paths
|
// Push the search paths
|
||||||
@@ -1281,7 +1383,7 @@ class DefaultGlobber {
|
|||||||
// Directory
|
// Directory
|
||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
// Matched
|
// Matched
|
||||||
if (match & internal_match_kind_1.MatchKind.Directory) {
|
if (match & internal_match_kind_1.MatchKind.Directory && options.matchDirectories) {
|
||||||
yield yield __await(item.path);
|
yield yield __await(item.path);
|
||||||
}
|
}
|
||||||
// Descend?
|
// Descend?
|
||||||
@@ -1376,12 +1478,117 @@ exports.DefaultGlobber = DefaultGlobber;
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 2448:
|
||||||
|
/***/ (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;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
||||||
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||||
|
var m = o[Symbol.asyncIterator], i;
|
||||||
|
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
||||||
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||||
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.hashFiles = void 0;
|
||||||
|
const crypto = __importStar(__nccwpck_require__(6113));
|
||||||
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
|
const fs = __importStar(__nccwpck_require__(7147));
|
||||||
|
const stream = __importStar(__nccwpck_require__(2781));
|
||||||
|
const util = __importStar(__nccwpck_require__(3837));
|
||||||
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
|
function hashFiles(globber, currentWorkspace, verbose = false) {
|
||||||
|
var e_1, _a;
|
||||||
|
var _b;
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const writeDelegate = verbose ? core.info : core.debug;
|
||||||
|
let hasMatch = false;
|
||||||
|
const githubWorkspace = currentWorkspace
|
||||||
|
? currentWorkspace
|
||||||
|
: (_b = process.env['GITHUB_WORKSPACE']) !== null && _b !== void 0 ? _b : process.cwd();
|
||||||
|
const result = crypto.createHash('sha256');
|
||||||
|
let count = 0;
|
||||||
|
try {
|
||||||
|
for (var _c = __asyncValues(globber.globGenerator()), _d; _d = yield _c.next(), !_d.done;) {
|
||||||
|
const file = _d.value;
|
||||||
|
writeDelegate(file);
|
||||||
|
if (!file.startsWith(`${githubWorkspace}${path.sep}`)) {
|
||||||
|
writeDelegate(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fs.statSync(file).isDirectory()) {
|
||||||
|
writeDelegate(`Skip directory '${file}'.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const hash = crypto.createHash('sha256');
|
||||||
|
const pipeline = util.promisify(stream.pipeline);
|
||||||
|
yield pipeline(fs.createReadStream(file), hash);
|
||||||
|
result.write(hash.digest());
|
||||||
|
count++;
|
||||||
|
if (!hasMatch) {
|
||||||
|
hasMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
if (_d && !_d.done && (_a = _c.return)) yield _a.call(_c);
|
||||||
|
}
|
||||||
|
finally { if (e_1) throw e_1.error; }
|
||||||
|
}
|
||||||
|
result.end();
|
||||||
|
if (hasMatch) {
|
||||||
|
writeDelegate(`Found ${count} files to hash.`);
|
||||||
|
return result.digest('hex');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writeDelegate(`No matches found for glob`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.hashFiles = hashFiles;
|
||||||
|
//# sourceMappingURL=internal-hash-files.js.map
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
/***/ 1063:
|
/***/ 1063:
|
||||||
/***/ ((__unused_webpack_module, exports) => {
|
/***/ ((__unused_webpack_module, exports) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.MatchKind = void 0;
|
||||||
/**
|
/**
|
||||||
* Indicates whether a pattern matches a path
|
* Indicates whether a pattern matches a path
|
||||||
*/
|
*/
|
||||||
@@ -1401,13 +1608,36 @@ var MatchKind;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 1849:
|
/***/ 1849:
|
||||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const assert = __nccwpck_require__(9491);
|
exports.safeTrimTrailingSeparator = exports.normalizeSeparators = exports.hasRoot = exports.hasAbsoluteRoot = exports.ensureAbsoluteRoot = exports.dirname = void 0;
|
||||||
const path = __nccwpck_require__(1017);
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
|
const assert_1 = __importDefault(__nccwpck_require__(9491));
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
/**
|
/**
|
||||||
* Similar to path.dirname except normalizes the path separators and slightly better handling for Windows UNC paths.
|
* Similar to path.dirname except normalizes the path separators and slightly better handling for Windows UNC paths.
|
||||||
@@ -1447,8 +1677,8 @@ exports.dirname = dirname;
|
|||||||
* or `C:` are expanded based on the current working directory.
|
* or `C:` are expanded based on the current working directory.
|
||||||
*/
|
*/
|
||||||
function ensureAbsoluteRoot(root, itemPath) {
|
function ensureAbsoluteRoot(root, itemPath) {
|
||||||
assert(root, `ensureAbsoluteRoot parameter 'root' must not be empty`);
|
assert_1.default(root, `ensureAbsoluteRoot parameter 'root' must not be empty`);
|
||||||
assert(itemPath, `ensureAbsoluteRoot parameter 'itemPath' must not be empty`);
|
assert_1.default(itemPath, `ensureAbsoluteRoot parameter 'itemPath' must not be empty`);
|
||||||
// Already rooted
|
// Already rooted
|
||||||
if (hasAbsoluteRoot(itemPath)) {
|
if (hasAbsoluteRoot(itemPath)) {
|
||||||
return itemPath;
|
return itemPath;
|
||||||
@@ -1458,7 +1688,7 @@ function ensureAbsoluteRoot(root, itemPath) {
|
|||||||
// Check for itemPath like C: or C:foo
|
// Check for itemPath like C: or C:foo
|
||||||
if (itemPath.match(/^[A-Z]:[^\\/]|^[A-Z]:$/i)) {
|
if (itemPath.match(/^[A-Z]:[^\\/]|^[A-Z]:$/i)) {
|
||||||
let cwd = process.cwd();
|
let cwd = process.cwd();
|
||||||
assert(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`);
|
assert_1.default(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`);
|
||||||
// Drive letter matches cwd? Expand to cwd
|
// Drive letter matches cwd? Expand to cwd
|
||||||
if (itemPath[0].toUpperCase() === cwd[0].toUpperCase()) {
|
if (itemPath[0].toUpperCase() === cwd[0].toUpperCase()) {
|
||||||
// Drive only, e.g. C:
|
// Drive only, e.g. C:
|
||||||
@@ -1483,11 +1713,11 @@ function ensureAbsoluteRoot(root, itemPath) {
|
|||||||
// Check for itemPath like \ or \foo
|
// Check for itemPath like \ or \foo
|
||||||
else if (normalizeSeparators(itemPath).match(/^\\$|^\\[^\\]/)) {
|
else if (normalizeSeparators(itemPath).match(/^\\$|^\\[^\\]/)) {
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
assert(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`);
|
assert_1.default(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`);
|
||||||
return `${cwd[0]}:\\${itemPath.substr(1)}`;
|
return `${cwd[0]}:\\${itemPath.substr(1)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(hasAbsoluteRoot(root), `ensureAbsoluteRoot parameter 'root' must have an absolute root`);
|
assert_1.default(hasAbsoluteRoot(root), `ensureAbsoluteRoot parameter 'root' must have an absolute root`);
|
||||||
// Otherwise ensure root ends with a separator
|
// Otherwise ensure root ends with a separator
|
||||||
if (root.endsWith('/') || (IS_WINDOWS && root.endsWith('\\'))) {
|
if (root.endsWith('/') || (IS_WINDOWS && root.endsWith('\\'))) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
@@ -1504,7 +1734,7 @@ exports.ensureAbsoluteRoot = ensureAbsoluteRoot;
|
|||||||
* `\\hello\share` and `C:\hello` (and using alternate separator).
|
* `\\hello\share` and `C:\hello` (and using alternate separator).
|
||||||
*/
|
*/
|
||||||
function hasAbsoluteRoot(itemPath) {
|
function hasAbsoluteRoot(itemPath) {
|
||||||
assert(itemPath, `hasAbsoluteRoot parameter 'itemPath' must not be empty`);
|
assert_1.default(itemPath, `hasAbsoluteRoot parameter 'itemPath' must not be empty`);
|
||||||
// Normalize separators
|
// Normalize separators
|
||||||
itemPath = normalizeSeparators(itemPath);
|
itemPath = normalizeSeparators(itemPath);
|
||||||
// Windows
|
// Windows
|
||||||
@@ -1521,7 +1751,7 @@ exports.hasAbsoluteRoot = hasAbsoluteRoot;
|
|||||||
* `\`, `\hello`, `\\hello\share`, `C:`, and `C:\hello` (and using alternate separator).
|
* `\`, `\hello`, `\\hello\share`, `C:`, and `C:\hello` (and using alternate separator).
|
||||||
*/
|
*/
|
||||||
function hasRoot(itemPath) {
|
function hasRoot(itemPath) {
|
||||||
assert(itemPath, `isRooted parameter 'itemPath' must not be empty`);
|
assert_1.default(itemPath, `isRooted parameter 'itemPath' must not be empty`);
|
||||||
// Normalize separators
|
// Normalize separators
|
||||||
itemPath = normalizeSeparators(itemPath);
|
itemPath = normalizeSeparators(itemPath);
|
||||||
// Windows
|
// Windows
|
||||||
@@ -1583,14 +1813,37 @@ exports.safeTrimTrailingSeparator = safeTrimTrailingSeparator;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 6836:
|
/***/ 6836:
|
||||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const assert = __nccwpck_require__(9491);
|
exports.Path = void 0;
|
||||||
const path = __nccwpck_require__(1017);
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const pathHelper = __nccwpck_require__(1849);
|
const pathHelper = __importStar(__nccwpck_require__(1849));
|
||||||
|
const assert_1 = __importDefault(__nccwpck_require__(9491));
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
/**
|
/**
|
||||||
* Helper class for parsing paths into segments
|
* Helper class for parsing paths into segments
|
||||||
@@ -1604,7 +1857,7 @@ class Path {
|
|||||||
this.segments = [];
|
this.segments = [];
|
||||||
// String
|
// String
|
||||||
if (typeof itemPath === 'string') {
|
if (typeof itemPath === 'string') {
|
||||||
assert(itemPath, `Parameter 'itemPath' must not be empty`);
|
assert_1.default(itemPath, `Parameter 'itemPath' must not be empty`);
|
||||||
// Normalize slashes and trim unnecessary trailing slash
|
// Normalize slashes and trim unnecessary trailing slash
|
||||||
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath);
|
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath);
|
||||||
// Not rooted
|
// Not rooted
|
||||||
@@ -1631,24 +1884,24 @@ class Path {
|
|||||||
// Array
|
// Array
|
||||||
else {
|
else {
|
||||||
// Must not be empty
|
// Must not be empty
|
||||||
assert(itemPath.length > 0, `Parameter 'itemPath' must not be an empty array`);
|
assert_1.default(itemPath.length > 0, `Parameter 'itemPath' must not be an empty array`);
|
||||||
// Each segment
|
// Each segment
|
||||||
for (let i = 0; i < itemPath.length; i++) {
|
for (let i = 0; i < itemPath.length; i++) {
|
||||||
let segment = itemPath[i];
|
let segment = itemPath[i];
|
||||||
// Must not be empty
|
// Must not be empty
|
||||||
assert(segment, `Parameter 'itemPath' must not contain any empty segments`);
|
assert_1.default(segment, `Parameter 'itemPath' must not contain any empty segments`);
|
||||||
// Normalize slashes
|
// Normalize slashes
|
||||||
segment = pathHelper.normalizeSeparators(itemPath[i]);
|
segment = pathHelper.normalizeSeparators(itemPath[i]);
|
||||||
// Root segment
|
// Root segment
|
||||||
if (i === 0 && pathHelper.hasRoot(segment)) {
|
if (i === 0 && pathHelper.hasRoot(segment)) {
|
||||||
segment = pathHelper.safeTrimTrailingSeparator(segment);
|
segment = pathHelper.safeTrimTrailingSeparator(segment);
|
||||||
assert(segment === pathHelper.dirname(segment), `Parameter 'itemPath' root segment contains information for multiple segments`);
|
assert_1.default(segment === pathHelper.dirname(segment), `Parameter 'itemPath' root segment contains information for multiple segments`);
|
||||||
this.segments.push(segment);
|
this.segments.push(segment);
|
||||||
}
|
}
|
||||||
// All other segments
|
// All other segments
|
||||||
else {
|
else {
|
||||||
// Must not contain slash
|
// Must not contain slash
|
||||||
assert(!segment.includes(path.sep), `Parameter 'itemPath' contains unexpected path separators`);
|
assert_1.default(!segment.includes(path.sep), `Parameter 'itemPath' contains unexpected path separators`);
|
||||||
this.segments.push(segment);
|
this.segments.push(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1680,12 +1933,32 @@ exports.Path = Path;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 9005:
|
/***/ 9005:
|
||||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const pathHelper = __nccwpck_require__(1849);
|
exports.partialMatch = exports.match = exports.getSearchPaths = void 0;
|
||||||
|
const pathHelper = __importStar(__nccwpck_require__(1849));
|
||||||
const internal_match_kind_1 = __nccwpck_require__(1063);
|
const internal_match_kind_1 = __nccwpck_require__(1063);
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
/**
|
/**
|
||||||
@@ -1761,21 +2034,44 @@ exports.partialMatch = partialMatch;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 4536:
|
/***/ 4536:
|
||||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
const assert = __nccwpck_require__(9491);
|
exports.Pattern = void 0;
|
||||||
const os = __nccwpck_require__(2037);
|
const os = __importStar(__nccwpck_require__(2037));
|
||||||
const path = __nccwpck_require__(1017);
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const pathHelper = __nccwpck_require__(1849);
|
const pathHelper = __importStar(__nccwpck_require__(1849));
|
||||||
|
const assert_1 = __importDefault(__nccwpck_require__(9491));
|
||||||
const minimatch_1 = __nccwpck_require__(3973);
|
const minimatch_1 = __nccwpck_require__(3973);
|
||||||
const internal_match_kind_1 = __nccwpck_require__(1063);
|
const internal_match_kind_1 = __nccwpck_require__(1063);
|
||||||
const internal_path_1 = __nccwpck_require__(6836);
|
const internal_path_1 = __nccwpck_require__(6836);
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
class Pattern {
|
class Pattern {
|
||||||
constructor(patternOrNegate, segments) {
|
constructor(patternOrNegate, isImplicitPattern = false, segments, homedir) {
|
||||||
/**
|
/**
|
||||||
* Indicates whether matches should be excluded from the result set
|
* Indicates whether matches should be excluded from the result set
|
||||||
*/
|
*/
|
||||||
@@ -1789,9 +2085,9 @@ class Pattern {
|
|||||||
else {
|
else {
|
||||||
// Convert to pattern
|
// Convert to pattern
|
||||||
segments = segments || [];
|
segments = segments || [];
|
||||||
assert(segments.length, `Parameter 'segments' must not empty`);
|
assert_1.default(segments.length, `Parameter 'segments' must not empty`);
|
||||||
const root = Pattern.getLiteral(segments[0]);
|
const root = Pattern.getLiteral(segments[0]);
|
||||||
assert(root && pathHelper.hasAbsoluteRoot(root), `Parameter 'segments' first element must be a root path`);
|
assert_1.default(root && pathHelper.hasAbsoluteRoot(root), `Parameter 'segments' first element must be a root path`);
|
||||||
pattern = new internal_path_1.Path(segments).toString().trim();
|
pattern = new internal_path_1.Path(segments).toString().trim();
|
||||||
if (patternOrNegate) {
|
if (patternOrNegate) {
|
||||||
pattern = `!${pattern}`;
|
pattern = `!${pattern}`;
|
||||||
@@ -1803,7 +2099,7 @@ class Pattern {
|
|||||||
pattern = pattern.substr(1).trim();
|
pattern = pattern.substr(1).trim();
|
||||||
}
|
}
|
||||||
// Normalize slashes and ensures absolute root
|
// Normalize slashes and ensures absolute root
|
||||||
pattern = Pattern.fixupPattern(pattern);
|
pattern = Pattern.fixupPattern(pattern, homedir);
|
||||||
// Segments
|
// Segments
|
||||||
this.segments = new internal_path_1.Path(pattern).segments;
|
this.segments = new internal_path_1.Path(pattern).segments;
|
||||||
// Trailing slash indicates the pattern should only match directories, not regular files
|
// Trailing slash indicates the pattern should only match directories, not regular files
|
||||||
@@ -1819,6 +2115,7 @@ class Pattern {
|
|||||||
this.searchPath = new internal_path_1.Path(searchSegments).toString();
|
this.searchPath = new internal_path_1.Path(searchSegments).toString();
|
||||||
// Root RegExp (required when determining partial match)
|
// Root RegExp (required when determining partial match)
|
||||||
this.rootRegExp = new RegExp(Pattern.regExpEscape(searchSegments[0]), IS_WINDOWS ? 'i' : '');
|
this.rootRegExp = new RegExp(Pattern.regExpEscape(searchSegments[0]), IS_WINDOWS ? 'i' : '');
|
||||||
|
this.isImplicitPattern = isImplicitPattern;
|
||||||
// Create minimatch
|
// Create minimatch
|
||||||
const minimatchOptions = {
|
const minimatchOptions = {
|
||||||
dot: true,
|
dot: true,
|
||||||
@@ -1840,11 +2137,11 @@ class Pattern {
|
|||||||
// Normalize slashes
|
// Normalize slashes
|
||||||
itemPath = pathHelper.normalizeSeparators(itemPath);
|
itemPath = pathHelper.normalizeSeparators(itemPath);
|
||||||
// Append a trailing slash. Otherwise Minimatch will not match the directory immediately
|
// Append a trailing slash. Otherwise Minimatch will not match the directory immediately
|
||||||
// preceeding the globstar. For example, given the pattern `/foo/**`, Minimatch returns
|
// preceding the globstar. For example, given the pattern `/foo/**`, Minimatch returns
|
||||||
// false for `/foo` but returns true for `/foo/`. Append a trailing slash to handle that quirk.
|
// false for `/foo` but returns true for `/foo/`. Append a trailing slash to handle that quirk.
|
||||||
if (!itemPath.endsWith(path.sep)) {
|
if (!itemPath.endsWith(path.sep) && this.isImplicitPattern === false) {
|
||||||
// Note, this is safe because the constructor ensures the pattern has an absolute root.
|
// Note, this is safe because the constructor ensures the pattern has an absolute root.
|
||||||
// For example, formats like C: and C:foo on Windows are resolved to an aboslute root.
|
// For example, formats like C: and C:foo on Windows are resolved to an absolute root.
|
||||||
itemPath = `${itemPath}${path.sep}`;
|
itemPath = `${itemPath}${path.sep}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1882,15 +2179,15 @@ class Pattern {
|
|||||||
/**
|
/**
|
||||||
* Normalizes slashes and ensures absolute root
|
* Normalizes slashes and ensures absolute root
|
||||||
*/
|
*/
|
||||||
static fixupPattern(pattern) {
|
static fixupPattern(pattern, homedir) {
|
||||||
// Empty
|
// Empty
|
||||||
assert(pattern, 'pattern cannot be empty');
|
assert_1.default(pattern, 'pattern cannot be empty');
|
||||||
// Must not contain `.` segment, unless first segment
|
// Must not contain `.` segment, unless first segment
|
||||||
// Must not contain `..` segment
|
// Must not contain `..` segment
|
||||||
const literalSegments = new internal_path_1.Path(pattern).segments.map(x => Pattern.getLiteral(x));
|
const literalSegments = new internal_path_1.Path(pattern).segments.map(x => Pattern.getLiteral(x));
|
||||||
assert(literalSegments.every((x, i) => (x !== '.' || i === 0) && x !== '..'), `Invalid pattern '${pattern}'. Relative pathing '.' and '..' is not allowed.`);
|
assert_1.default(literalSegments.every((x, i) => (x !== '.' || i === 0) && x !== '..'), `Invalid pattern '${pattern}'. Relative pathing '.' and '..' is not allowed.`);
|
||||||
// Must not contain globs in root, e.g. Windows UNC path \\foo\b*r
|
// Must not contain globs in root, e.g. Windows UNC path \\foo\b*r
|
||||||
assert(!pathHelper.hasRoot(pattern) || literalSegments[0], `Invalid pattern '${pattern}'. Root segment must not contain globs.`);
|
assert_1.default(!pathHelper.hasRoot(pattern) || literalSegments[0], `Invalid pattern '${pattern}'. Root segment must not contain globs.`);
|
||||||
// Normalize slashes
|
// Normalize slashes
|
||||||
pattern = pathHelper.normalizeSeparators(pattern);
|
pattern = pathHelper.normalizeSeparators(pattern);
|
||||||
// Replace leading `.` segment
|
// Replace leading `.` segment
|
||||||
@@ -1899,9 +2196,9 @@ class Pattern {
|
|||||||
}
|
}
|
||||||
// Replace leading `~` segment
|
// Replace leading `~` segment
|
||||||
else if (pattern === '~' || pattern.startsWith(`~${path.sep}`)) {
|
else if (pattern === '~' || pattern.startsWith(`~${path.sep}`)) {
|
||||||
const homedir = os.homedir();
|
homedir = homedir || os.homedir();
|
||||||
assert(homedir, 'Unable to determine HOME directory');
|
assert_1.default(homedir, 'Unable to determine HOME directory');
|
||||||
assert(pathHelper.hasAbsoluteRoot(homedir), `Expected HOME directory to be a rooted path. Actual '${homedir}'`);
|
assert_1.default(pathHelper.hasAbsoluteRoot(homedir), `Expected HOME directory to be a rooted path. Actual '${homedir}'`);
|
||||||
pattern = Pattern.globEscape(homedir) + pattern.substr(1);
|
pattern = Pattern.globEscape(homedir) + pattern.substr(1);
|
||||||
}
|
}
|
||||||
// Replace relative drive root, e.g. pattern is C: or C:foo
|
// Replace relative drive root, e.g. pattern is C: or C:foo
|
||||||
@@ -2004,6 +2301,7 @@ exports.Pattern = Pattern;
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.SearchState = void 0;
|
||||||
class SearchState {
|
class SearchState {
|
||||||
constructor(path, level) {
|
constructor(path, level) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
@@ -2232,6 +2530,19 @@ class HttpClientResponse {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
readBodyBuffer() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const chunks = [];
|
||||||
|
this.message.on('data', (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
this.message.on('end', () => {
|
||||||
|
resolve(Buffer.concat(chunks));
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.HttpClientResponse = HttpClientResponse;
|
exports.HttpClientResponse = HttpClientResponse;
|
||||||
function isHttps(requestUrl) {
|
function isHttps(requestUrl) {
|
||||||
@@ -2736,7 +3047,13 @@ function getProxyUrl(reqUrl) {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
if (proxyVar) {
|
if (proxyVar) {
|
||||||
return new URL(proxyVar);
|
try {
|
||||||
|
return new URL(proxyVar);
|
||||||
|
}
|
||||||
|
catch (_a) {
|
||||||
|
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
|
||||||
|
return new URL(`http://${proxyVar}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -2747,6 +3064,10 @@ function checkBypass(reqUrl) {
|
|||||||
if (!reqUrl.hostname) {
|
if (!reqUrl.hostname) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const reqHost = reqUrl.hostname;
|
||||||
|
if (isLoopbackAddress(reqHost)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
|
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
|
||||||
if (!noProxy) {
|
if (!noProxy) {
|
||||||
return false;
|
return false;
|
||||||
@@ -2772,13 +3093,24 @@ function checkBypass(reqUrl) {
|
|||||||
.split(',')
|
.split(',')
|
||||||
.map(x => x.trim().toUpperCase())
|
.map(x => x.trim().toUpperCase())
|
||||||
.filter(x => x)) {
|
.filter(x => x)) {
|
||||||
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
|
if (upperNoProxyItem === '*' ||
|
||||||
|
upperReqHosts.some(x => x === upperNoProxyItem ||
|
||||||
|
x.endsWith(`.${upperNoProxyItem}`) ||
|
||||||
|
(upperNoProxyItem.startsWith('.') &&
|
||||||
|
x.endsWith(`${upperNoProxyItem}`)))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.checkBypass = checkBypass;
|
exports.checkBypass = checkBypass;
|
||||||
|
function isLoopbackAddress(host) {
|
||||||
|
const hostLower = host.toLowerCase();
|
||||||
|
return (hostLower === 'localhost' ||
|
||||||
|
hostLower.startsWith('127.') ||
|
||||||
|
hostLower.startsWith('[::1]') ||
|
||||||
|
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
|
||||||
|
}
|
||||||
//# sourceMappingURL=proxy.js.map
|
//# sourceMappingURL=proxy.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -2817,6 +3149,9 @@ function range(a, b, str) {
|
|||||||
var i = ai;
|
var i = ai;
|
||||||
|
|
||||||
if (ai >= 0 && bi > 0) {
|
if (ai >= 0 && bi > 0) {
|
||||||
|
if(a===b) {
|
||||||
|
return [ai, bi];
|
||||||
|
}
|
||||||
begs = [];
|
begs = [];
|
||||||
left = str.length;
|
left = str.length;
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ mscordaccore.dll
|
|||||||
mscordaccore_amd64_amd64_6.0.522.21309.dll
|
mscordaccore_amd64_amd64_6.0.522.21309.dll
|
||||||
mscordaccore_arm64_arm64_6.0.522.21309.dll
|
mscordaccore_arm64_arm64_6.0.522.21309.dll
|
||||||
mscordaccore_amd64_amd64_6.0.1322.58009.dll
|
mscordaccore_amd64_amd64_6.0.1322.58009.dll
|
||||||
|
mscordaccore_amd64_amd64_6.0.2023.32017.dll
|
||||||
mscordbi.dll
|
mscordbi.dll
|
||||||
mscorlib.dll
|
mscorlib.dll
|
||||||
mscorrc.debug.dll
|
mscorrc.debug.dll
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace GitHub.Runner.Common
|
|||||||
private bool? _isHostedServer;
|
private bool? _isHostedServer;
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public int AgentId { get; set; }
|
public ulong AgentId { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ namespace GitHub.Runner.Common
|
|||||||
public static class Features
|
public static class Features
|
||||||
{
|
{
|
||||||
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
||||||
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
|
public static readonly string Node16Warning = "DistributedTask.AddWarningToNode16Action";
|
||||||
|
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages";
|
||||||
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
||||||
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
|
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
|
||||||
}
|
}
|
||||||
@@ -170,7 +171,8 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
||||||
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
||||||
public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
||||||
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: {0}. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.";
|
public static readonly string EnforcedNode12DetectedAfterEndOfLife = "The following actions uses node12 which is deprecated and will be forced to run on node16: {0}. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/";
|
||||||
|
public static readonly string EnforcedNode12DetectedAfterEndOfLifeEnvVariable = "Node16ForceActionsWarnings";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RunnerEvent
|
public static class RunnerEvent
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
||||||
{
|
{
|
||||||
_trace.Warning($"Runner is running under insecure mode: HTTPS server certifcate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable.");
|
_trace.Warning($"Runner is running under insecure mode: HTTPS server certificate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
||||||
|
|||||||
73
src/Runner.Common/RedirectMessageHandler.cs
Normal file
73
src/Runner.Common/RedirectMessageHandler.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles redirects for Http requests
|
||||||
|
/// </summary>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public class RedirectMessageHandler : DelegatingHandler
|
||||||
|
{
|
||||||
|
public RedirectMessageHandler(ITraceWriter trace)
|
||||||
|
{
|
||||||
|
Trace = trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(
|
||||||
|
HttpRequestMessage request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (response != null &&
|
||||||
|
IsRedirect(response.StatusCode) &&
|
||||||
|
response.Headers.Location != null)
|
||||||
|
{
|
||||||
|
Trace.Info($"Redirecting to '{response.Headers.Location}'.");
|
||||||
|
|
||||||
|
request = await CloneAsync(request, response.Headers.Location).ConfigureAwait(false);
|
||||||
|
|
||||||
|
response.Dispose();
|
||||||
|
|
||||||
|
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsRedirect(HttpStatusCode statusCode)
|
||||||
|
{
|
||||||
|
return (int)statusCode >= 300 && (int)statusCode < 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<HttpRequestMessage> CloneAsync(HttpRequestMessage request, Uri requestUri)
|
||||||
|
{
|
||||||
|
var clone = new HttpRequestMessage(request.Method, requestUri)
|
||||||
|
{
|
||||||
|
Version = request.Version
|
||||||
|
};
|
||||||
|
|
||||||
|
request.Headers.ForEach(header => clone.Headers.TryAddWithoutValidation(header.Key, header.Value));
|
||||||
|
|
||||||
|
request.Options.ForEach(option => clone.Options.Set(new HttpRequestOptionsKey<object>(option.Key), option.Value));
|
||||||
|
|
||||||
|
if (request.Content != null)
|
||||||
|
{
|
||||||
|
clone.Content = new ByteArrayContent(await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
||||||
|
|
||||||
|
request.Content.Headers.ForEach(header => clone.Content.Headers.TryAddWithoutValidation(header.Key, header.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ITraceWriter Trace;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ namespace GitHub.Runner.Common
|
|||||||
Dictionary<String, VariableValue> outputs,
|
Dictionary<String, VariableValue> outputs,
|
||||||
IList<StepResult> stepResults,
|
IList<StepResult> stepResults,
|
||||||
IList<Annotation> jobAnnotations,
|
IList<Annotation> jobAnnotations,
|
||||||
|
string environmentUrl,
|
||||||
CancellationToken token);
|
CancellationToken token);
|
||||||
|
|
||||||
Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken token);
|
Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken token);
|
||||||
@@ -70,11 +71,12 @@ namespace GitHub.Runner.Common
|
|||||||
Dictionary<String, VariableValue> outputs,
|
Dictionary<String, VariableValue> outputs,
|
||||||
IList<StepResult> stepResults,
|
IList<StepResult> stepResults,
|
||||||
IList<Annotation> jobAnnotations,
|
IList<Annotation> jobAnnotations,
|
||||||
|
string environmentUrl,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection();
|
CheckConnection();
|
||||||
return RetryRequest(
|
return RetryRequest(
|
||||||
async () => await _runServiceHttpClient.CompleteJobAsync(requestUri, planId, jobId, result, outputs, stepResults, jobAnnotations, cancellationToken), cancellationToken);
|
async () => await _runServiceHttpClient.CompleteJobAsync(requestUri, planId, jobId, result, outputs, stepResults, jobAnnotations, environmentUrl, cancellationToken), cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken cancellationToken)
|
public Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Threading.Channels" Version="4.4.0" />
|
<PackageReference Include="System.Threading.Channels" Version="4.4.0" />
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ namespace GitHub.Runner.Common
|
|||||||
[ServiceLocator(Default = typeof(RunnerDotcomServer))]
|
[ServiceLocator(Default = typeof(RunnerDotcomServer))]
|
||||||
public interface IRunnerDotcomServer : IRunnerService
|
public interface IRunnerDotcomServer : IRunnerService
|
||||||
{
|
{
|
||||||
Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, string githubUrl, string githubToken, string agentName);
|
Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName);
|
||||||
|
|
||||||
Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey);
|
Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey);
|
||||||
|
Task<DistributedTask.WebApi.Runner> ReplaceRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey);
|
||||||
Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken);
|
Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken);
|
||||||
|
|
||||||
string GetGitHubRequestId(HttpResponseHeaders headers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RequestType
|
public enum RequestType
|
||||||
@@ -42,7 +41,7 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, string githubUrl, string githubToken, string agentName = null)
|
public async Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName)
|
||||||
{
|
{
|
||||||
var githubApiUrl = "";
|
var githubApiUrl = "";
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
||||||
@@ -52,11 +51,11 @@ namespace GitHub.Runner.Common
|
|||||||
// org runner
|
// org runner
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
||||||
{
|
{
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
|
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
|
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (path.Length == 2)
|
else if (path.Length == 2)
|
||||||
@@ -69,11 +68,11 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
||||||
{
|
{
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
|
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
|
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -82,14 +81,8 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
var runnersList = await RetryRequest<ListRunnersResponse>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
var runnersList = await RetryRequest<ListRunnersResponse>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
||||||
var agents = runnersList.ToTaskAgents();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(agentName))
|
return runnersList.ToTaskAgents();
|
||||||
{
|
|
||||||
return agents;
|
|
||||||
}
|
|
||||||
|
|
||||||
return agents.Where(x => string.Equals(x.Name, agentName, StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken)
|
public async Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken)
|
||||||
@@ -137,6 +130,16 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey)
|
public async Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey)
|
||||||
|
{
|
||||||
|
return await AddOrReplaceRunner(runnerGroupId, agent, githubUrl, githubToken, publicKey, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DistributedTask.WebApi.Runner> ReplaceRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey)
|
||||||
|
{
|
||||||
|
return await AddOrReplaceRunner(runnerGroupId, agent, githubUrl, githubToken, publicKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<DistributedTask.WebApi.Runner> AddOrReplaceRunner(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey, bool replace)
|
||||||
{
|
{
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
||||||
@@ -159,9 +162,15 @@ namespace GitHub.Runner.Common
|
|||||||
{"updates_disabled", agent.DisableUpdate},
|
{"updates_disabled", agent.DisableUpdate},
|
||||||
{"ephemeral", agent.Ephemeral},
|
{"ephemeral", agent.Ephemeral},
|
||||||
{"labels", agent.Labels},
|
{"labels", agent.Labels},
|
||||||
{"public_key", publicKey}
|
{"public_key", publicKey},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
bodyObject.Add("runner_id", agent.Id);
|
||||||
|
bodyObject.Add("replace", replace);
|
||||||
|
}
|
||||||
|
|
||||||
var body = new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json");
|
var body = new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json");
|
||||||
|
|
||||||
return await RetryRequest<DistributedTask.WebApi.Runner>(githubApiUrl, githubToken, RequestType.Post, 3, "Failed to add agent", body);
|
return await RetryRequest<DistributedTask.WebApi.Runner>(githubApiUrl, githubToken, RequestType.Post, 3, "Failed to add agent", body);
|
||||||
@@ -195,7 +204,7 @@ namespace GitHub.Runner.Common
|
|||||||
if (response != null)
|
if (response != null)
|
||||||
{
|
{
|
||||||
responseStatus = response.StatusCode;
|
responseStatus = response.StatusCode;
|
||||||
var githubRequestId = GetGitHubRequestId(response.Headers);
|
var githubRequestId = UrlUtil.GetGitHubRequestId(response.Headers);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -224,14 +233,5 @@ namespace GitHub.Runner.Common
|
|||||||
await Task.Delay(backOff);
|
await Task.Delay(backOff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetGitHubRequestId(HttpResponseHeaders headers)
|
|
||||||
{
|
|
||||||
if (headers.TryGetValues("x-github-request-id", out var headerValues))
|
|
||||||
{
|
|
||||||
return headerValues.FirstOrDefault();
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
||||||
Task DeleteAgentAsync(int agentPoolId, int agentId);
|
Task DeleteAgentAsync(int agentPoolId, ulong agentId);
|
||||||
Task DeleteAgentAsync(int agentId);
|
Task DeleteAgentAsync(ulong agentId);
|
||||||
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
||||||
@@ -50,7 +50,7 @@ namespace GitHub.Runner.Common
|
|||||||
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent update
|
// agent update
|
||||||
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace);
|
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, ulong agentId, string currentState, string trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RunnerServer : RunnerService, IRunnerServer
|
public sealed class RunnerServer : RunnerService, IRunnerServer
|
||||||
@@ -239,13 +239,13 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentPoolId, int agentId)
|
public Task DeleteAgentAsync(int agentPoolId, ulong agentId)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentId)
|
public Task DeleteAgentAsync(ulong agentId)
|
||||||
{
|
{
|
||||||
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
|
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, ulong agentId, string currentState, string trace)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
||||||
|
|||||||
@@ -6,13 +6,7 @@ namespace GitHub.Runner.Common.Util
|
|||||||
public static class NodeUtil
|
public static class NodeUtil
|
||||||
{
|
{
|
||||||
private const string _defaultNodeVersion = "node16";
|
private const string _defaultNodeVersion = "node16";
|
||||||
|
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16", "node20" });
|
||||||
#if (OS_OSX || OS_WINDOWS) && ARM64
|
|
||||||
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" });
|
|
||||||
#else
|
|
||||||
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node12", "node16" });
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static string GetInternalNodeVersion()
|
public static string GetInternalNodeVersion()
|
||||||
{
|
{
|
||||||
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
|
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace GitHub.Runner.Listener
|
|||||||
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
|
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
|
catch (AccessDeniedException e) when (e.ErrorCode == 1)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
if (!IsGetNextMessageExceptionRetriable(ex))
|
if (!IsGetNextMessageExceptionRetriable(ex))
|
||||||
{
|
{
|
||||||
throw;
|
throw new NonRetryableException("Get next message failed with non-retryable error.", ex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -351,21 +351,39 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new()
|
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"Microsoft-System-Net-Http",
|
"System.Net.Http",
|
||||||
new HashSet<string>
|
new HashSet<string>
|
||||||
{
|
{
|
||||||
"Info",
|
"Info",
|
||||||
"Associate",
|
"Associate",
|
||||||
"Enter",
|
|
||||||
"Exit"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Microsoft-System-Net-Security",
|
"System.Net.Security",
|
||||||
|
new HashSet<string>
|
||||||
|
{
|
||||||
|
"Info",
|
||||||
|
"DumpBuffer",
|
||||||
|
"SslStreamCtor",
|
||||||
|
"SecureChannelCtor",
|
||||||
|
"NoDelegateNoClientCert",
|
||||||
|
"CertsAfterFiltering",
|
||||||
|
"UsingCachedCredential",
|
||||||
|
"SspiSelectedCipherSuite"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Private.InternalDiagnostics.System.Net.Http",
|
||||||
|
new HashSet<string>
|
||||||
|
{
|
||||||
|
"Info",
|
||||||
|
"Associate",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Private.InternalDiagnostics.System.Net.Security",
|
||||||
new HashSet<string>
|
new HashSet<string>
|
||||||
{
|
{
|
||||||
"Enter",
|
|
||||||
"Exit",
|
|
||||||
"Info",
|
"Info",
|
||||||
"DumpBuffer",
|
"DumpBuffer",
|
||||||
"SslStreamCtor",
|
"SslStreamCtor",
|
||||||
@@ -391,8 +409,8 @@ namespace GitHub.Runner.Listener.Check
|
|||||||
{
|
{
|
||||||
base.OnEventSourceCreated(eventSource);
|
base.OnEventSourceCreated(eventSource);
|
||||||
|
|
||||||
if (eventSource.Name == "Microsoft-System-Net-Http" ||
|
if (eventSource.Name.Contains("System.Net.Http") ||
|
||||||
eventSource.Name == "Microsoft-System-Net-Security")
|
eventSource.Name.Contains("System.Net.Security"))
|
||||||
{
|
{
|
||||||
EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All);
|
EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
List<TaskAgent> agents;
|
List<TaskAgent> agents;
|
||||||
if (runnerSettings.UseV2Flow)
|
if (runnerSettings.UseV2Flow)
|
||||||
{
|
{
|
||||||
agents = await _dotcomServer.GetRunnersAsync(runnerSettings.PoolId, runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName);
|
agents = await _dotcomServer.GetRunnerByNameAsync(runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -263,7 +263,23 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
agent = await _runnerServer.ReplaceAgentAsync(runnerSettings.PoolId, agent);
|
if (runnerSettings.UseV2Flow)
|
||||||
|
{
|
||||||
|
var runner = await _dotcomServer.ReplaceRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML);
|
||||||
|
runnerSettings.ServerUrlV2 = runner.RunnerAuthorization.ServerUrl;
|
||||||
|
|
||||||
|
agent.Id = runner.Id;
|
||||||
|
agent.Authorization = new TaskAgentAuthorization()
|
||||||
|
{
|
||||||
|
AuthorizationUrl = runner.RunnerAuthorization.AuthorizationUrl,
|
||||||
|
ClientId = new Guid(runner.RunnerAuthorization.ClientId)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
agent = await _runnerServer.ReplaceAgentAsync(runnerSettings.PoolId, agent);
|
||||||
|
}
|
||||||
|
|
||||||
if (command.DisableUpdate &&
|
if (command.DisableUpdate &&
|
||||||
command.DisableUpdate != agent.DisableUpdate)
|
command.DisableUpdate != agent.DisableUpdate)
|
||||||
{
|
{
|
||||||
@@ -709,7 +725,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
||||||
responseStatus = response.StatusCode;
|
responseStatus = response.StatusCode;
|
||||||
var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
|
var githubRequestId = UrlUtil.GetGitHubRequestId(response.Headers);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -772,7 +788,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
||||||
responseStatus = response.StatusCode;
|
responseStatus = response.StatusCode;
|
||||||
var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
|
var githubRequestId = UrlUtil.GetGitHubRequestId(response.Headers);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1077,23 +1077,7 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
if (this._isRunServiceJob)
|
if (this._isRunServiceJob)
|
||||||
{
|
{
|
||||||
var runServer = await GetRunServerAsync(systemConnection);
|
Trace.Verbose($"Skip CompleteJobRequestAsync call from Listener because it's RunService job");
|
||||||
var unhandledExceptionIssue = new Issue() { Type = IssueType.Error, Message = detailInfo };
|
|
||||||
var unhandledAnnotation = unhandledExceptionIssue.ToAnnotation();
|
|
||||||
var jobAnnotations = new List<Annotation>();
|
|
||||||
if (unhandledAnnotation.HasValue)
|
|
||||||
{
|
|
||||||
jobAnnotations.Add(unhandledAnnotation.Value);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, result, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, CancellationToken.None);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Error("Fail to raise job completion back to service.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,7 +1177,7 @@ namespace GitHub.Runner.Listener
|
|||||||
jobAnnotations.Add(unhandledAnnotation.Value);
|
jobAnnotations.Add(unhandledAnnotation.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, TaskResult.Failed, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, CancellationToken.None);
|
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, TaskResult.Failed, outputs: null, stepResults: null, jobAnnotations: jobAnnotations, environmentUrl: null, CancellationToken.None);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -123,8 +123,15 @@ namespace GitHub.Runner.Listener
|
|||||||
Trace.Error("Catch exception during create session.");
|
Trace.Error("Catch exception during create session.");
|
||||||
Trace.Error(ex);
|
Trace.Error(ex);
|
||||||
|
|
||||||
if (ex is VssOAuthTokenRequestException && creds.Federated is VssOAuthCredential vssOAuthCred)
|
if (ex is VssOAuthTokenRequestException vssOAuthEx && creds.Federated is VssOAuthCredential vssOAuthCred)
|
||||||
{
|
{
|
||||||
|
// "invalid_client" means the runner registration has been deleted from the server.
|
||||||
|
if (string.Equals(vssOAuthEx.Error, "invalid_client", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether we get 401 because the runner registration already removed by the service.
|
// Check whether we get 401 because the runner registration already removed by the service.
|
||||||
// If the runner registration get deleted, we can't exchange oauth token.
|
// If the runner registration get deleted, we can't exchange oauth token.
|
||||||
Trace.Error("Test oauth app registration.");
|
Trace.Error("Test oauth app registration.");
|
||||||
@@ -245,7 +252,7 @@ namespace GitHub.Runner.Listener
|
|||||||
_accessTokenRevoked = true;
|
_accessTokenRevoked = true;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
|
catch (AccessDeniedException e) when (e.ErrorCode == 1)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
|
catch (AccessDeniedException e) when (e.ErrorCode == 1)
|
||||||
{
|
{
|
||||||
terminal.WriteError($"An error occured: {e.Message}");
|
terminal.WriteError($"An error occured: {e.Message}");
|
||||||
trace.Error(e);
|
trace.Error(e);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.4.0" />
|
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" />
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" />
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace GitHub.Runner.Listener
|
|||||||
private ITerminal _terminal;
|
private ITerminal _terminal;
|
||||||
private IRunnerServer _runnerServer;
|
private IRunnerServer _runnerServer;
|
||||||
private int _poolId;
|
private int _poolId;
|
||||||
private int _agentId;
|
private ulong _agentId;
|
||||||
private readonly ConcurrentQueue<string> _updateTrace = new();
|
private readonly ConcurrentQueue<string> _updateTrace = new();
|
||||||
private Task _cloneAndCalculateContentHashTask;
|
private Task _cloneAndCalculateContentHashTask;
|
||||||
private string _dotnetRuntimeCloneDirectory;
|
private string _dotnetRuntimeCloneDirectory;
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ namespace GitHub.Runner.Sdk
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(httpProxyAddress) && !Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var _))
|
||||||
|
{
|
||||||
|
httpProxyAddress = PrependHttpIfMissing(httpProxyAddress);
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(httpProxyAddress) && Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var proxyHttpUri))
|
if (!string.IsNullOrEmpty(httpProxyAddress) && Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var proxyHttpUri))
|
||||||
{
|
{
|
||||||
_httpProxyAddress = proxyHttpUri.OriginalString;
|
_httpProxyAddress = proxyHttpUri.OriginalString;
|
||||||
@@ -99,6 +103,10 @@ namespace GitHub.Runner.Sdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(httpsProxyAddress) && !Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var _))
|
||||||
|
{
|
||||||
|
httpsProxyAddress = PrependHttpIfMissing(httpsProxyAddress);
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(httpsProxyAddress) && Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var proxyHttpsUri))
|
if (!string.IsNullOrEmpty(httpsProxyAddress) && Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var proxyHttpsUri))
|
||||||
{
|
{
|
||||||
_httpsProxyAddress = proxyHttpsUri.OriginalString;
|
_httpsProxyAddress = proxyHttpsUri.OriginalString;
|
||||||
@@ -240,5 +248,20 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string PrependHttpIfMissing(string proxyAddress)
|
||||||
|
{
|
||||||
|
// much like in golang, see https://github.com/golang/net/blob/f5464ddb689c015d1abf4df78a806a54af977e6c/http/httpproxy/proxy.go#LL156C31-L156C31
|
||||||
|
if (!proxyAddress.StartsWith("http://", StringComparison.Ordinal) && !proxyAddress.StartsWith("https://", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var prependedProxyAddress = "http://" + proxyAddress;
|
||||||
|
if (Uri.TryCreate(prependedProxyAddress, UriKind.Absolute, out var _))
|
||||||
|
{
|
||||||
|
// if prepending http:// turns the proxyAddress into a valid Uri, then use that
|
||||||
|
return prependedProxyAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return proxyAddress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
namespace GitHub.Runner.Sdk
|
namespace GitHub.Runner.Sdk
|
||||||
{
|
{
|
||||||
@@ -48,5 +50,15 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
return credUri.Uri;
|
return credUri.Uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetGitHubRequestId(HttpResponseHeaders headers)
|
||||||
|
{
|
||||||
|
if (headers != null &&
|
||||||
|
headers.TryGetValues("x-github-request-id", out var headerValues))
|
||||||
|
{
|
||||||
|
return headerValues.FirstOrDefault();
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
|
||||||
{
|
{
|
||||||
settings.AllowAutoRedirect = true;
|
settings.AllowAutoRedirectForBroker = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove Invariant from the list of accepted languages.
|
// Remove Invariant from the list of accepted languages.
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using WebApi = GitHub.DistributedTask.WebApi;
|
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants;
|
using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using WebApi = GitHub.DistributedTask.WebApi;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -115,6 +115,14 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Result = TaskResult.Failed;
|
executionContext.Result = TaskResult.Failed;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
catch (InvalidActionArchiveException ex)
|
||||||
|
{
|
||||||
|
// Log the error and fail the PrepareActionsAsync Initialization.
|
||||||
|
Trace.Error($"Caught exception from PrepareActionsAsync Initialization: {ex}");
|
||||||
|
executionContext.InfrastructureError(ex.Message);
|
||||||
|
executionContext.Result = TaskResult.Failed;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
if (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables))
|
if (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables))
|
||||||
{
|
{
|
||||||
if (state.ImagesToPull.Count > 0)
|
if (state.ImagesToPull.Count > 0)
|
||||||
@@ -835,6 +843,12 @@ namespace GitHub.Runner.Worker
|
|||||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
using (var response = await httpClient.GetAsync(link))
|
using (var response = await httpClient.GetAsync(link))
|
||||||
{
|
{
|
||||||
|
var requestId = UrlUtil.GetGitHubRequestId(response.Headers);
|
||||||
|
if (!string.IsNullOrEmpty(requestId))
|
||||||
|
{
|
||||||
|
Trace.Info($"Request URL: {link} X-GitHub-Request-Id: {requestId} Http Status: {response.StatusCode}");
|
||||||
|
}
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
using (var result = await response.Content.ReadAsStreamAsync())
|
using (var result = await response.Content.ReadAsStreamAsync())
|
||||||
@@ -849,7 +863,7 @@ namespace GitHub.Runner.Worker
|
|||||||
else if (response.StatusCode == HttpStatusCode.NotFound)
|
else if (response.StatusCode == HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
// It doesn't make sense to retry in this case, so just stop
|
// It doesn't make sense to retry in this case, so just stop
|
||||||
throw new ActionNotFoundException(new Uri(link));
|
throw new ActionNotFoundException(new Uri(link), requestId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -901,7 +915,14 @@ namespace GitHub.Runner.Worker
|
|||||||
Directory.CreateDirectory(stagingDirectory);
|
Directory.CreateDirectory(stagingDirectory);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
|
try
|
||||||
|
{
|
||||||
|
ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
|
||||||
|
}
|
||||||
|
catch (InvalidDataException e)
|
||||||
|
{
|
||||||
|
throw new InvalidActionArchiveException($"Can't un-zip archive file: {archiveFile}. action being checked out: {downloadInfo.NameWithOwner}@{downloadInfo.Ref}. error: {e}.");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
string tar = WhichUtil.Which("tar", require: true, trace: Trace);
|
string tar = WhichUtil.Which("tar", require: true, trace: Trace);
|
||||||
|
|
||||||
@@ -927,7 +948,7 @@ namespace GitHub.Runner.Worker
|
|||||||
int exitCode = await processInvoker.ExecuteAsync(stagingDirectory, tar, $"-xzf \"{archiveFile}\"", null, executionContext.CancellationToken);
|
int exitCode = await processInvoker.ExecuteAsync(stagingDirectory, tar, $"-xzf \"{archiveFile}\"", null, executionContext.CancellationToken);
|
||||||
if (exitCode != 0)
|
if (exitCode != 0)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. return code: {exitCode}.");
|
throw new InvalidActionArchiveException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. Action being checked out: {downloadInfo.NameWithOwner}@{downloadInfo.Ref}. return code: {exitCode}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1042,7 +1063,7 @@ namespace GitHub.Runner.Worker
|
|||||||
if (actionDefinitionData.Execution.ExecutionType == ActionExecutionType.Container)
|
if (actionDefinitionData.Execution.ExecutionType == ActionExecutionType.Container)
|
||||||
{
|
{
|
||||||
var containerAction = actionDefinitionData.Execution as ContainerActionExecutionData;
|
var containerAction = actionDefinitionData.Execution as ContainerActionExecutionData;
|
||||||
if (containerAction.Image.EndsWith("Dockerfile") || containerAction.Image.EndsWith("dockerfile"))
|
if (DockerUtil.IsDockerfile(containerAction.Image))
|
||||||
{
|
{
|
||||||
var dockerFileFullPath = Path.Combine(actionEntryDirectory, containerAction.Image);
|
var dockerFileFullPath = Path.Combine(actionEntryDirectory, containerAction.Image);
|
||||||
executionContext.Debug($"Dockerfile for action: '{dockerFileFullPath}'.");
|
executionContext.Debug($"Dockerfile for action: '{dockerFileFullPath}'.");
|
||||||
@@ -1127,8 +1148,16 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var fullPath = IOUtil.ResolvePath(actionEntryDirectory, "."); // resolve full path without access filesystem.
|
var reference = repositoryReference.Name;
|
||||||
throw new InvalidOperationException($"Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '{fullPath}'. Did you forget to run actions/checkout before running your local action?");
|
if (!string.IsNullOrEmpty(repositoryReference.Path))
|
||||||
|
{
|
||||||
|
reference = $"{reference}/{repositoryReference.Path}";
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(repositoryReference.Ref))
|
||||||
|
{
|
||||||
|
reference = $"{reference}@{repositoryReference.Ref}";
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException($"Can't find 'action.yml', 'action.yaml' or 'Dockerfile' for action '{reference}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -449,7 +449,8 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase) ||
|
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase))
|
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(usingToken.Value, "node20", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(mainToken?.Value))
|
if (string.IsNullOrEmpty(mainToken?.Value))
|
||||||
{
|
{
|
||||||
@@ -489,7 +490,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12' or 'node16' instead.");
|
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12', 'node16' or 'node20' instead.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pluginToken != null)
|
else if (pluginToken != null)
|
||||||
@@ -500,7 +501,7 @@ namespace GitHub.Runner.Worker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.");
|
throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12', 'node16' or 'node20'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConvertInputs(
|
private void ConvertInputs(
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
public class ActionNotFoundException : Exception
|
public class ActionNotFoundException : Exception
|
||||||
{
|
{
|
||||||
public ActionNotFoundException(Uri actionUri)
|
public ActionNotFoundException(Uri actionUri, string requestId)
|
||||||
: base(FormatMessage(actionUri))
|
: base(FormatMessage(actionUri, requestId))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +25,13 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FormatMessage(Uri actionUri)
|
private static string FormatMessage(Uri actionUri, string requestId)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(requestId))
|
||||||
|
{
|
||||||
|
return $"An action could not be found at the URI '{actionUri}' ({requestId})";
|
||||||
|
}
|
||||||
|
|
||||||
return $"An action could not be found at the URI '{actionUri}'";
|
return $"An action could not be found at the URI '{actionUri}'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker.Container
|
namespace GitHub.Runner.Worker.Container
|
||||||
@@ -65,6 +66,16 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsDockerfile(string image)
|
||||||
|
{
|
||||||
|
if (image.StartsWith("docker://", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var imageWithoutPath = image.Split('/').Last();
|
||||||
|
return imageWithoutPath.StartsWith("Dockerfile.", StringComparison.OrdinalIgnoreCase) || imageWithoutPath.EndsWith("Dockerfile", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
public static string CreateEscapedOption(string flag, string key)
|
public static string CreateEscapedOption(string flag, string key)
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(key))
|
if (String.IsNullOrEmpty(key))
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace GitHub.Runner.Worker
|
|||||||
// \_layout\_work\_temp\[jobname-support]\files\environment.txt
|
// \_layout\_work\_temp\[jobname-support]\files\environment.txt
|
||||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||||
RunnerSettings settings = configurationStore.GetSettings();
|
RunnerSettings settings = configurationStore.GetSettings();
|
||||||
int runnerId = settings.AgentId;
|
ulong runnerId = settings.AgentId;
|
||||||
string runnerName = settings.AgentName;
|
string runnerName = settings.AgentName;
|
||||||
int poolId = settings.PoolId;
|
int poolId = settings.PoolId;
|
||||||
|
|
||||||
|
|||||||
@@ -78,11 +78,12 @@ namespace GitHub.Runner.Worker
|
|||||||
List<string> StepEnvironmentOverrides { get; }
|
List<string> StepEnvironmentOverrides { get; }
|
||||||
|
|
||||||
ExecutionContext Root { get; }
|
ExecutionContext Root { get; }
|
||||||
|
ExecutionContext Parent { get; }
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
||||||
void CancelToken();
|
void CancelToken();
|
||||||
IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null);
|
IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null, TimeSpan? timeout = null);
|
||||||
IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
|
IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
@@ -264,6 +265,14 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutionContext Parent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _parentExecutionContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public JobContext JobContext
|
public JobContext JobContext
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -348,7 +357,8 @@ namespace GitHub.Runner.Worker
|
|||||||
bool isEmbedded = false,
|
bool isEmbedded = false,
|
||||||
CancellationTokenSource cancellationTokenSource = null,
|
CancellationTokenSource cancellationTokenSource = null,
|
||||||
Guid embeddedId = default(Guid),
|
Guid embeddedId = default(Guid),
|
||||||
string siblingScopeName = null)
|
string siblingScopeName = null,
|
||||||
|
TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
|
|
||||||
@@ -377,6 +387,12 @@ namespace GitHub.Runner.Worker
|
|||||||
child.ExpressionFunctions.Add(item);
|
child.ExpressionFunctions.Add(item);
|
||||||
}
|
}
|
||||||
child._cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource();
|
child._cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource();
|
||||||
|
if (timeout != null)
|
||||||
|
{
|
||||||
|
// composite steps inherit the timeout from the parent, set by https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepstimeout-minutes
|
||||||
|
child.SetTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
child.EchoOnActionCommand = EchoOnActionCommand;
|
child.EchoOnActionCommand = EchoOnActionCommand;
|
||||||
|
|
||||||
if (recordOrder != null)
|
if (recordOrder != null)
|
||||||
@@ -406,7 +422,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An embedded execution context shares the same record ID, record name, logger,
|
/// An embedded execution context shares the same record ID, record name, logger,
|
||||||
/// and a linked cancellation token.
|
/// but NOT the cancellation token (just like workflow steps contexts - they don't share a token)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IExecutionContext CreateEmbeddedChild(
|
public IExecutionContext CreateEmbeddedChild(
|
||||||
string scopeName,
|
string scopeName,
|
||||||
@@ -416,7 +432,7 @@ namespace GitHub.Runner.Worker
|
|||||||
Dictionary<string, string> intraActionState = null,
|
Dictionary<string, string> intraActionState = null,
|
||||||
string siblingScopeName = null)
|
string siblingScopeName = null)
|
||||||
{
|
{
|
||||||
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName);
|
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: null, intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName, timeout: GetRemainingTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(string currentOperation = null)
|
public void Start(string currentOperation = null)
|
||||||
@@ -477,28 +493,32 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
PublishStepTelemetry();
|
PublishStepTelemetry();
|
||||||
|
|
||||||
var stepResult = new StepResult
|
if (_record.RecordType == "Task")
|
||||||
{
|
{
|
||||||
ExternalID = _record.Id,
|
var stepResult = new StepResult
|
||||||
Conclusion = _record.Result ?? TaskResult.Succeeded,
|
|
||||||
Status = _record.State,
|
|
||||||
Number = _record.Order,
|
|
||||||
Name = _record.Name,
|
|
||||||
StartedAt = _record.StartTime,
|
|
||||||
CompletedAt = _record.FinishTime,
|
|
||||||
Annotations = new List<Annotation>()
|
|
||||||
};
|
|
||||||
|
|
||||||
_record.Issues?.ForEach(issue =>
|
|
||||||
{
|
|
||||||
var annotation = issue.ToAnnotation();
|
|
||||||
if (annotation != null)
|
|
||||||
{
|
{
|
||||||
stepResult.Annotations.Add(annotation.Value);
|
ExternalID = _record.Id,
|
||||||
}
|
Conclusion = _record.Result ?? TaskResult.Succeeded,
|
||||||
});
|
Status = _record.State,
|
||||||
|
Number = _record.Order,
|
||||||
|
Name = _record.Name,
|
||||||
|
StartedAt = _record.StartTime,
|
||||||
|
CompletedAt = _record.FinishTime,
|
||||||
|
Annotations = new List<Annotation>()
|
||||||
|
};
|
||||||
|
|
||||||
|
_record.Issues?.ForEach(issue =>
|
||||||
|
{
|
||||||
|
var annotation = issue.ToAnnotation();
|
||||||
|
if (annotation != null)
|
||||||
|
{
|
||||||
|
stepResult.Annotations.Add(annotation.Value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Global.StepsResult.Add(stepResult);
|
||||||
|
}
|
||||||
|
|
||||||
Global.StepsResult.Add(stepResult);
|
|
||||||
|
|
||||||
if (Root != this)
|
if (Root != this)
|
||||||
{
|
{
|
||||||
@@ -593,9 +613,33 @@ namespace GitHub.Runner.Worker
|
|||||||
if (timeout != null)
|
if (timeout != null)
|
||||||
{
|
{
|
||||||
_cancellationTokenSource.CancelAfter(timeout.Value);
|
_cancellationTokenSource.CancelAfter(timeout.Value);
|
||||||
|
m_timeoutStartedAt = DateTime.UtcNow;
|
||||||
|
m_timeout = timeout.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DateTime? m_timeoutStartedAt;
|
||||||
|
TimeSpan? m_timeout;
|
||||||
|
public TimeSpan? GetRemainingTimeout()
|
||||||
|
{
|
||||||
|
if (m_timeoutStartedAt != null && m_timeout != null)
|
||||||
|
{
|
||||||
|
var elapsedSinceTimeoutSet = DateTime.UtcNow - m_timeoutStartedAt.Value;
|
||||||
|
var remainingTimeout = m_timeout.Value - elapsedSinceTimeoutSet;
|
||||||
|
if (remainingTimeout.Ticks > 0)
|
||||||
|
{
|
||||||
|
return remainingTimeout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there was a timeout and it has expired
|
||||||
|
return TimeSpan.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no timeout was ever set
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void Progress(int percentage, string currentOperation = null)
|
public void Progress(int percentage, string currentOperation = null)
|
||||||
{
|
{
|
||||||
if (percentage > 100 || percentage < 0)
|
if (percentage > 100 || percentage < 0)
|
||||||
@@ -763,9 +807,9 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
Global.Variables = new Variables(HostContext, variables);
|
Global.Variables = new Variables(HostContext, variables);
|
||||||
|
|
||||||
if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo12") ?? false)
|
if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo16") ?? false)
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion, "node12");
|
Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion, "node16");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environment variables shared across all actions
|
// Environment variables shared across all actions
|
||||||
@@ -1355,6 +1399,12 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
foreach (var key in dict.Keys.ToList())
|
foreach (var key in dict.Keys.ToList())
|
||||||
{
|
{
|
||||||
|
if (key == PipelineTemplateConstants.HostWorkspace)
|
||||||
|
{
|
||||||
|
// The HostWorkspace context var is excluded so that there is a var that always points to the host path.
|
||||||
|
// This var can be used to translate back from container paths, e.g. in HashFilesFunction, which always runs on the host machine
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (dict[key] is StringContextData)
|
if (dict[key] is StringContextData)
|
||||||
{
|
{
|
||||||
var value = dict[key].ToString();
|
var value = dict[key].ToString();
|
||||||
@@ -1401,7 +1451,15 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public void Error(string format, params Object[] args)
|
public void Error(string format, params Object[] args)
|
||||||
{
|
{
|
||||||
_executionContext.Error(string.Format(CultureInfo.CurrentCulture, format, args));
|
/* TraceWriter should be used for logging and not creating erros. */
|
||||||
|
if (logTemplateErrorsAsDebugMessages())
|
||||||
|
{
|
||||||
|
_executionContext.Debug(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_executionContext.Error(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Info(string format, params Object[] args)
|
public void Info(string format, params Object[] args)
|
||||||
@@ -1414,8 +1472,18 @@ namespace GitHub.Runner.Worker
|
|||||||
// todo: switch to verbose?
|
// todo: switch to verbose?
|
||||||
_executionContext.Debug(string.Format(CultureInfo.CurrentCulture, $"{format}", args));
|
_executionContext.Debug(string.Format(CultureInfo.CurrentCulture, $"{format}", args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool logTemplateErrorsAsDebugMessages()
|
||||||
|
{
|
||||||
|
if (_executionContext.Global.Variables.TryGetValue(Constants.Runner.Features.LogTemplateErrorsAsDebugMessages, out var logErrorsAsDebug))
|
||||||
|
{
|
||||||
|
return StringUtil.ConvertToBoolean(logErrorsAsDebug, defaultValue: false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class WellKnownTags
|
public static class WellKnownTags
|
||||||
{
|
{
|
||||||
public static readonly string Section = "##[section]";
|
public static readonly string Section = "##[section]";
|
||||||
|
|||||||
@@ -26,11 +26,18 @@ namespace GitHub.Runner.Worker.Expressions
|
|||||||
ArgUtil.NotNull(githubContextData, nameof(githubContextData));
|
ArgUtil.NotNull(githubContextData, nameof(githubContextData));
|
||||||
var githubContext = githubContextData as DictionaryContextData;
|
var githubContext = githubContextData as DictionaryContextData;
|
||||||
ArgUtil.NotNull(githubContext, nameof(githubContext));
|
ArgUtil.NotNull(githubContext, nameof(githubContext));
|
||||||
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out var workspace);
|
|
||||||
|
if (!githubContext.TryGetValue(PipelineTemplateConstants.HostWorkspace, out var workspace))
|
||||||
|
{
|
||||||
|
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out workspace);
|
||||||
|
}
|
||||||
|
ArgUtil.NotNull(workspace, nameof(workspace));
|
||||||
|
|
||||||
var workspaceData = workspace as StringContextData;
|
var workspaceData = workspace as StringContextData;
|
||||||
ArgUtil.NotNull(workspaceData, nameof(workspaceData));
|
ArgUtil.NotNull(workspaceData, nameof(workspaceData));
|
||||||
|
|
||||||
string githubWorkspace = workspaceData.Value;
|
string githubWorkspace = workspaceData.Value;
|
||||||
|
|
||||||
bool followSymlink = false;
|
bool followSymlink = false;
|
||||||
List<string> patterns = new();
|
List<string> patterns = new();
|
||||||
var firstParameter = true;
|
var firstParameter = true;
|
||||||
|
|||||||
@@ -141,6 +141,28 @@ namespace GitHub.Runner.Worker
|
|||||||
var pairs = new EnvFileKeyValuePairs(context, filePath);
|
var pairs = new EnvFileKeyValuePairs(context, filePath);
|
||||||
foreach (var pair in pairs)
|
foreach (var pair in pairs)
|
||||||
{
|
{
|
||||||
|
var isBlocked = false;
|
||||||
|
foreach (var blocked in _setEnvBlockList)
|
||||||
|
{
|
||||||
|
if (string.Equals(blocked, pair.Key, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Log Telemetry and let user know they shouldn't do this
|
||||||
|
var issue = new Issue()
|
||||||
|
{
|
||||||
|
Type = IssueType.Error,
|
||||||
|
Message = $"Can't store {blocked} output parameter using '$GITHUB_ENV' command."
|
||||||
|
};
|
||||||
|
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = $"{Constants.Runner.UnsupportedCommand}_{pair.Key}";
|
||||||
|
context.AddIssue(issue, ExecutionContextLogOptions.Default);
|
||||||
|
|
||||||
|
isBlocked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isBlocked)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
SetEnvironmentVariable(context, pair.Key, pair.Value);
|
SetEnvironmentVariable(context, pair.Key, pair.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,6 +176,11 @@ namespace GitHub.Runner.Worker
|
|||||||
context.SetEnvContext(name, value);
|
context.SetEnvContext(name, value);
|
||||||
context.Debug($"{name}='{value}'");
|
context.Debug($"{name}='{value}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string[] _setEnvBlockList =
|
||||||
|
{
|
||||||
|
"NODE_OPTIONS"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CreateStepSummaryCommand : RunnerService, IFileCommandExtension
|
public sealed class CreateStepSummaryCommand : RunnerService, IFileCommandExtension
|
||||||
|
|||||||
@@ -310,6 +310,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Mark job as cancelled
|
// Mark job as cancelled
|
||||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||||
|
step.ExecutionContext.SetGitHubContext("action_status", (ExecutionContext.Root.Result?.ToActionResult() ?? ActionResult.Cancelled).ToString().ToLowerInvariant());
|
||||||
|
|
||||||
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
||||||
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
{
|
{
|
||||||
Data.Image = Data.Image.Substring("docker://".Length);
|
Data.Image = Data.Image.Substring("docker://".Length);
|
||||||
}
|
}
|
||||||
else if (Data.Image.EndsWith("Dockerfile") || Data.Image.EndsWith("dockerfile"))
|
else if (DockerUtil.IsDockerfile(Data.Image))
|
||||||
{
|
{
|
||||||
// ensure docker file exist
|
// ensure docker file exist
|
||||||
dockerFile = Path.Combine(ActionDirectory, Data.Image);
|
dockerFile = Path.Combine(ActionDirectory, Data.Image);
|
||||||
@@ -228,6 +228,10 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
||||||
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
||||||
}
|
}
|
||||||
|
if (systemConnection.Data.TryGetValue("ResultsServiceUrl", out var resultsUrl) && !string.IsNullOrEmpty(resultsUrl))
|
||||||
|
{
|
||||||
|
Environment["ACTIONS_RESULTS_URL"] = resultsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var variable in this.Environment)
|
foreach (var variable in this.Environment)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,18 +58,31 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
var nodeData = data as NodeJSActionExecutionData;
|
var nodeData = data as NodeJSActionExecutionData;
|
||||||
|
|
||||||
// With node12 EoL in 04/2022, we want to be able to uniformly upgrade all JS actions to node16 from the server
|
// With node12 EoL in 04/2022, we want to be able to uniformly upgrade all JS actions to node16 from the server
|
||||||
if (string.Equals(nodeData.NodeVersion, "node12", StringComparison.InvariantCultureIgnoreCase) &&
|
if (string.Equals(nodeData.NodeVersion, "node12", StringComparison.InvariantCultureIgnoreCase))
|
||||||
(executionContext.Global.Variables.GetBoolean("DistributedTask.ForceGithubJavascriptActionsToNode16") ?? false))
|
|
||||||
{
|
{
|
||||||
// The user can opt out of this behaviour by setting this variable to true, either setting 'env' in their workflow or as an environment variable on their machine
|
var repoAction = action as Pipelines.RepositoryPathReference;
|
||||||
executionContext.Global.EnvironmentVariables.TryGetValue(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, out var workflowOptOut);
|
if (repoAction != null)
|
||||||
var isWorkflowOptOutSet = !string.IsNullOrEmpty(workflowOptOut);
|
|
||||||
var isLocalOptOut = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion));
|
|
||||||
bool isOptOut = isWorkflowOptOutSet ? StringUtil.ConvertToBoolean(workflowOptOut) : isLocalOptOut;
|
|
||||||
if (!isOptOut)
|
|
||||||
{
|
{
|
||||||
nodeData.NodeVersion = "node16";
|
var warningActions = new HashSet<string>();
|
||||||
|
if (executionContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
|
||||||
|
{
|
||||||
|
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
string repoActionFullName;
|
||||||
|
if (string.IsNullOrEmpty(repoAction.Name))
|
||||||
|
{
|
||||||
|
repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
|
||||||
|
}
|
||||||
|
|
||||||
|
warningActions.Add(repoActionFullName);
|
||||||
|
executionContext.Global.Variables.Set("Node16ForceActionsWarnings", StringUtil.ConvertToJson(warningActions));
|
||||||
}
|
}
|
||||||
|
nodeData.NodeVersion = "node16";
|
||||||
}
|
}
|
||||||
(handler as INodeScriptActionHandler).Data = nodeData;
|
(handler as INodeScriptActionHandler).Data = nodeData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
Environment["ACTIONS_ID_TOKEN_REQUEST_URL"] = generateIdTokenUrl;
|
||||||
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
Environment["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = systemConnection.Authorization.Parameters[EndpointAuthorizationParameters.AccessToken];
|
||||||
}
|
}
|
||||||
|
if (systemConnection.Data.TryGetValue("ResultsServiceUrl", out var resultsUrl) && !string.IsNullOrEmpty(resultsUrl))
|
||||||
|
{
|
||||||
|
Environment["ACTIONS_RESULTS_URL"] = resultsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the target script.
|
// Resolve the target script.
|
||||||
string target = null;
|
string target = null;
|
||||||
@@ -98,20 +102,14 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OS_OSX || OS_WINDOWS
|
|
||||||
if (string.Equals(Data.NodeVersion, "node12", StringComparison.OrdinalIgnoreCase) &&
|
if (string.Equals(Data.NodeVersion, "node12", StringComparison.OrdinalIgnoreCase) &&
|
||||||
Constants.Runner.PlatformArchitecture.Equals(Constants.Architecture.Arm64))
|
Constants.Runner.PlatformArchitecture.Equals(Constants.Architecture.Arm64))
|
||||||
{
|
{
|
||||||
#if OS_OSX
|
ExecutionContext.Output($"The node12 is not supported. Use node16 instead.");
|
||||||
ExecutionContext.Output($"The node12 is not supported on macOS ARM64 platform. Use node16 instead.");
|
|
||||||
#elif OS_WINDOWS
|
|
||||||
ExecutionContext.Output($"The node12 is not supported on windows ARM64 platform. Use node16 instead.");
|
|
||||||
#endif
|
|
||||||
Data.NodeVersion = "node16";
|
Data.NodeVersion = "node16";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
string forcedNodeVersion = System.Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedActionsNodeVersion);
|
|
||||||
|
|
||||||
|
string forcedNodeVersion = System.Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedActionsNodeVersion);
|
||||||
if (forcedNodeVersion == "node16" && Data.NodeVersion != "node16")
|
if (forcedNodeVersion == "node16" && Data.NodeVersion != "node16")
|
||||||
{
|
{
|
||||||
Data.NodeVersion = "node16";
|
Data.NodeVersion = "node16";
|
||||||
@@ -136,29 +134,6 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Remove environment variable that may cause conflicts with the node within the runner.
|
// Remove environment variable that may cause conflicts with the node within the runner.
|
||||||
Environment.Remove("NODE_ICU_DATA"); // https://github.com/actions/runner/issues/795
|
Environment.Remove("NODE_ICU_DATA"); // https://github.com/actions/runner/issues/795
|
||||||
|
|
||||||
if (Data.NodeVersion == "node12" && (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.Node12Warning) ?? false))
|
|
||||||
{
|
|
||||||
var repoAction = Action as RepositoryPathReference;
|
|
||||||
var warningActions = new HashSet<string>();
|
|
||||||
if (ExecutionContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
|
|
||||||
{
|
|
||||||
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings);
|
|
||||||
}
|
|
||||||
|
|
||||||
var repoActionFullName = "";
|
|
||||||
if (string.IsNullOrEmpty(repoAction.Name))
|
|
||||||
{
|
|
||||||
repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
|
|
||||||
}
|
|
||||||
|
|
||||||
warningActions.Add(repoActionFullName);
|
|
||||||
ExecutionContext.Global.Variables.Set("Node12ActionsWarnings", StringUtil.ConvertToJson(warningActions));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
||||||
using (var stderrManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
using (var stderrManager = new OutputManager(ExecutionContext, ActionCommandManager))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -15,6 +16,7 @@ using GitHub.DistributedTask.WebApi;
|
|||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Services.Common;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
@@ -34,12 +36,13 @@ namespace GitHub.Runner.Worker
|
|||||||
public interface IJobExtension : IRunnerService
|
public interface IJobExtension : IRunnerService
|
||||||
{
|
{
|
||||||
Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message);
|
Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message);
|
||||||
void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
|
Task FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class JobExtension : RunnerService, IJobExtension
|
public sealed class JobExtension : RunnerService, IJobExtension
|
||||||
{
|
{
|
||||||
private readonly HashSet<string> _existingProcesses = new(StringComparer.OrdinalIgnoreCase);
|
private readonly HashSet<string> _existingProcesses = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly List<Task<string>> _connectivityCheckTasks = new();
|
||||||
private bool _processCleanup;
|
private bool _processCleanup;
|
||||||
private string _processLookupId = $"github_{Guid.NewGuid()}";
|
private string _processLookupId = $"github_{Guid.NewGuid()}";
|
||||||
private CancellationTokenSource _diskSpaceCheckToken = new();
|
private CancellationTokenSource _diskSpaceCheckToken = new();
|
||||||
@@ -175,7 +178,14 @@ namespace GitHub.Runner.Worker
|
|||||||
context.Debug("Update context data");
|
context.Debug("Update context data");
|
||||||
string _workDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
string _workDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
context.SetRunnerContext("workspace", Path.Combine(_workDirectory, trackingConfig.PipelineDirectory));
|
context.SetRunnerContext("workspace", Path.Combine(_workDirectory, trackingConfig.PipelineDirectory));
|
||||||
context.SetGitHubContext("workspace", Path.Combine(_workDirectory, trackingConfig.WorkspaceDirectory));
|
|
||||||
|
var githubWorkspace = Path.Combine(_workDirectory, trackingConfig.WorkspaceDirectory);
|
||||||
|
if (jobContext.Global.Variables.GetBoolean(Constants.Runner.Features.UseContainerPathForTemplate) ?? false)
|
||||||
|
{
|
||||||
|
// This value is used to translate paths from the container path back to the host path.
|
||||||
|
context.SetGitHubContext("host-workspace", githubWorkspace);
|
||||||
|
}
|
||||||
|
context.SetGitHubContext("workspace", githubWorkspace);
|
||||||
|
|
||||||
// Temporary hack for GHES alpha
|
// Temporary hack for GHES alpha
|
||||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||||
@@ -421,6 +431,22 @@ namespace GitHub.Runner.Worker
|
|||||||
_diskSpaceCheckTask = CheckDiskSpaceAsync(context, _diskSpaceCheckToken.Token);
|
_diskSpaceCheckTask = CheckDiskSpaceAsync(context, _diskSpaceCheckToken.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check server connectivity in background
|
||||||
|
ServiceEndpoint systemConnection = message.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (systemConnection.Data.TryGetValue("ConnectivityChecks", out var connectivityChecksPayload) &&
|
||||||
|
!string.IsNullOrEmpty(connectivityChecksPayload))
|
||||||
|
{
|
||||||
|
Trace.Info($"Start checking server connectivity.");
|
||||||
|
var checkUrls = StringUtil.ConvertFromJson<List<string>>(connectivityChecksPayload);
|
||||||
|
if (checkUrls?.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var checkUrl in checkUrls)
|
||||||
|
{
|
||||||
|
_connectivityCheckTasks.Add(CheckConnectivity(checkUrl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException ex) when (jobContext.CancellationToken.IsCancellationRequested)
|
catch (OperationCanceledException ex) when (jobContext.CancellationToken.IsCancellationRequested)
|
||||||
@@ -465,7 +491,7 @@ namespace GitHub.Runner.Worker
|
|||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
|
public async Task FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
||||||
@@ -642,6 +668,28 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
_diskSpaceCheckToken.Cancel();
|
_diskSpaceCheckToken.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect server connectivity check result
|
||||||
|
if (_connectivityCheckTasks.Count > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trace.Info($"Wait for all connectivity checks to finish.");
|
||||||
|
await Task.WhenAll(_connectivityCheckTasks);
|
||||||
|
foreach (var check in _connectivityCheckTasks)
|
||||||
|
{
|
||||||
|
var result = await check;
|
||||||
|
Trace.Info($"Connectivity check result: {result}");
|
||||||
|
context.Global.JobTelemetry.Add(new JobTelemetry() { Type = JobTelemetryType.ConnectivityCheck, Message = result });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.Error($"Fail to check server connectivity.");
|
||||||
|
Trace.Error(ex);
|
||||||
|
context.Global.JobTelemetry.Add(new JobTelemetry() { Type = JobTelemetryType.ConnectivityCheck, Message = $"Fail to check server connectivity. {ex.Message}" });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -657,6 +705,37 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> CheckConnectivity(string endpointUrl)
|
||||||
|
{
|
||||||
|
Trace.Info($"Check server connectivity for {endpointUrl}.");
|
||||||
|
string result = string.Empty;
|
||||||
|
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||||
|
using (var httpClient = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
|
var response = await httpClient.GetAsync(endpointUrl, timeoutTokenSource.Token);
|
||||||
|
result = $"{endpointUrl}: {response.StatusCode}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is OperationCanceledException && timeoutTokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Trace.Error($"Request timeout during connectivity check: {ex}");
|
||||||
|
result = $"{endpointUrl}: timeout";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.Error($"Catch exception during connectivity check: {ex}");
|
||||||
|
result = $"{endpointUrl}: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CheckDiskSpaceAsync(IExecutionContext context, CancellationToken token)
|
private async Task CheckDiskSpaceAsync(IExecutionContext context, CancellationToken token)
|
||||||
{
|
{
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Net.Http.Headers;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
using GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
@@ -83,7 +84,14 @@ namespace GitHub.Runner.Worker
|
|||||||
Trace.Info($"Creating job server with URL: {jobServerUrl}");
|
Trace.Info($"Creating job server with URL: {jobServerUrl}");
|
||||||
// jobServerQueue is the throttling reporter.
|
// jobServerQueue is the throttling reporter.
|
||||||
_jobServerQueue = HostContext.GetService<IJobServerQueue>();
|
_jobServerQueue = HostContext.GetService<IJobServerQueue>();
|
||||||
VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential, new DelegatingHandler[] { new ThrottlingReportHandler(_jobServerQueue) });
|
var delegatingHandlers = new List<DelegatingHandler>() { new ThrottlingReportHandler(_jobServerQueue) };
|
||||||
|
message.Variables.TryGetValue("Actions.EnableHttpRedirects", out VariableValue enableHttpRedirects);
|
||||||
|
if (StringUtil.ConvertToBoolean(enableHttpRedirects?.Value) &&
|
||||||
|
!StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_NO_HTTP_REDIRECTS")))
|
||||||
|
{
|
||||||
|
delegatingHandlers.Add(new RedirectMessageHandler(Trace));
|
||||||
|
}
|
||||||
|
VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential, delegatingHandlers);
|
||||||
await jobServer.ConnectAsync(jobConnection);
|
await jobServer.ConnectAsync(jobConnection);
|
||||||
|
|
||||||
_jobServerQueue.Start(message);
|
_jobServerQueue.Start(message);
|
||||||
@@ -228,7 +236,7 @@ namespace GitHub.Runner.Worker
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Trace.Info("Finalize job.");
|
Trace.Info("Finalize job.");
|
||||||
jobExtension.FinalizeJob(jobContext, message, jobStartTimeUtc);
|
await jobExtension.FinalizeJob(jobContext, message, jobStartTimeUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Info($"Job result after all job steps finish: {jobContext.Result ?? TaskResult.Succeeded}");
|
Trace.Info($"Job result after all job steps finish: {jobContext.Result ?? TaskResult.Succeeded}");
|
||||||
@@ -268,10 +276,10 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
jobContext.Debug($"Finishing: {message.JobDisplayName}");
|
jobContext.Debug($"Finishing: {message.JobDisplayName}");
|
||||||
TaskResult result = jobContext.Complete(taskResult);
|
TaskResult result = jobContext.Complete(taskResult);
|
||||||
if (jobContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
|
if (jobContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
|
||||||
{
|
{
|
||||||
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings));
|
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings));
|
||||||
jobContext.Warning(string.Format(Constants.Runner.Node12DetectedAfterEndOfLife, actions));
|
jobContext.Warning(string.Format(Constants.Runner.EnforcedNode12DetectedAfterEndOfLife, actions));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to clean temp after file upload since they may be pending fileupload still use the TEMP dir.
|
// Make sure to clean temp after file upload since they may be pending fileupload still use the TEMP dir.
|
||||||
@@ -283,6 +291,13 @@ namespace GitHub.Runner.Worker
|
|||||||
// Make sure we don't submit secrets as telemetry
|
// Make sure we don't submit secrets as telemetry
|
||||||
MaskTelemetrySecrets(jobContext.Global.JobTelemetry);
|
MaskTelemetrySecrets(jobContext.Global.JobTelemetry);
|
||||||
|
|
||||||
|
// Get environment url
|
||||||
|
string environmentUrl = null;
|
||||||
|
if (jobContext.ActionsEnvironment?.Url is StringToken urlStringToken)
|
||||||
|
{
|
||||||
|
environmentUrl = urlStringToken.Value;
|
||||||
|
}
|
||||||
|
|
||||||
Trace.Info($"Raising job completed against run service");
|
Trace.Info($"Raising job completed against run service");
|
||||||
var completeJobRetryLimit = 5;
|
var completeJobRetryLimit = 5;
|
||||||
var exceptions = new List<Exception>();
|
var exceptions = new List<Exception>();
|
||||||
@@ -290,7 +305,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, result, jobContext.JobOutputs, jobContext.Global.StepsResult, jobContext.Global.JobAnnotations, default);
|
await runServer.CompleteJobAsync(message.Plan.PlanId, message.JobId, result, jobContext.JobOutputs, jobContext.Global.StepsResult, jobContext.Global.JobAnnotations, environmentUrl, default);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -360,10 +375,10 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jobContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
|
if (jobContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
|
||||||
{
|
{
|
||||||
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings));
|
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings));
|
||||||
jobContext.Warning(string.Format(Constants.Runner.Node12DetectedAfterEndOfLife, actions));
|
jobContext.Warning(string.Format(Constants.Runner.EnforcedNode12DetectedAfterEndOfLife, actions));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -213,7 +213,26 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
// ConfigureAwait(false) enables the continuation to be run outside any captured
|
// ConfigureAwait(false) enables the continuation to be run outside any captured
|
||||||
// SyncronizationContext (such as ASP.NET's) which keeps things from deadlocking...
|
// SyncronizationContext (such as ASP.NET's) which keeps things from deadlocking...
|
||||||
response = await m_messageInvoker.SendAsync(request, tokenSource.Token).ConfigureAwait(false);
|
|
||||||
|
var tmpResponse = await m_messageInvoker.SendAsync(request, tokenSource.Token).ConfigureAwait(false);
|
||||||
|
if (Settings.AllowAutoRedirectForBroker && tmpResponse.StatusCode == HttpStatusCode.Redirect)
|
||||||
|
{
|
||||||
|
//Dispose of the previous response
|
||||||
|
tmpResponse?.Dispose();
|
||||||
|
|
||||||
|
var location = tmpResponse.Headers.Location;
|
||||||
|
request = new HttpRequestMessage(HttpMethod.Get, location);
|
||||||
|
|
||||||
|
// Reapply the token to new redirected request
|
||||||
|
ApplyToken(request, token, applyICredentialsToWebProxy: lastResponseDemandedProxyAuth);
|
||||||
|
|
||||||
|
// Resend the request
|
||||||
|
response = await m_messageInvoker.SendAsync(request, tokenSource.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = tmpResponse;
|
||||||
|
}
|
||||||
|
|
||||||
traceInfo?.TraceRequestSendTime();
|
traceInfo?.TraceRequestSendTime();
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,16 @@ namespace GitHub.Services.Common
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether or not HttpClientHandler should follow redirect on outgoing broker requests
|
||||||
|
/// This is special since this also sends token in the request, where as default AllowAutoRedirect does not
|
||||||
|
/// </summary>
|
||||||
|
public Boolean AllowAutoRedirectForBroker
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether or not compression should be used on outgoing requests.
|
/// Gets or sets a value indicating whether or not compression should be used on outgoing requests.
|
||||||
/// The default value is true.
|
/// The default value is true.
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
public virtual async Task DeleteAgentAsync(
|
public virtual async Task DeleteAgentAsync(
|
||||||
int poolId,
|
int poolId,
|
||||||
int agentId,
|
ulong agentId,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -243,7 +243,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
public virtual Task<TaskAgent> ReplaceAgentAsync(
|
public virtual Task<TaskAgent> ReplaceAgentAsync(
|
||||||
int poolId,
|
int poolId,
|
||||||
int agentId,
|
ulong agentId,
|
||||||
TaskAgent agent,
|
TaskAgent agent,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
@@ -786,7 +786,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
public virtual Task<TaskAgent> UpdateAgentUpdateStateAsync(
|
public virtual Task<TaskAgent> UpdateAgentUpdateStateAsync(
|
||||||
int poolId,
|
int poolId,
|
||||||
int agentId,
|
ulong agentId,
|
||||||
string currentState,
|
string currentState,
|
||||||
string updateTrace,
|
string updateTrace,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
|
|||||||
@@ -82,5 +82,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
public const String WorkflowRoot = "workflow-root";
|
public const String WorkflowRoot = "workflow-root";
|
||||||
public const String WorkingDirectory = "working-directory";
|
public const String WorkingDirectory = "working-directory";
|
||||||
public const String Workspace = "workspace";
|
public const String Workspace = "workspace";
|
||||||
|
public const String HostWorkspace = "host-workspace";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AgentRefreshMessage(
|
public AgentRefreshMessage(
|
||||||
Int32 agentId,
|
ulong agentId,
|
||||||
String targetVersion,
|
String targetVersion,
|
||||||
TimeSpan? timeout = null)
|
TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public Int32 AgentId
|
public ulong AgentId
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
[DataContract]
|
[DataContract]
|
||||||
public sealed class DiagnosticLogMetadata
|
public sealed class DiagnosticLogMetadata
|
||||||
{
|
{
|
||||||
public DiagnosticLogMetadata(string agentName, int agentId, int poolId, string phaseName, string fileName, string phaseResult)
|
public DiagnosticLogMetadata(string agentName, ulong agentId, int poolId, string phaseName, string fileName, string phaseResult)
|
||||||
{
|
{
|
||||||
AgentName = agentName;
|
AgentName = agentName;
|
||||||
AgentId = agentId;
|
AgentId = agentId;
|
||||||
@@ -19,7 +19,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public int AgentId { get; set; }
|
public ulong AgentId { get; set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public int PoolId { get; set; }
|
public int PoolId { get; set; }
|
||||||
|
|||||||
@@ -2516,4 +2516,23 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public sealed class InvalidActionArchiveException : DistributedTaskException
|
||||||
|
{
|
||||||
|
public InvalidActionArchiveException(String message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidActionArchiveException(String message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private InvalidActionArchiveException(SerializationInfo info, StreamingContext context)
|
||||||
|
: base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,8 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
|
|
||||||
[EnumMember]
|
[EnumMember]
|
||||||
ActionCommand = 1,
|
ActionCommand = 1,
|
||||||
|
|
||||||
|
[EnumMember]
|
||||||
|
ConnectivityCheck = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
|
|
||||||
public List<TaskAgent> ToTaskAgents()
|
public List<TaskAgent> ToTaskAgents()
|
||||||
{
|
{
|
||||||
return Runners.Select(runner => new TaskAgent() { Name = runner.Name }).ToList();
|
return Runners.Select(runner => new TaskAgent() { Id = runner.Id, Name = runner.Name }).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public Int32 Id
|
public ulong Id
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
internal set;
|
internal set;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public RunnerRefreshMessage(
|
public RunnerRefreshMessage(
|
||||||
Int32 runnerId,
|
ulong runnerId,
|
||||||
String targetVersion,
|
String targetVersion,
|
||||||
int? timeoutInSeconds = null)
|
int? timeoutInSeconds = null)
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public Int32 RunnerId
|
public ulong RunnerId
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// Identifier of the agent.
|
/// Identifier of the agent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public Int32 Id
|
public ulong Id
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
|||||||
@@ -26,5 +26,8 @@ namespace GitHub.Actions.RunService.WebApi
|
|||||||
|
|
||||||
[DataMember(Name = "annotations", EmitDefaultValue = false)]
|
[DataMember(Name = "annotations", EmitDefaultValue = false)]
|
||||||
public IList<Annotation> Annotations { get; set; }
|
public IList<Annotation> Annotations { get; set; }
|
||||||
|
|
||||||
|
[DataMember(Name = "environmentUrl", EmitDefaultValue = false)]
|
||||||
|
public string EnvironmentUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ namespace GitHub.Actions.RunService.WebApi
|
|||||||
Dictionary<String, VariableValue> outputs,
|
Dictionary<String, VariableValue> outputs,
|
||||||
IList<StepResult> stepResults,
|
IList<StepResult> stepResults,
|
||||||
IList<Annotation> jobAnnotations,
|
IList<Annotation> jobAnnotations,
|
||||||
|
string environmentUrl,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
HttpMethod httpMethod = new HttpMethod("POST");
|
HttpMethod httpMethod = new HttpMethod("POST");
|
||||||
@@ -110,7 +111,8 @@ namespace GitHub.Actions.RunService.WebApi
|
|||||||
Conclusion = result,
|
Conclusion = result,
|
||||||
Outputs = outputs,
|
Outputs = outputs,
|
||||||
StepResults = stepResults,
|
StepResults = stepResults,
|
||||||
Annotations = jobAnnotations
|
Annotations = jobAnnotations,
|
||||||
|
EnvironmentUrl = environmentUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
requestUri = new Uri(requestUri, "completejob");
|
requestUri = new Uri(requestUri, "completejob");
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.4" />
|
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.2.1" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.2.1" />
|
||||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.Cng" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.4.0" />
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ namespace GitHub.Actions.RunService.WebApi
|
|||||||
return result.Value;
|
return result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.StatusCode == HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
throw new AccessDeniedException(result.Error);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Exception($"Failed to get job message: {result.Error}");
|
throw new Exception($"Failed to get job message: {result.Error}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -145,6 +145,49 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
|
|||||||
Assert.Equal(expected, actual);
|
Assert.Equal(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
[InlineData("dockerhub/repo", false)]
|
||||||
|
[InlineData("debian:latest", false)]
|
||||||
|
[InlineData("something/dockerfileimage", false)]
|
||||||
|
[InlineData("ghcr.io/docker/dockerfile", true)] // should be false but might break the current workflows
|
||||||
|
[InlineData("Dockerfile", true)]
|
||||||
|
[InlineData("Dockerfile.", true)]
|
||||||
|
[InlineData(".Dockerfile", true)]
|
||||||
|
[InlineData(".Dockerfile.", false)]
|
||||||
|
[InlineData("dockerfile", true)]
|
||||||
|
[InlineData("dockerfile.", true)]
|
||||||
|
[InlineData(".dockerfile", true)]
|
||||||
|
[InlineData(".dockerfile.", false)]
|
||||||
|
[InlineData("Dockerfile.test", true)]
|
||||||
|
[InlineData("test.Dockerfile", true)]
|
||||||
|
[InlineData("docker/dockerfile:latest", false)]
|
||||||
|
[InlineData("/some/path/dockerfile:latest", false)]
|
||||||
|
[InlineData("dockerfile:latest", false)]
|
||||||
|
[InlineData("Dockerfile:latest", false)]
|
||||||
|
[InlineData("dockerfile-latest", false)]
|
||||||
|
[InlineData("Dockerfile-latest", false)]
|
||||||
|
[InlineData("dockerfile.latest", true)]
|
||||||
|
[InlineData("Dockerfile.latest", true)]
|
||||||
|
[InlineData("../dockerfile/dockerfileone", false)]
|
||||||
|
[InlineData("../Dockerfile/dockerfileone", false)]
|
||||||
|
[InlineData("../dockerfile.test", true)]
|
||||||
|
[InlineData("../Dockerfile.test", true)]
|
||||||
|
[InlineData("./dockerfile/image", false)]
|
||||||
|
[InlineData("./Dockerfile/image", false)]
|
||||||
|
[InlineData("example/Dockerfile.test", true)]
|
||||||
|
[InlineData("./example/Dockerfile.test", true)]
|
||||||
|
[InlineData("example/test.dockerfile", true)]
|
||||||
|
[InlineData("./example/test.dockerfile", true)]
|
||||||
|
[InlineData("docker://Dockerfile", false)]
|
||||||
|
[InlineData("docker://ubuntu:latest", false)]
|
||||||
|
public void IsDockerfile(string input, bool expected)
|
||||||
|
{
|
||||||
|
var actual = DockerUtil.IsDockerfile(input);
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
_runnerServer.Setup(x => x.AddAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
_runnerServer.Setup(x => x.AddAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
||||||
_runnerServer.Setup(x => x.ReplaceAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
_runnerServer.Setup(x => x.ReplaceAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
||||||
|
|
||||||
_dotcomServer.Setup(x => x.GetRunnersAsync(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgents));
|
_dotcomServer.Setup(x => x.GetRunnerByNameAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgents));
|
||||||
_dotcomServer.Setup(x => x.GetRunnerGroupsAsync(It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedPools));
|
_dotcomServer.Setup(x => x.GetRunnerGroupsAsync(It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedPools));
|
||||||
_dotcomServer.Setup(x => x.AddRunnerAsync(It.IsAny<int>(), It.IsAny<TaskAgent>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedRunner));
|
_dotcomServer.Setup(x => x.AddRunnerAsync(It.IsAny<int>(), It.IsAny<TaskAgent>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedRunner));
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
updater.Initialize(hc);
|
updater.Initialize(hc);
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -180,7 +180,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.200.0"), DownloadUrl = _packageUrl }));
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.200.0"), DownloadUrl = _packageUrl }));
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -234,7 +234,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
updater.Initialize(hc);
|
updater.Initialize(hc);
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -289,7 +289,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
updater.Initialize(hc);
|
updater.Initialize(hc);
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -344,7 +344,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = new List<TrimmedPackageMetadata>() { new TrimmedPackageMetadata() } }));
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = new List<TrimmedPackageMetadata>() { new TrimmedPackageMetadata() } }));
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -416,7 +416,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
updater.Initialize(hc);
|
updater.Initialize(hc);
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -490,7 +490,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -579,7 +579,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -681,7 +681,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
|
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
@@ -758,7 +758,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.999.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Callback((int p, int a, string s, string t) =>
|
.Callback((int p, ulong a, string s, string t) =>
|
||||||
{
|
{
|
||||||
hc.GetTrace().Info(t);
|
hc.GetTrace().Info(t);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -186,8 +186,8 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("http_proxy", "127.0.0.1:7777");
|
Environment.SetEnvironmentVariable("http_proxy", "#fragment");
|
||||||
Environment.SetEnvironmentVariable("https_proxy", "127.0.0.1");
|
Environment.SetEnvironmentVariable("https_proxy", "#fragment");
|
||||||
var proxy = new RunnerWebProxy();
|
var proxy = new RunnerWebProxy();
|
||||||
|
|
||||||
Assert.Null(proxy.HttpProxyAddress);
|
Assert.Null(proxy.HttpProxyAddress);
|
||||||
@@ -206,6 +206,68 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public void WebProxyPrependsHTTPforHTTP_PROXY_IfNoProtocol()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("http_proxy", "127.0.0.1:7777");
|
||||||
|
var proxy = new RunnerWebProxy();
|
||||||
|
|
||||||
|
Assert.Equal("http://127.0.0.1:7777", proxy.HttpProxyAddress);
|
||||||
|
Assert.Null(proxy.HttpProxyUsername);
|
||||||
|
Assert.Null(proxy.HttpProxyPassword);
|
||||||
|
|
||||||
|
Assert.Equal(0, proxy.NoProxyList.Count);
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("http_proxy", "http://127.0.0.1:7777");
|
||||||
|
proxy = new RunnerWebProxy();
|
||||||
|
|
||||||
|
Assert.Equal("http://127.0.0.1:7777", proxy.HttpProxyAddress);
|
||||||
|
Assert.Null(proxy.HttpProxyUsername);
|
||||||
|
Assert.Null(proxy.HttpProxyPassword);
|
||||||
|
|
||||||
|
Assert.Equal(0, proxy.NoProxyList.Count);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
CleanProxyEnv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public void WebProxyPrependsHTTPforHTTPS_PROXY_IfNoProtocol()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("https_proxy", "127.0.0.1:7777");
|
||||||
|
var proxy = new RunnerWebProxy();
|
||||||
|
|
||||||
|
Assert.Equal("http://127.0.0.1:7777", proxy.HttpsProxyAddress);
|
||||||
|
Assert.Null(proxy.HttpProxyUsername);
|
||||||
|
Assert.Null(proxy.HttpProxyPassword);
|
||||||
|
|
||||||
|
Assert.Equal(0, proxy.NoProxyList.Count);
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("https_proxy", "https://127.0.0.1:7777");
|
||||||
|
proxy = new RunnerWebProxy();
|
||||||
|
|
||||||
|
Assert.Equal("https://127.0.0.1:7777", proxy.HttpsProxyAddress); // existing protocol 'https' is not removed
|
||||||
|
Assert.Null(proxy.HttpProxyUsername);
|
||||||
|
Assert.Null(proxy.HttpProxyPassword);
|
||||||
|
|
||||||
|
Assert.Equal(0, proxy.NoProxyList.Count);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
CleanProxyEnv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Common")]
|
[Trait("Category", "Common")]
|
||||||
|
|||||||
@@ -96,6 +96,63 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public async void PrepareActions_DownloadActionFromDotCom_ZipFileError()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Setup();
|
||||||
|
const string ActionName = "ownerName/sample-action";
|
||||||
|
var actions = new List<Pipelines.ActionStep>
|
||||||
|
{
|
||||||
|
new Pipelines.ActionStep()
|
||||||
|
{
|
||||||
|
Name = "action",
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Reference = new Pipelines.RepositoryPathReference()
|
||||||
|
{
|
||||||
|
Name = ActionName,
|
||||||
|
Ref = "main",
|
||||||
|
RepositoryType = "GitHub"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a corrupted ZIP file for testing
|
||||||
|
var tempDir = _hc.GetDirectory(WellKnownDirectory.Temp);
|
||||||
|
Directory.CreateDirectory(tempDir);
|
||||||
|
var archiveFile = Path.Combine(tempDir, Path.GetRandomFileName());
|
||||||
|
using (var fileStream = new FileStream(archiveFile, FileMode.Create))
|
||||||
|
{
|
||||||
|
// Used Co-Pilot for magic bytes here. They represent the tar header and just need to be invalid for the CLI to break.
|
||||||
|
var buffer = new byte[] { 0x50, 0x4B, 0x03, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00 };
|
||||||
|
fileStream.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
using var stream = File.OpenRead(archiveFile);
|
||||||
|
|
||||||
|
string dotcomArchiveLink = GetLinkToActionArchive("https://api.github.com", ActionName, "main");
|
||||||
|
var mockClientHandler = new Mock<HttpClientHandler>();
|
||||||
|
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(dotcomArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
||||||
|
|
||||||
|
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
||||||
|
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
||||||
|
_hc.SetSingleton(mockHandlerFactory.Object);
|
||||||
|
|
||||||
|
_configurationStore.Object.GetSettings().IsHostedServer = true;
|
||||||
|
|
||||||
|
// Act + Assert
|
||||||
|
await Assert.ThrowsAsync<InvalidActionArchiveException>(async () => await _actionManager.PrepareActionsAsync(_ec.Object, actions));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Teardown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -1424,6 +1481,74 @@ runs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void LoadsNode20ActionDefinition()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Arrange.
|
||||||
|
Setup();
|
||||||
|
const string Content = @"
|
||||||
|
# Container action
|
||||||
|
name: 'Hello World'
|
||||||
|
description: 'Greet the world and record the time'
|
||||||
|
author: 'GitHub'
|
||||||
|
inputs:
|
||||||
|
greeting: # id of input
|
||||||
|
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||||
|
required: true
|
||||||
|
default: 'Hello'
|
||||||
|
entryPoint: # id of input
|
||||||
|
description: 'optional docker entrypoint overwrite.'
|
||||||
|
required: false
|
||||||
|
outputs:
|
||||||
|
time: # id of output
|
||||||
|
description: 'The time we did the greeting'
|
||||||
|
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||||
|
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||||
|
runs:
|
||||||
|
using: 'node20'
|
||||||
|
main: 'task.js'
|
||||||
|
";
|
||||||
|
Pipelines.ActionStep instance;
|
||||||
|
string directory;
|
||||||
|
CreateAction(yamlContent: Content, instance: out instance, directory: out directory);
|
||||||
|
|
||||||
|
// Act.
|
||||||
|
Definition definition = _actionManager.LoadAction(_ec.Object, instance);
|
||||||
|
|
||||||
|
// Assert.
|
||||||
|
Assert.NotNull(definition);
|
||||||
|
Assert.Equal(directory, definition.Directory);
|
||||||
|
Assert.NotNull(definition.Data);
|
||||||
|
Assert.NotNull(definition.Data.Inputs); // inputs
|
||||||
|
Dictionary<string, string> inputDefaults = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var input in definition.Data.Inputs)
|
||||||
|
{
|
||||||
|
var name = input.Key.AssertString("key").Value;
|
||||||
|
var value = input.Value.AssertScalar("value").ToString();
|
||||||
|
|
||||||
|
_hc.GetTrace().Info($"Default: {name} = {value}");
|
||||||
|
inputDefaults[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(2, inputDefaults.Count);
|
||||||
|
Assert.True(inputDefaults.ContainsKey("greeting"));
|
||||||
|
Assert.Equal("Hello", inputDefaults["greeting"]);
|
||||||
|
Assert.True(string.IsNullOrEmpty(inputDefaults["entryPoint"]));
|
||||||
|
Assert.NotNull(definition.Data.Execution); // execution
|
||||||
|
|
||||||
|
Assert.NotNull(definition.Data.Execution as NodeJSActionExecutionData);
|
||||||
|
Assert.Equal("task.js", (definition.Data.Execution as NodeJSActionExecutionData).Script);
|
||||||
|
Assert.Equal("node20", (definition.Data.Execution as NodeJSActionExecutionData).NodeVersion);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Teardown();
|
||||||
|
}
|
||||||
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
@@ -459,6 +459,49 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void Load_Node20Action()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
Setup();
|
||||||
|
|
||||||
|
var actionManifest = new ActionManifestManager();
|
||||||
|
actionManifest.Initialize(_hc);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "node20action.yml"));
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal("Hello World", result.Name);
|
||||||
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
Assert.Equal(1, result.Deprecated.Count);
|
||||||
|
|
||||||
|
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
||||||
|
result.Deprecated.TryGetValue("greeting", out string value);
|
||||||
|
Assert.Equal("This property has been deprecated", value);
|
||||||
|
|
||||||
|
Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
|
||||||
|
|
||||||
|
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||||
|
|
||||||
|
Assert.Equal("main.js", nodeAction.Script);
|
||||||
|
Assert.Equal("node20", nodeAction.NodeVersion);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Teardown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -715,7 +758,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
//Assert
|
//Assert
|
||||||
var err = Assert.Throws<ArgumentException>(() => actionManifest.Load(_ec.Object, action_path));
|
var err = Assert.Throws<ArgumentException>(() => actionManifest.Load(_ec.Object, action_path));
|
||||||
Assert.Contains($"Fail to load {action_path}", err.Message);
|
Assert.Contains($"Fail to load {action_path}", err.Message);
|
||||||
_ec.Verify(x => x.AddIssue(It.Is<Issue>(s => s.Message.Contains("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.")), It.IsAny<ExecutionContextLogOptions>()), Times.Once);
|
_ec.Verify(x => x.AddIssue(It.Is<Issue>(s => s.Message.Contains("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12', 'node16' or 'node20'.")), It.IsAny<ExecutionContextLogOptions>()), Times.Once);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -821,8 +821,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
ec.Complete();
|
ec.Complete();
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(1, ec.Global.StepsResult.Count);
|
Assert.Equal(0, ec.Global.StepsResult.Count);
|
||||||
Assert.Equal(TaskResult.Succeeded, ec.Global.StepsResult.Single().Conclusion);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,19 +30,10 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Theory]
|
[Theory]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
[InlineData("node12", "", "", "", "node12")]
|
[InlineData("node12", "node16")]
|
||||||
[InlineData("node12", "true", "", "", "node16")]
|
[InlineData("node16", "node16")]
|
||||||
[InlineData("node12", "true", "", "true", "node12")]
|
[InlineData("node20", "node20")]
|
||||||
[InlineData("node12", "true", "true", "", "node12")]
|
public void IsNodeVersionUpgraded(string inputVersion, string expectedVersion)
|
||||||
[InlineData("node12", "true", "true", "true", "node12")]
|
|
||||||
[InlineData("node12", "true", "false", "true", "node16")] // workflow overrides env
|
|
||||||
[InlineData("node16", "", "", "", "node16")]
|
|
||||||
[InlineData("node16", "true", "", "", "node16")]
|
|
||||||
[InlineData("node16", "true", "", "true", "node16")]
|
|
||||||
[InlineData("node16", "true", "true", "", "node16")]
|
|
||||||
[InlineData("node16", "true", "true", "true", "node16")]
|
|
||||||
[InlineData("node16", "true", "false", "true", "node16")]
|
|
||||||
public void IsNodeVersionUpgraded(string inputVersion, string serverFeatureFlag, string workflowOptOut, string machineOptOut, string expectedVersion)
|
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -52,24 +43,10 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
// Server Feature Flag
|
// Server Feature Flag
|
||||||
var variables = new Dictionary<string, VariableValue>();
|
var variables = new Dictionary<string, VariableValue>();
|
||||||
if (!string.IsNullOrEmpty(serverFeatureFlag))
|
|
||||||
{
|
|
||||||
variables["DistributedTask.ForceGithubJavascriptActionsToNode16"] = serverFeatureFlag;
|
|
||||||
}
|
|
||||||
Variables serverVariables = new(hc, variables);
|
Variables serverVariables = new(hc, variables);
|
||||||
|
|
||||||
// Workflow opt-out
|
// Workflow opt-out
|
||||||
var workflowVariables = new Dictionary<string, string>();
|
var workflowVariables = new Dictionary<string, string>();
|
||||||
if (!string.IsNullOrEmpty(workflowOptOut))
|
|
||||||
{
|
|
||||||
workflowVariables[Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion] = workflowOptOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Machine opt-out
|
|
||||||
if (!string.IsNullOrEmpty(machineOptOut))
|
|
||||||
{
|
|
||||||
Environment.SetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, machineOptOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ec.Setup(x => x.Global).Returns(new GlobalContext()
|
_ec.Setup(x => x.Global).Returns(new GlobalContext()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using GitHub.DistributedTask.WebApi;
|
using System;
|
||||||
using GitHub.Runner.Worker;
|
|
||||||
using Moq;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using GitHub.Runner.Worker;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Tests.Worker
|
namespace GitHub.Runner.Common.Tests.Worker
|
||||||
@@ -105,6 +105,18 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
|
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
|
||||||
github["secret_source"] = new Pipelines.ContextData.StringContextData("Actions");
|
github["secret_source"] = new Pipelines.ContextData.StringContextData("Actions");
|
||||||
_message.ContextData.Add("github", github);
|
_message.ContextData.Add("github", github);
|
||||||
|
_message.Resources.Endpoints.Add(new ServiceEndpoint()
|
||||||
|
{
|
||||||
|
Name = WellKnownServiceEndpointNames.SystemVssConnection,
|
||||||
|
Url = new Uri("https://pipelines.actions.githubusercontent.com"),
|
||||||
|
Authorization = new EndpointAuthorization()
|
||||||
|
{
|
||||||
|
Scheme = "Test",
|
||||||
|
Parameters = {
|
||||||
|
{"AccessToken", "token"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
hc.SetSingleton(_actionManager.Object);
|
hc.SetSingleton(_actionManager.Object);
|
||||||
hc.SetSingleton(_config.Object);
|
hc.SetSingleton(_config.Object);
|
||||||
@@ -231,7 +243,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void UploadDiganosticLogIfEnvironmentVariableSet()
|
public async Task UploadDiganosticLogIfEnvironmentVariableSet()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -244,7 +256,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_jobEc.Initialize(hc);
|
_jobEc.Initialize(hc);
|
||||||
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
_diagnosticLogManager.Verify(x =>
|
_diagnosticLogManager.Verify(x =>
|
||||||
x.UploadDiagnosticLogs(
|
x.UploadDiagnosticLogs(
|
||||||
@@ -259,7 +271,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void DontUploadDiagnosticLogIfEnvironmentVariableFalse()
|
public async Task DontUploadDiagnosticLogIfEnvironmentVariableFalse()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -272,7 +284,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_jobEc.Initialize(hc);
|
_jobEc.Initialize(hc);
|
||||||
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
_diagnosticLogManager.Verify(x =>
|
_diagnosticLogManager.Verify(x =>
|
||||||
x.UploadDiagnosticLogs(
|
x.UploadDiagnosticLogs(
|
||||||
@@ -287,14 +299,14 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void DontUploadDiagnosticLogIfEnvironmentVariableMissing()
|
public async Task DontUploadDiagnosticLogIfEnvironmentVariableMissing()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
var jobExtension = new JobExtension();
|
var jobExtension = new JobExtension();
|
||||||
jobExtension.Initialize(hc);
|
jobExtension.Initialize(hc);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
_diagnosticLogManager.Verify(x =>
|
_diagnosticLogManager.Verify(x =>
|
||||||
x.UploadDiagnosticLogs(
|
x.UploadDiagnosticLogs(
|
||||||
@@ -309,7 +321,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void EnsureFinalizeJobRunsIfMessageHasNoEnvironmentUrl()
|
public async Task EnsureFinalizeJobRunsIfMessageHasNoEnvironmentUrl()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -322,7 +334,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_jobEc.Initialize(hc);
|
_jobEc.Initialize(hc);
|
||||||
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
||||||
}
|
}
|
||||||
@@ -331,7 +343,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void EnsureFinalizeJobHandlesNullEnvironmentUrl()
|
public async Task EnsureFinalizeJobHandlesNullEnvironmentUrl()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -347,7 +359,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_jobEc.Initialize(hc);
|
_jobEc.Initialize(hc);
|
||||||
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
||||||
}
|
}
|
||||||
@@ -356,7 +368,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void EnsureFinalizeJobHandlesNullEnvironment()
|
public async Task EnsureFinalizeJobHandlesNullEnvironment()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -369,7 +381,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_jobEc.Initialize(hc);
|
_jobEc.Initialize(hc);
|
||||||
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
_jobEc.InitializeJob(_message, _tokenSource.Token);
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
||||||
}
|
}
|
||||||
@@ -397,7 +409,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
var hookStart = result.First() as JobExtensionRunner;
|
var hookStart = result.First() as JobExtensionRunner;
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
Assert.Equal(Constants.Hooks.JobStartedStepName, hookStart.DisplayName);
|
Assert.Equal(Constants.Hooks.JobStartedStepName, hookStart.DisplayName);
|
||||||
Assert.Equal(Constants.Hooks.JobCompletedStepName, (_jobEc.PostJobSteps.Last() as JobExtensionRunner).DisplayName);
|
Assert.Equal(Constants.Hooks.JobCompletedStepName, (_jobEc.PostJobSteps.Last() as JobExtensionRunner).DisplayName);
|
||||||
@@ -410,7 +422,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void EnsureNoPreAndPostHookSteps()
|
public async Task EnsureNoPreAndPostHookSteps()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
@@ -425,7 +437,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
var x = _jobEc.JobSteps;
|
var x = _jobEc.JobSteps;
|
||||||
|
|
||||||
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
await jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
|
||||||
|
|
||||||
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
Assert.Equal(TaskResult.Succeeded, _jobEc.Result);
|
||||||
Assert.Equal(0, _jobEc.PostJobSteps.Count);
|
Assert.Equal(0, _jobEc.PostJobSteps.Count);
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
timeline,
|
timeline,
|
||||||
jobId,
|
jobId,
|
||||||
testName,
|
testName,
|
||||||
testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null, null,
|
testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null, null,
|
||||||
|
new ActionsEnvironmentReference("staging"),
|
||||||
messageType: messageType);
|
messageType: messageType);
|
||||||
message.Variables[Constants.Variables.System.Culture] = "en-US";
|
message.Variables[Constants.Variables.System.Culture] = "en-US";
|
||||||
message.Resources.Endpoints.Add(new ServiceEndpoint()
|
message.Resources.Endpoints.Add(new ServiceEndpoint()
|
||||||
|
|||||||
@@ -183,6 +183,47 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void SetEnvFileCommand_BlockListItemsFiltered()
|
||||||
|
{
|
||||||
|
using (var hostContext = Setup())
|
||||||
|
{
|
||||||
|
var stateFile = Path.Combine(_rootDirectory, "simple");
|
||||||
|
var content = new List<string>
|
||||||
|
{
|
||||||
|
"NODE_OPTIONS=asdf",
|
||||||
|
};
|
||||||
|
WriteContent(stateFile, content);
|
||||||
|
_setEnvFileCommand.ProcessCommand(_executionContext.Object, stateFile, null);
|
||||||
|
Assert.Equal(1, _issues.Count);
|
||||||
|
Assert.Equal(0, _executionContext.Object.Global.EnvironmentVariables.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void SetEnvFileCommand_BlockListItemsFiltered_Heredoc()
|
||||||
|
{
|
||||||
|
using (var hostContext = Setup())
|
||||||
|
{
|
||||||
|
var stateFile = Path.Combine(_rootDirectory, "simple");
|
||||||
|
var content = new List<string>
|
||||||
|
{
|
||||||
|
"NODE_OPTIONS<<EOF",
|
||||||
|
"asdf",
|
||||||
|
"EOF",
|
||||||
|
};
|
||||||
|
WriteContent(stateFile, content);
|
||||||
|
_setEnvFileCommand.ProcessCommand(_executionContext.Object, stateFile, null);
|
||||||
|
Assert.Equal(1, _issues.Count);
|
||||||
|
Assert.Equal(0, _executionContext.Object.Global.EnvironmentVariables.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
@@ -82,6 +82,33 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public async Task DetermineNode20RuntimeVersionInAlpineContainerAsync()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
// Arrange.
|
||||||
|
var sh = new ContainerStepHost();
|
||||||
|
sh.Initialize(hc);
|
||||||
|
sh.Container = new ContainerInfo() { ContainerId = "1234abcd" };
|
||||||
|
|
||||||
|
_dc.Setup(d => d.DockerExec(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<List<string>>()))
|
||||||
|
.Callback((IExecutionContext ec, string id, string options, string command, List<string> output) =>
|
||||||
|
{
|
||||||
|
output.Add("alpine");
|
||||||
|
})
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
// Act.
|
||||||
|
var nodeVersion = await sh.DetermineNodeRuntimeVersion(_ec.Object, "node20");
|
||||||
|
|
||||||
|
// Assert.
|
||||||
|
Assert.Equal("node20_alpine", nodeVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -108,6 +135,33 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.Equal("node16", nodeVersion);
|
Assert.Equal("node16", nodeVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public async Task DetermineNode20RuntimeVersionInUnknowContainerAsync()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
// Arrange.
|
||||||
|
var sh = new ContainerStepHost();
|
||||||
|
sh.Initialize(hc);
|
||||||
|
sh.Container = new ContainerInfo() { ContainerId = "1234abcd" };
|
||||||
|
|
||||||
|
_dc.Setup(d => d.DockerExec(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<List<string>>()))
|
||||||
|
.Callback((IExecutionContext ec, string id, string options, string command, List<string> output) =>
|
||||||
|
{
|
||||||
|
output.Add("github");
|
||||||
|
})
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
// Act.
|
||||||
|
var nodeVersion = await sh.DetermineNodeRuntimeVersion(_ec.Object, "node20");
|
||||||
|
|
||||||
|
// Assert.
|
||||||
|
Assert.Equal("node20", nodeVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.3.0" />
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.4.0" />
|
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" />
|
<PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" />
|
||||||
<PackageReference Include="Moq" Version="4.11.0" />
|
<PackageReference Include="Moq" Version="4.11.0" />
|
||||||
|
|||||||
20
src/Test/TestData/node20action.yml
Normal file
20
src/Test/TestData/node20action.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: 'Hello World'
|
||||||
|
description: 'Greet the world and record the time'
|
||||||
|
author: 'Test Corporation'
|
||||||
|
inputs:
|
||||||
|
greeting: # id of input
|
||||||
|
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
|
||||||
|
required: true
|
||||||
|
default: 'Hello'
|
||||||
|
deprecationMessage: 'This property has been deprecated'
|
||||||
|
entryPoint: # id of input
|
||||||
|
description: 'optional docker entrypoint overwrite.'
|
||||||
|
required: false
|
||||||
|
outputs:
|
||||||
|
time: # id of output
|
||||||
|
description: 'The time we did the greeting'
|
||||||
|
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
|
||||||
|
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||||
|
runs:
|
||||||
|
using: 'node20'
|
||||||
|
main: 'main.js'
|
||||||
@@ -22,7 +22,7 @@ DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
|
|||||||
PACKAGE_DIR="$SCRIPT_DIR/../_package"
|
PACKAGE_DIR="$SCRIPT_DIR/../_package"
|
||||||
PACKAGE_TRIMS_DIR="$SCRIPT_DIR/../_package_trims"
|
PACKAGE_TRIMS_DIR="$SCRIPT_DIR/../_package_trims"
|
||||||
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
|
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
|
||||||
DOTNETSDK_VERSION="6.0.405"
|
DOTNETSDK_VERSION="6.0.412"
|
||||||
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
|
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
|
||||||
RUNNER_VERSION=$(cat runnerversion)
|
RUNNER_VERSION=$(cat runnerversion)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "6.0.405"
|
"version": "6.0.412"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user