Compare commits

..

3 Commits

Author SHA1 Message Date
Ferenc Hammerl
2a7e9ad3a7 Bump patch version for new release 2023-07-25 14:40:05 +02:00
Ferenc Hammerl
00e60cad27 Pass timeout in executioncontext instead of stepsrunner (#2714) (#2715)
* Pass timeout in executioncontext instead of stepsrunner

* Fix linting
2023-07-25 14:31:07 +02:00
JoannaaKL
f8ad46b347 Update releaseVersion 2023-07-24 13:06:36 +02:00
115 changed files with 2351 additions and 7289 deletions

View File

@@ -1,24 +1,27 @@
// 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.415" "version": "6.0.405"
}, },
"ghcr.io/devcontainers/features/node:1": { "ghcr.io/devcontainers/features/node:1": {
"version": "16" "version": "16"
} }
}, },
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
"ms-azuretools.vscode-docker", "ms-azuretools.vscode-docker",
"ms-dotnettools.csharp", "ms-dotnettools.csharp",
"eamodio.gitlens" "eamodio.gitlens"
] ]
} }
}, },
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost", // dotnet restore to install dependencies so OmniSharp works out of the box
"remoteUser": "vscode" // 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",
"remoteUser": "vscode"
}

View File

@@ -1,20 +0,0 @@
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

View File

@@ -1,18 +0,0 @@
name: Close Bugs Bot
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *' # every day at midnight
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
close-issue-message: "This issue does not seem to be a problem with the runner application, it concerns the GitHub actions platform more generally. Could you please post your feedback on the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions) which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃"
exempt-issue-labels: "keep"
stale-issue-label: "actions-bug"
only-labels: "actions-bug"
days-before-stale: 0
days-before-close: 1
close-issue-reason: "completed"

View File

@@ -1,18 +0,0 @@
name: Close Features Bot
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *' # every day at midnight
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
close-issue-message: "Thank you for your interest in the runner application and taking the time to provide your valuable feedback. We kindly ask you to redirect this feedback to the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions-and-packages) which our team actively monitors and would be a better place to start a discussion for new feature requests in GitHub Actions. For more information on this policy please [read our contribution guidelines](https://github.com/actions/runner#contribute). 😃"
exempt-issue-labels: "keep"
stale-issue-label: "actions-feature"
only-labels: "actions-feature"
days-before-stale: 0
days-before-close: 1
close-issue-reason: "completed"

View File

@@ -1,306 +0,0 @@
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)"

View File

@@ -53,9 +53,6 @@ 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

View File

@@ -699,9 +699,6 @@ 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

View File

@@ -1,16 +0,0 @@
name: Stale Bot
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

View File

@@ -1,6 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
cd src/Misc/expressionFunc/hashFiles
npx lint-staged

View File

@@ -9,13 +9,11 @@ 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:
``` ```
curl -v https://api.github.com/zen curl -v https://api.github.com/api/v3/zen
curl -v https://vstoken.actions.githubusercontent.com/_apis/health curl -v https://vstoken.actions.githubusercontent.com/_apis/health
curl -v https://pipelines.actions.githubusercontent.com/_apis/health curl -v https://pipelines.actions.githubusercontent.com/_apis/health
``` ```

View File

@@ -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](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 - Firewall rules that block action runner from accessing certain hosts, ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
### Identify and solve these problems ### Identify and solve these problems

View File

@@ -1,19 +1,15 @@
# Source: https://github.com/dotnet/dotnet-docker # Source: https://github.com/dotnet/dotnet-docker
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy as build FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy as build
ARG TARGETOS
ARG TARGETARCH
ARG RUNNER_VERSION ARG RUNNER_VERSION
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.4.0 ARG RUNNER_ARCH="x64"
ARG DOCKER_VERSION=24.0.6 ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.2
ARG BUILDX_VERSION=0.11.2 ARG DOCKER_VERSION=20.10.23
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 export RUNNER_ARCH=${TARGETARCH} \ 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 \
&& 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
@@ -21,16 +17,11 @@ 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 RUNNER_ARCH=${TARGETARCH} \ RUN export DOCKER_ARCH=x86_64 \
&& 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/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \ && curl -fLo docker.tgz https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
&& tar zxvf docker.tgz \ && tar zxvf docker.tgz \
&& rm -rf docker.tgz \ && rm -rf docker.tgz
&& mkdir -p /usr/local/lib/docker/cli-plugins \
&& curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy
@@ -54,7 +45,6 @@ RUN adduser --disabled-password --gecos "" --uid 1001 runner \
WORKDIR /home/runner WORKDIR /home/runner
COPY --chown=runner:docker --from=build /actions-runner . COPY --chown=runner:docker --from=build /actions-runner .
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker

View File

@@ -1,20 +1,9 @@
## What's Changed ## Bugs
* Trim whitespace in `./Misc/contentHash/dotnetRuntime/*` by @TingluoHuang in https://github.com/actions/runner/pull/2915 - Fixes `if:cancelled()` composite steps not running and normal composite steps not interrupting when the job is cancelled (#2638)
* Send os and arch during long poll by @luketomlinson in https://github.com/actions/runner/pull/2913 - Fix the bug causing double error reporting fix to remain inactive (#2703)
* Revert "Update default version to node20 (#2844)" by @takost in https://github.com/actions/runner/pull/2918
* Fix telemetry publish from JobServerQueue. by @TingluoHuang in https://github.com/actions/runner/pull/2919
* Use block blob instead of append blob by @yacaovsnc in https://github.com/actions/runner/pull/2924
* Provide detail info on untar failures. by @TingluoHuang in https://github.com/actions/runner/pull/2939
* Bump node.js to 20.8.1 by @TingluoHuang in https://github.com/actions/runner/pull/2945
* Update dotnet sdk to latest version @6.0.415 by @github-actions in https://github.com/actions/runner/pull/2929
* Fix typo in log strings by @rajbos in https://github.com/actions/runner/pull/2695
* feat: add support of arm64 arch runners in service creation script by @tuxity in https://github.com/actions/runner/pull/2606
* Add `buildx` to images by @ajschmidt8 in https://github.com/actions/runner/pull/2901
## New Contributors ## Misc
* @tuxity made their first contribution in https://github.com/actions/runner/pull/2606 - Collect telemetry on GitHub-related HTTP requests (#2691)
**Full Changelog**: https://github.com/actions/runner/compare/v2.310.2...v2.311.0
_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.

View File

@@ -1 +1 @@
<Update to ./src/runnerversion when creating release> 2.307.1

View File

@@ -8,7 +8,7 @@ set -e
# Configures it as a service more secure # Configures it as a service more secure
# Should be used on VMs and not containers # Should be used on VMs and not containers
# Works on OSX and Linux # Works on OSX and Linux
# Assumes x64 arch (support arm64) # Assumes x64 arch
# See EXAMPLES below # See EXAMPLES below
flags_found=false flags_found=false
@@ -87,9 +87,6 @@ sudo echo
runner_plat=linux runner_plat=linux
[ ! -z "$(which sw_vers)" ] && runner_plat=osx; [ ! -z "$(which sw_vers)" ] && runner_plat=osx;
runner_arch=x64
[ ! -z "$(arch | grep arm64)" ] && runner_arch=arm64
function fatal() function fatal()
{ {
echo "error: $1" >&2 echo "error: $1" >&2
@@ -142,7 +139,7 @@ echo "Downloading latest runner ..."
# For the GHES Alpha, download the runner from github.com # For the GHES Alpha, download the runner from github.com
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name') latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
latest_version=$(echo ${latest_version_label:1}) latest_version=$(echo ${latest_version_label:1})
runner_file="actions-runner-${runner_plat}-${runner_arch}-${latest_version}.tar.gz" runner_file="actions-runner-${runner_plat}-x64-${latest_version}.tar.gz"
if [ -f "${runner_file}" ]; then if [ -f "${runner_file}" ]; then
echo "${runner_file} exists. skipping download." echo "${runner_file} exists. skipping download."

View File

@@ -1 +1 @@
531b31914e525ecb12cc5526415bc70a112ebc818f877347af1a231011f539c5 39f2a931565d6a10e695ac8ed14bb9dcbb568151410349b32dbf9c27bae29602

View File

@@ -1 +1 @@
722dd5fa5ecc207fcccf67f6e502d689f2119d8117beff2041618fba17dc66a4 29ffb303537d8ba674fbebc7729292c21c4ebd17b3198f91ed593ef4cbbb67b5

View File

@@ -1 +1 @@
8ca75c76e15ab9dc7fe49a66c5c74e171e7fabd5d26546fda8931bd11bff30f9 de6868a836fa3cb9e5ddddbc079da1c25e819aa2d2fc193cc9931c353687c57c

View File

@@ -1 +1 @@
70496eb1c99b39b3373b5088c95a35ebbaac1098e6c47c8aab94771f3ffbf501 339d3e1a5fd28450c0fe6cb820cc7aae291f0f9e2d153ac34e1f7b080e35d30e

View File

@@ -1 +1 @@
4f8d48727d535daabcaec814e0dafb271c10625366c78e7e022ca7477a73023f dcb7f606c1d7d290381e5020ee73e7f16dcbd2f20ac9b431362ccbb5120d449c

View File

@@ -1 +1 @@
d54d7428f2b9200a0030365a6a4e174e30a1b29b922f8254dffb2924bd09549d 1bbcb0e9a2cf4be4b1fce77458de139b70ac58efcbb415a6db028b9373ae1673

View File

@@ -1 +1 @@
eaa939c45307f46b7003902255b3a2a09287215d710984107667e03ac493eb26 44cd25f3c104d0abb44d262397a80e0b2c4f206465c5d899a22eec043dac0fb3

View File

@@ -1 +1 @@
4bf3e1af0d482af1b2eaf9f08250248a8c1aea8ec20a3c5be116d58cdd930009 3807dcbf947e840c33535fb466b096d76bf09e5c0254af8fc8cbbb24c6388222

View File

@@ -1 +1 @@
ec1719a8cb4d8687328aa64f4aa7c4e3498a715d8939117874782e3e6e63a14b ee01eee80cd8a460a4b9780ee13fdd20f25c59e754b4ccd99df55fbba2a85634

View File

@@ -1 +1 @@
50538de29f173bb73f708c4ed2c8328a62b8795829b97b2a6cb57197e2305287 a9fb9c14e24e79aec97d4da197dd7bfc6364297d6fce573afb2df48cc9a931f8

View File

@@ -1 +1 @@
a0a96cbb7593643b69e669bf14d7b29b7f27800b3a00bb3305aebe041456c701 a4e0e8fc62eba0967a39c7d693dcd0aeb8b2bed0765f9c38df80d42884f65341

View File

@@ -1 +1 @@
6255b22692779467047ecebd60ad46984866d75cdfe10421d593a7b51d620b09 17ac17fbe785b3d6fa2868d8d17185ebfe0c90b4b0ddf6b67eac70e42bcd989b

View File

@@ -1 +1 @@
6ff1abd055dc35bfbf06f75c2f08908f660346f66ad1d8f81c910068e9ba029d 89f24657a550f1e818b0e9975e5b80edcf4dd22b7d4bccbb9e48e37f45d30fb1

View File

@@ -1 +1 @@
433a6d748742d12abd20dc2a79b62ac3d9718ae47ef26f8e84dc8c180eea3659 24fd131b5dce33ef16038b771407bc0507da8682a72fb3b7780607235f76db0b

View File

@@ -1,19 +1,11 @@
{ {
"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",
"overrides": [ "parser": "typescript"
{ }
"files": "*.{js,ts,json}",
"options": {
"tabWidth": 2
}
}
]
}

View File

@@ -1,3 +1,4 @@
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run prepare && npm run all`. To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run all`.
When you commit changes to the JSON or Typescript file, the javascript binary will be automatically re-compiled and added to the latest commit. > Note: this package also needs to be recompiled for dependabot PRs updating one of
> its dependencies.

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,7 @@
"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 format && npm run lint && npm run build && npm run pack", "all": "npm run build && npm run format && npm run lint && npm run pack"
"prepare": "cd ../../../../ && husky install"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -20,32 +18,18 @@
"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.4.0" "@actions/glob": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.2", "@types/node": "^12.7.12",
"@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^5.15.0",
"@typescript-eslint/parser": "^6.7.2", "@vercel/ncc": "^0.36.0",
"@vercel/ncc": "^0.38.0", "eslint": "^8.11.0",
"eslint": "^8.47.0", "eslint-plugin-github": "^4.3.5",
"eslint-plugin-github": "^4.10.0", "prettier": "^1.19.1",
"eslint-plugin-prettier": "^5.0.0", "typescript": "^3.6.4"
"prettier": "^3.0.3",
"typescript": "^5.2.2",
"husky": "^8.0.3",
"lint-staged": "^14.0.0"
} }
} }

View File

@@ -52,13 +52,12 @@ async function run(): Promise<void> {
} }
} }
;(async () => { run()
try { .then(out => {
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)
} })
})()

View File

@@ -4,11 +4,8 @@ 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
NODE_ALPINE_URL=https://github.com/actions/alpine_nodejs/releases/download NODE12_VERSION="12.22.7"
NODE16_VERSION="16.20.2" NODE16_VERSION="16.16.0"
NODE20_VERSION="20.8.1"
# 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
@@ -140,10 +137,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
@@ -152,10 +149,8 @@ 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_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin acquireExternalTool "$UNOFFICIAL_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
@@ -163,30 +158,29 @@ 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 "$NODE_ALPINE_URL/v${NODE16_VERSION}/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 "$NODE_ALPINE_URL/v${NODE20_VERSION}/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

View File

@@ -6,29 +6,6 @@
"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) {
@@ -45,6 +22,13 @@ 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));
@@ -53,7 +37,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 _a, e_1, _b, _c; var e_1, _a;
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
@@ -72,10 +56,8 @@ 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 _d = true, _e = __asyncValues(globber.globGenerator()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { for (var _b = __asyncValues(globber.globGenerator()), _c; _c = yield _b.next(), !_c.done;) {
_c = _f.value; const file = _c.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.`);
@@ -98,7 +80,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 (!_d && !_a && (_b = _e.return)) yield _b.call(_e); if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
} }
finally { if (e_1) throw e_1.error; } finally { if (e_1) throw e_1.error; }
} }
@@ -112,18 +94,15 @@ function run() {
} }
}); });
} }
; run()
(() => __awaiter(void 0, void 0, void 0, function* () { .then(out => {
try { console.log(out);
const out = yield run(); process.exit(0);
console.log(out); })
process.exit(0); .catch(err => {
} console.error(err);
catch (err) { process.exit(1);
console.error(err); });
process.exit(1);
}
}))();
/***/ }), /***/ }),
@@ -267,6 +246,7 @@ 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
@@ -296,9 +276,20 @@ 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) {
return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); const delimiter = `ghadelimiter_${uuid_1.v4()}`;
// 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;
/** /**
@@ -316,7 +307,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.issueFileCommand('PATH', inputPath); file_command_1.issueCommand('PATH', inputPath);
} }
else { else {
command_1.issueCommand('add-path', {}, inputPath); command_1.issueCommand('add-path', {}, inputPath);
@@ -356,10 +347,7 @@ function getMultilineInput(name, options) {
const inputs = getInput(name, options) const inputs = getInput(name, options)
.split('\n') .split('\n')
.filter(x => x !== ''); .filter(x => x !== '');
if (options && options.trimWhitespace === false) { return inputs;
return inputs;
}
return inputs.map(input => input.trim());
} }
exports.getMultilineInput = getMultilineInput; exports.getMultilineInput = getMultilineInput;
/** /**
@@ -392,12 +380,8 @@ 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 }, utils_1.toCommandValue(value)); command_1.issueCommand('set-output', { name }, value);
} }
exports.setOutput = setOutput; exports.setOutput = setOutput;
/** /**
@@ -526,11 +510,7 @@ 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) {
const filePath = process.env['GITHUB_STATE'] || ''; command_1.issueCommand('save-state', { name }, value);
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;
/** /**
@@ -596,14 +576,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; exports.issueCommand = 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 issueFileCommand(command, message) { function issueCommand(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}`);
@@ -615,22 +594,7 @@ function issueFileCommand(command, message) {
encoding: 'utf8' encoding: 'utf8'
}); });
} }
exports.issueFileCommand = issueFileCommand; exports.issueCommand = issueCommand;
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
/***/ }), /***/ }),
@@ -1136,9 +1100,7 @@ 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
* *
@@ -1151,56 +1113,17 @@ 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:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ ((__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 }));
exports.getOptions = void 0; const core = __nccwpck_require__(2186);
const core = __importStar(__nccwpck_require__(2186));
/** /**
* Returns a copy with defaults filled in. * Returns a copy with defaults filled in.
*/ */
@@ -1208,7 +1131,6 @@ 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) {
@@ -1220,10 +1142,6 @@ 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}'`);
@@ -1241,25 +1159,6 @@ 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) {
@@ -1289,12 +1188,11 @@ 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 }));
exports.DefaultGlobber = void 0; const core = __nccwpck_require__(2186);
const core = __importStar(__nccwpck_require__(2186)); const fs = __nccwpck_require__(7147);
const fs = __importStar(__nccwpck_require__(7147)); const globOptionsHelper = __nccwpck_require__(1026);
const globOptionsHelper = __importStar(__nccwpck_require__(1026)); const path = __nccwpck_require__(1017);
const path = __importStar(__nccwpck_require__(1017)); const patternHelper = __nccwpck_require__(9005);
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);
@@ -1340,7 +1238,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, true, pattern.segments.concat('**'))); patterns.push(new internal_pattern_1.Pattern(pattern.negate, pattern.segments.concat('**')));
} }
} }
// Push the search paths // Push the search paths
@@ -1383,7 +1281,7 @@ class DefaultGlobber {
// Directory // Directory
if (stats.isDirectory()) { if (stats.isDirectory()) {
// Matched // Matched
if (match & internal_match_kind_1.MatchKind.Directory && options.matchDirectories) { if (match & internal_match_kind_1.MatchKind.Directory) {
yield yield __await(item.path); yield yield __await(item.path);
} }
// Descend? // Descend?
@@ -1478,117 +1376,12 @@ 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
*/ */
@@ -1608,36 +1401,13 @@ var MatchKind;
/***/ }), /***/ }),
/***/ 1849: /***/ 1849:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ ((__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 }));
exports.safeTrimTrailingSeparator = exports.normalizeSeparators = exports.hasRoot = exports.hasAbsoluteRoot = exports.ensureAbsoluteRoot = exports.dirname = void 0; const assert = __nccwpck_require__(9491);
const path = __importStar(__nccwpck_require__(1017)); const path = __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.
@@ -1677,8 +1447,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_1.default(root, `ensureAbsoluteRoot parameter 'root' must not be empty`); assert(root, `ensureAbsoluteRoot parameter 'root' must not be empty`);
assert_1.default(itemPath, `ensureAbsoluteRoot parameter 'itemPath' must not be empty`); assert(itemPath, `ensureAbsoluteRoot parameter 'itemPath' must not be empty`);
// Already rooted // Already rooted
if (hasAbsoluteRoot(itemPath)) { if (hasAbsoluteRoot(itemPath)) {
return itemPath; return itemPath;
@@ -1688,7 +1458,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_1.default(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`); assert(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:
@@ -1713,11 +1483,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_1.default(cwd.match(/^[A-Z]:\\/i), `Expected current directory to start with an absolute drive root. Actual '${cwd}'`); assert(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_1.default(hasAbsoluteRoot(root), `ensureAbsoluteRoot parameter 'root' must have an absolute root`); assert(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
@@ -1734,7 +1504,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_1.default(itemPath, `hasAbsoluteRoot parameter 'itemPath' must not be empty`); assert(itemPath, `hasAbsoluteRoot parameter 'itemPath' must not be empty`);
// Normalize separators // Normalize separators
itemPath = normalizeSeparators(itemPath); itemPath = normalizeSeparators(itemPath);
// Windows // Windows
@@ -1751,7 +1521,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_1.default(itemPath, `isRooted parameter 'itemPath' must not be empty`); assert(itemPath, `isRooted parameter 'itemPath' must not be empty`);
// Normalize separators // Normalize separators
itemPath = normalizeSeparators(itemPath); itemPath = normalizeSeparators(itemPath);
// Windows // Windows
@@ -1813,37 +1583,14 @@ exports.safeTrimTrailingSeparator = safeTrimTrailingSeparator;
/***/ }), /***/ }),
/***/ 6836: /***/ 6836:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ ((__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 }));
exports.Path = void 0; const assert = __nccwpck_require__(9491);
const path = __importStar(__nccwpck_require__(1017)); const path = __nccwpck_require__(1017);
const pathHelper = __importStar(__nccwpck_require__(1849)); const pathHelper = __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
@@ -1857,7 +1604,7 @@ class Path {
this.segments = []; this.segments = [];
// String // String
if (typeof itemPath === 'string') { if (typeof itemPath === 'string') {
assert_1.default(itemPath, `Parameter 'itemPath' must not be empty`); assert(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
@@ -1884,24 +1631,24 @@ class Path {
// Array // Array
else { else {
// Must not be empty // Must not be empty
assert_1.default(itemPath.length > 0, `Parameter 'itemPath' must not be an empty array`); assert(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_1.default(segment, `Parameter 'itemPath' must not contain any empty segments`); assert(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_1.default(segment === pathHelper.dirname(segment), `Parameter 'itemPath' root segment contains information for multiple segments`); assert(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_1.default(!segment.includes(path.sep), `Parameter 'itemPath' contains unexpected path separators`); assert(!segment.includes(path.sep), `Parameter 'itemPath' contains unexpected path separators`);
this.segments.push(segment); this.segments.push(segment);
} }
} }
@@ -1933,32 +1680,12 @@ exports.Path = Path;
/***/ }), /***/ }),
/***/ 9005: /***/ 9005:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ ((__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 }));
exports.partialMatch = exports.match = exports.getSearchPaths = void 0; const pathHelper = __nccwpck_require__(1849);
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';
/** /**
@@ -2034,44 +1761,21 @@ exports.partialMatch = partialMatch;
/***/ }), /***/ }),
/***/ 4536: /***/ 4536:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { /***/ ((__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 }));
exports.Pattern = void 0; const assert = __nccwpck_require__(9491);
const os = __importStar(__nccwpck_require__(2037)); const os = __nccwpck_require__(2037);
const path = __importStar(__nccwpck_require__(1017)); const path = __nccwpck_require__(1017);
const pathHelper = __importStar(__nccwpck_require__(1849)); const pathHelper = __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, isImplicitPattern = false, segments, homedir) { constructor(patternOrNegate, segments) {
/** /**
* Indicates whether matches should be excluded from the result set * Indicates whether matches should be excluded from the result set
*/ */
@@ -2085,9 +1789,9 @@ class Pattern {
else { else {
// Convert to pattern // Convert to pattern
segments = segments || []; segments = segments || [];
assert_1.default(segments.length, `Parameter 'segments' must not empty`); assert(segments.length, `Parameter 'segments' must not empty`);
const root = Pattern.getLiteral(segments[0]); const root = Pattern.getLiteral(segments[0]);
assert_1.default(root && pathHelper.hasAbsoluteRoot(root), `Parameter 'segments' first element must be a root path`); assert(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}`;
@@ -2099,7 +1803,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, homedir); pattern = Pattern.fixupPattern(pattern);
// 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
@@ -2115,7 +1819,6 @@ 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,
@@ -2137,11 +1840,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
// preceding the globstar. For example, given the pattern `/foo/**`, Minimatch returns // preceeding 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) && this.isImplicitPattern === false) { if (!itemPath.endsWith(path.sep)) {
// 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 absolute root. // For example, formats like C: and C:foo on Windows are resolved to an aboslute root.
itemPath = `${itemPath}${path.sep}`; itemPath = `${itemPath}${path.sep}`;
} }
} }
@@ -2179,15 +1882,15 @@ class Pattern {
/** /**
* Normalizes slashes and ensures absolute root * Normalizes slashes and ensures absolute root
*/ */
static fixupPattern(pattern, homedir) { static fixupPattern(pattern) {
// Empty // Empty
assert_1.default(pattern, 'pattern cannot be empty'); assert(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_1.default(literalSegments.every((x, i) => (x !== '.' || i === 0) && x !== '..'), `Invalid pattern '${pattern}'. Relative pathing '.' and '..' is not allowed.`); assert(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_1.default(!pathHelper.hasRoot(pattern) || literalSegments[0], `Invalid pattern '${pattern}'. Root segment must not contain globs.`); assert(!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
@@ -2196,9 +1899,9 @@ class Pattern {
} }
// Replace leading `~` segment // Replace leading `~` segment
else if (pattern === '~' || pattern.startsWith(`~${path.sep}`)) { else if (pattern === '~' || pattern.startsWith(`~${path.sep}`)) {
homedir = homedir || os.homedir(); const homedir = os.homedir();
assert_1.default(homedir, 'Unable to determine HOME directory'); assert(homedir, 'Unable to determine HOME directory');
assert_1.default(pathHelper.hasAbsoluteRoot(homedir), `Expected HOME directory to be a rooted path. Actual '${homedir}'`); assert(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
@@ -2301,7 +2004,6 @@ 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;
@@ -2530,19 +2232,6 @@ 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) {
@@ -3047,13 +2736,7 @@ function getProxyUrl(reqUrl) {
} }
})(); })();
if (proxyVar) { if (proxyVar) {
try { return new URL(proxyVar);
return new URL(proxyVar);
}
catch (_a) {
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
return new URL(`http://${proxyVar}`);
}
} }
else { else {
return undefined; return undefined;
@@ -3064,10 +2747,6 @@ 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;
@@ -3093,24 +2772,13 @@ function checkBypass(reqUrl) {
.split(',') .split(',')
.map(x => x.trim().toUpperCase()) .map(x => x.trim().toUpperCase())
.filter(x => x)) { .filter(x => x)) {
if (upperNoProxyItem === '*' || if (upperReqHosts.some(x => x === 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
/***/ }), /***/ }),
@@ -3149,9 +2817,6 @@ 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;

View File

@@ -2,7 +2,7 @@
SET UPDATEFILE=update.finished SET UPDATEFILE=update.finished
"%~dp0\bin\Runner.Listener.exe" run %* "%~dp0\bin\Runner.Listener.exe" run %*
rem using `if %ERRORLEVEL% EQU N` instead of `if ERRORLEVEL N` rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
rem `if ERRORLEVEL N` means: error level is N or MORE rem `if ERRORLEVEL N` means: error level is N or MORE
if %ERRORLEVEL% EQU 0 ( if %ERRORLEVEL% EQU 0 (

View File

@@ -75,9 +75,6 @@ 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
mscordaccore_amd64_amd64_6.0.2223.42425.dll
mscordaccore_amd64_amd64_6.0.2323.48002.dll
mscordbi.dll mscordbi.dll
mscorlib.dll mscorlib.dll
mscorrc.debug.dll mscorrc.debug.dll

View File

@@ -1,5 +1,4 @@
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Runner.Common.Util;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -7,28 +6,29 @@ namespace GitHub.Runner.Common
{ {
public sealed class ActionCommand public sealed class ActionCommand
{ {
private static readonly StringEscapingUtil.EscapeMapping[] _escapeMappings = new[] private static readonly EscapeMapping[] _escapeMappings = new[]
{ {
new StringEscapingUtil.EscapeMapping(token: ";", replacement: "%3B"), new EscapeMapping(token: ";", replacement: "%3B"),
new StringEscapingUtil.EscapeMapping(token: "\r", replacement: "%0D"), new EscapeMapping(token: "\r", replacement: "%0D"),
new StringEscapingUtil.EscapeMapping(token: "\n", replacement: "%0A"), new EscapeMapping(token: "\n", replacement: "%0A"),
new StringEscapingUtil.EscapeMapping(token: "]", replacement: "%5D"), new EscapeMapping(token: "]", replacement: "%5D"),
new StringEscapingUtil.EscapeMapping(token: "%", replacement: "%25"), new EscapeMapping(token: "%", replacement: "%25"),
}; };
private static readonly StringEscapingUtil.EscapeMapping[] _escapeDataMappings = new[] private static readonly EscapeMapping[] _escapeDataMappings = new[]
{ {
new StringEscapingUtil.EscapeMapping(token: "\r", replacement: "%0D"), new EscapeMapping(token: "\r", replacement: "%0D"),
new StringEscapingUtil.EscapeMapping(token: "\n", replacement: "%0A"), new EscapeMapping(token: "\n", replacement: "%0A"),
new EscapeMapping(token: "%", replacement: "%25"),
}; };
private static readonly StringEscapingUtil.EscapeMapping[] _escapePropertyMappings = new[] private static readonly EscapeMapping[] _escapePropertyMappings = new[]
{ {
new StringEscapingUtil.EscapeMapping(token: "\r", replacement: "%0D"), new EscapeMapping(token: "\r", replacement: "%0D"),
new StringEscapingUtil.EscapeMapping(token: "\n", replacement: "%0A"), new EscapeMapping(token: "\n", replacement: "%0A"),
new StringEscapingUtil.EscapeMapping(token: ":", replacement: "%3A"), new EscapeMapping(token: ":", replacement: "%3A"),
new StringEscapingUtil.EscapeMapping(token: ",", replacement: "%2C"), new EscapeMapping(token: ",", replacement: "%2C"),
new StringEscapingUtil.EscapeMapping(token: "%", replacement: "%25"), new EscapeMapping(token: "%", replacement: "%25"),
}; };
private readonly Dictionary<string, string> _properties = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, string> _properties = new(StringComparer.OrdinalIgnoreCase);
@@ -103,12 +103,12 @@ namespace GitHub.Runner.Common
string[] pair = propertyStr.Split(new[] { '=' }, count: 2, options: StringSplitOptions.RemoveEmptyEntries); string[] pair = propertyStr.Split(new[] { '=' }, count: 2, options: StringSplitOptions.RemoveEmptyEntries);
if (pair.Length == 2) if (pair.Length == 2)
{ {
command.Properties[pair[0]] = StringEscapingUtil.UnescapeString(pair[1], _escapePropertyMappings); command.Properties[pair[0]] = UnescapeProperty(pair[1]);
} }
} }
} }
command.Data = StringEscapingUtil.UnescapeString(message.Substring(endIndex + _commandKey.Length), _escapeDataMappings); command.Data = UnescapeData(message.Substring(endIndex + _commandKey.Length));
return true; return true;
} }
catch catch
@@ -173,12 +173,12 @@ namespace GitHub.Runner.Common
string[] pair = propertyStr.Split(new[] { '=' }, count: 2, options: StringSplitOptions.RemoveEmptyEntries); string[] pair = propertyStr.Split(new[] { '=' }, count: 2, options: StringSplitOptions.RemoveEmptyEntries);
if (pair.Length == 2) if (pair.Length == 2)
{ {
command.Properties[pair[0]] = StringEscapingUtil.UnescapeString(pair[1], _escapeMappings); command.Properties[pair[0]] = Unescape(pair[1]);
} }
} }
} }
command.Data = StringEscapingUtil.UnescapeString(message.Substring(rbIndex + 1), _escapeMappings); command.Data = Unescape(message.Substring(rbIndex + 1));
return true; return true;
} }
catch catch
@@ -187,5 +187,67 @@ namespace GitHub.Runner.Common
return false; return false;
} }
} }
private static string Unescape(string escaped)
{
if (string.IsNullOrEmpty(escaped))
{
return string.Empty;
}
string unescaped = escaped;
foreach (EscapeMapping mapping in _escapeMappings)
{
unescaped = unescaped.Replace(mapping.Replacement, mapping.Token);
}
return unescaped;
}
private static string UnescapeProperty(string escaped)
{
if (string.IsNullOrEmpty(escaped))
{
return string.Empty;
}
string unescaped = escaped;
foreach (EscapeMapping mapping in _escapePropertyMappings)
{
unescaped = unescaped.Replace(mapping.Replacement, mapping.Token);
}
return unescaped;
}
private static string UnescapeData(string escaped)
{
if (string.IsNullOrEmpty(escaped))
{
return string.Empty;
}
string unescaped = escaped;
foreach (EscapeMapping mapping in _escapeDataMappings)
{
unescaped = unescaped.Replace(mapping.Replacement, mapping.Token);
}
return unescaped;
}
private sealed class EscapeMapping
{
public string Replacement { get; }
public string Token { get; }
public EscapeMapping(string token, string replacement)
{
ArgUtil.NotNullOrEmpty(token, nameof(token));
ArgUtil.NotNullOrEmpty(replacement, nameof(replacement));
Token = token;
Replacement = replacement;
}
}
} }
} }

View File

@@ -17,7 +17,7 @@ namespace GitHub.Runner.Common
{ {
Task ConnectAsync(Uri serverUrl, VssCredentials credentials); Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
Task<TaskAgentMessage> GetRunnerMessageAsync(CancellationToken token, TaskAgentStatus status, string version, string os, string architecture); Task<TaskAgentMessage> GetRunnerMessageAsync(CancellationToken token, TaskAgentStatus status, string version);
} }
public sealed class BrokerServer : RunnerService, IBrokerServer public sealed class BrokerServer : RunnerService, IBrokerServer
@@ -44,11 +44,11 @@ namespace GitHub.Runner.Common
} }
} }
public Task<TaskAgentMessage> GetRunnerMessageAsync(CancellationToken cancellationToken, TaskAgentStatus status, string version, string os, string architecture) public Task<TaskAgentMessage> GetRunnerMessageAsync(CancellationToken cancellationToken, TaskAgentStatus status, string version)
{ {
CheckConnection(); CheckConnection();
var jobMessage = RetryRequest<TaskAgentMessage>( var jobMessage = RetryRequest<TaskAgentMessage>(
async () => await _brokerHttpClient.GetRunnerMessageAsync(version, status, os, architecture, cancellationToken), cancellationToken); async () => await _brokerHttpClient.GetRunnerMessageAsync(version, status, cancellationToken), cancellationToken);
return jobMessage; return jobMessage;
} }

View File

@@ -18,7 +18,7 @@ namespace GitHub.Runner.Common
private bool? _isHostedServer; private bool? _isHostedServer;
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public ulong AgentId { get; set; } public int AgentId { get; set; }
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public string AgentName { get; set; } public string AgentName { get; set; }

View File

@@ -69,8 +69,6 @@ namespace GitHub.Runner.Common
public static readonly OSPlatform Platform = OSPlatform.OSX; public static readonly OSPlatform Platform = OSPlatform.OSX;
#elif OS_WINDOWS #elif OS_WINDOWS
public static readonly OSPlatform Platform = OSPlatform.Windows; public static readonly OSPlatform Platform = OSPlatform.Windows;
#else
public static readonly OSPlatform Platform = OSPlatform.Linux;
#endif #endif
#if X86 #if X86
@@ -81,8 +79,6 @@ namespace GitHub.Runner.Common
public static readonly Architecture PlatformArchitecture = Architecture.Arm; public static readonly Architecture PlatformArchitecture = Architecture.Arm;
#elif ARM64 #elif ARM64
public static readonly Architecture PlatformArchitecture = Architecture.Arm64; public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
#else
public static readonly Architecture PlatformArchitecture = Architecture.X64;
#endif #endif
public static readonly TimeSpan ExitOnUnloadTimeout = TimeSpan.FromSeconds(30); public static readonly TimeSpan ExitOnUnloadTimeout = TimeSpan.FromSeconds(30);
@@ -158,7 +154,7 @@ 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 Node16Warning = "DistributedTask.AddWarningToNode16Action"; public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages"; 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";
@@ -175,9 +171,7 @@ 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 DetectedNodeAfterEndOfLifeMessage = "Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: {0}. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/."; 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 DeprecatedNodeDetectedAfterEndOfLifeActions = "DeprecatedNodeActionsMessageWarnings";
public static readonly string DeprecatedNodeVersion = "node16";
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 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 readonly string EnforcedNode12DetectedAfterEndOfLifeEnvVariable = "Node16ForceActionsWarnings";
} }
@@ -261,7 +255,6 @@ namespace GitHub.Runner.Common
public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION"; public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION";
public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION"; public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION";
public static readonly string PrintLogToStdout = "ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT"; public static readonly string PrintLogToStdout = "ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT";
public static readonly string ActionArchiveCacheDirectory = "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE";
} }
public static class System public static class System

View File

@@ -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 certificate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable."); _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.");
} }
var credFile = GetConfigFile(WellKnownConfigFile.Credentials); var credFile = GetConfigFile(WellKnownConfigFile.Credentials);

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@@ -15,11 +14,10 @@ namespace GitHub.Runner.Common
[ServiceLocator(Default = typeof(JobServerQueue))] [ServiceLocator(Default = typeof(JobServerQueue))]
public interface IJobServerQueue : IRunnerService, IThrottlingReporter public interface IJobServerQueue : IRunnerService, IThrottlingReporter
{ {
IList<JobTelemetry> JobTelemetries { get; }
TaskCompletionSource<int> JobRecordUpdated { get; } TaskCompletionSource<int> JobRecordUpdated { get; }
event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling; event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
Task ShutdownAsync(); Task ShutdownAsync();
void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultsServiceOnly = false, bool enableTelemetry = false); void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultServiceOnly = false);
void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null); void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null);
void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource); void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource);
void QueueResultsUpload(Guid timelineRecordId, string name, string path, string type, bool deleteSource, bool finalize, bool firstBlock, long totalLines); void QueueResultsUpload(Guid timelineRecordId, string name, string path, string type, bool deleteSource, bool finalize, bool firstBlock, long totalLines);
@@ -71,18 +69,13 @@ namespace GitHub.Runner.Common
private Task[] _allDequeueTasks; private Task[] _allDequeueTasks;
private readonly TaskCompletionSource<int> _jobCompletionSource = new(); private readonly TaskCompletionSource<int> _jobCompletionSource = new();
private readonly TaskCompletionSource<int> _jobRecordUpdated = new(); private readonly TaskCompletionSource<int> _jobRecordUpdated = new();
private readonly List<JobTelemetry> _jobTelemetries = new();
private bool _queueInProcess = false; private bool _queueInProcess = false;
private bool _resultsServiceOnly = false; private bool _resultsServiceOnly = false;
private Stopwatch _resultsUploadTimer = new();
private Stopwatch _actionsUploadTimer = new();
public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated; public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated;
public event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling; public event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
public IList<JobTelemetry> JobTelemetries => _jobTelemetries;
// Web console dequeue will start with process queue every 250ms for the first 60*4 times (~60 seconds). // Web console dequeue will start with process queue every 250ms for the first 60*4 times (~60 seconds).
// Then the dequeue will happen every 500ms. // Then the dequeue will happen every 500ms.
// In this way, customer still can get instance live console output on job start, // In this way, customer still can get instance live console output on job start,
@@ -94,7 +87,6 @@ namespace GitHub.Runner.Common
private bool _firstConsoleOutputs = true; private bool _firstConsoleOutputs = true;
private bool _resultsClientInitiated = false; private bool _resultsClientInitiated = false;
private bool _enableTelemetry = false;
private delegate Task ResultsFileUploadHandler(ResultsUploadFileInfo file); private delegate Task ResultsFileUploadHandler(ResultsUploadFileInfo file);
public override void Initialize(IHostContext hostContext) public override void Initialize(IHostContext hostContext)
@@ -104,15 +96,14 @@ namespace GitHub.Runner.Common
_resultsServer = hostContext.GetService<IResultsServer>(); _resultsServer = hostContext.GetService<IResultsServer>();
} }
public void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultsServiceOnly = false, bool enableTelemetry = false) public void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultServiceOnly = false)
{ {
Trace.Entering(); Trace.Entering();
_resultsServiceOnly = resultsServiceOnly; _resultsServiceOnly = resultServiceOnly;
_enableTelemetry = enableTelemetry;
var serviceEndPoint = jobRequest.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase)); var serviceEndPoint = jobRequest.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
if (!resultsServiceOnly) if (!resultServiceOnly)
{ {
_jobServer.InitializeWebsocketClient(serviceEndPoint); _jobServer.InitializeWebsocketClient(serviceEndPoint);
} }
@@ -128,7 +119,7 @@ namespace GitHub.Runner.Common
{ {
string liveConsoleFeedUrl = null; string liveConsoleFeedUrl = null;
Trace.Info("Initializing results client"); Trace.Info("Initializing results client");
if (resultsServiceOnly if (resultServiceOnly
&& serviceEndPoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl) && serviceEndPoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl)
&& !string.IsNullOrEmpty(feedStreamUrl)) && !string.IsNullOrEmpty(feedStreamUrl))
{ {
@@ -220,12 +211,6 @@ namespace GitHub.Runner.Common
await _resultsServer.DisposeAsync(); await _resultsServer.DisposeAsync();
Trace.Info("All queue process tasks have been stopped, and all queues are drained."); Trace.Info("All queue process tasks have been stopped, and all queues are drained.");
if (_enableTelemetry)
{
var uploadTimeComparison = $"Actions upload time: {_actionsUploadTimer.ElapsedMilliseconds} ms, Result upload time: {_resultsUploadTimer.ElapsedMilliseconds} ms";
Trace.Info(uploadTimeComparison);
_jobTelemetries.Add(new JobTelemetry() { Type = JobTelemetryType.General, Message = uploadTimeComparison });
}
} }
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber) public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
@@ -471,10 +456,6 @@ namespace GitHub.Runner.Common
{ {
try try
{ {
if (_enableTelemetry)
{
_actionsUploadTimer.Start();
}
await UploadFile(file); await UploadFile(file);
} }
catch (Exception ex) catch (Exception ex)
@@ -490,13 +471,6 @@ namespace GitHub.Runner.Common
// _fileUploadQueue.Enqueue(file); // _fileUploadQueue.Enqueue(file);
//} //}
} }
finally
{
if (_enableTelemetry)
{
_actionsUploadTimer.Stop();
}
}
} }
Trace.Info("Try to upload {0} log files or attachments, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount); Trace.Info("Try to upload {0} log files or attachments, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount);
@@ -543,10 +517,6 @@ namespace GitHub.Runner.Common
{ {
try try
{ {
if (_enableTelemetry)
{
_resultsUploadTimer.Start();
}
if (String.Equals(file.Type, ChecksAttachmentType.StepSummary, StringComparison.OrdinalIgnoreCase)) if (String.Equals(file.Type, ChecksAttachmentType.StepSummary, StringComparison.OrdinalIgnoreCase))
{ {
await UploadSummaryFile(file); await UploadSummaryFile(file);
@@ -571,19 +541,10 @@ namespace GitHub.Runner.Common
Trace.Error(ex); Trace.Error(ex);
errorCount++; errorCount++;
// If we hit any exceptions uploading to Results, let's skip any additional uploads to Results unless Results is serving logs // If we hit any exceptions uploading to Results, let's skip any additional uploads to Results
if (!_resultsServiceOnly) _resultsClientInitiated = false;
{
_resultsClientInitiated = false; SendResultsTelemetry(ex);
SendResultsTelemetry(ex);
}
}
finally
{
if (_enableTelemetry)
{
_resultsUploadTimer.Stop();
}
} }
} }
@@ -699,11 +660,9 @@ namespace GitHub.Runner.Common
{ {
Trace.Info("Catch exception during update steps, skip update Results."); Trace.Info("Catch exception during update steps, skip update Results.");
Trace.Error(e); Trace.Error(e);
if (!_resultsServiceOnly) _resultsClientInitiated = false;
{
_resultsClientInitiated = false; SendResultsTelemetry(e);
SendResultsTelemetry(e);
}
} }
if (_bufferedRetryRecords.Remove(update.TimelineId)) if (_bufferedRetryRecords.Remove(update.TimelineId))

View File

@@ -1,73 +0,0 @@
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;
}
}

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Security; using System.Security;
@@ -53,8 +52,8 @@ namespace GitHub.Runner.Common
public void InitializeResultsClient(Uri uri, string liveConsoleFeedUrl, string token) public void InitializeResultsClient(Uri uri, string liveConsoleFeedUrl, string token)
{ {
this._resultsClient = CreateHttpClient(uri, token); var httpMessageHandler = HostContext.CreateHttpClientHandler();
this._resultsClient = new ResultsHttpClient(uri, httpMessageHandler, token, disposeHandler: true);
_token = token; _token = token;
if (!string.IsNullOrEmpty(liveConsoleFeedUrl)) if (!string.IsNullOrEmpty(liveConsoleFeedUrl))
{ {
@@ -63,26 +62,6 @@ namespace GitHub.Runner.Common
} }
} }
public ResultsHttpClient CreateHttpClient(Uri uri, string token)
{
// Using default 100 timeout
RawClientHttpRequestSettings settings = VssUtil.GetHttpRequestSettings(null);
// Create retry handler
IEnumerable<DelegatingHandler> delegatingHandlers = new List<DelegatingHandler>();
if (settings.MaxRetryRequest > 0)
{
delegatingHandlers = new DelegatingHandler[] { new VssHttpRetryMessageHandler(settings.MaxRetryRequest) };
}
// Setup RawHttpMessageHandler without credentials
var httpMessageHandler = new RawHttpMessageHandler(new NoOpCredentials(null), settings);
var pipeline = HttpClientFactory.CreatePipeline(httpMessageHandler, delegatingHandlers);
return new ResultsHttpClient(uri, pipeline, token, disposeHandler: true);
}
public Task CreateResultsStepSummaryAsync(string planId, string jobId, Guid stepId, string file, public Task CreateResultsStepSummaryAsync(string planId, string jobId, Guid stepId, string file,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {

View File

@@ -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.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<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" />

View File

@@ -15,11 +15,12 @@ namespace GitHub.Runner.Common
[ServiceLocator(Default = typeof(RunnerDotcomServer))] [ServiceLocator(Default = typeof(RunnerDotcomServer))]
public interface IRunnerDotcomServer : IRunnerService public interface IRunnerDotcomServer : IRunnerService
{ {
Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName); Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, 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
@@ -41,7 +42,7 @@ namespace GitHub.Runner.Common
} }
public async Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName) public async Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, string githubUrl, string githubToken, string agentName = null)
{ {
var githubApiUrl = ""; var githubApiUrl = "";
var gitHubUrlBuilder = new UriBuilder(githubUrl); var gitHubUrlBuilder = new UriBuilder(githubUrl);
@@ -51,11 +52,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/runners?name={Uri.EscapeDataString(agentName)}"; githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
} }
else else
{ {
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runners?name={Uri.EscapeDataString(agentName)}"; githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
} }
} }
else if (path.Length == 2) else if (path.Length == 2)
@@ -68,11 +69,11 @@ namespace GitHub.Runner.Common
if (UrlUtil.IsHostedServer(gitHubUrlBuilder)) if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
{ {
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}"; githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
} }
else else
{ {
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}"; githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
} }
} }
else else
@@ -81,8 +82,14 @@ 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();
return runnersList.ToTaskAgents(); if (string.IsNullOrEmpty(agentName))
{
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)
@@ -130,16 +137,6 @@ 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);
@@ -162,15 +159,9 @@ 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);
@@ -204,7 +195,7 @@ namespace GitHub.Runner.Common
if (response != null) if (response != null)
{ {
responseStatus = response.StatusCode; responseStatus = response.StatusCode;
var githubRequestId = UrlUtil.GetGitHubRequestId(response.Headers); var githubRequestId = GetGitHubRequestId(response.Headers);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -224,7 +215,7 @@ namespace GitHub.Runner.Common
} }
catch (Exception ex) when (retry < maxRetryAttemptsCount && responseStatus != System.Net.HttpStatusCode.NotFound) catch (Exception ex) when (retry < maxRetryAttemptsCount && responseStatus != System.Net.HttpStatusCode.NotFound)
{ {
Trace.Error($"{errorMessage} -- Attempt: {retry}"); Trace.Error($"{errorMessage} -- Atempt: {retry}");
Trace.Error(ex); Trace.Error(ex);
} }
} }
@@ -233,5 +224,14 @@ 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;
}
} }
} }

View File

@@ -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, ulong agentId); Task DeleteAgentAsync(int agentPoolId, int agentId);
Task DeleteAgentAsync(ulong agentId); Task DeleteAgentAsync(int 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);
@@ -38,7 +38,7 @@ namespace GitHub.Runner.Common
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken); Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken); Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken); Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, string os, string architecture, CancellationToken cancellationToken); Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken);
// job request // job request
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken); Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
@@ -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, ulong agentId, string currentState, string trace); Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int 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, ulong agentId) public Task DeleteAgentAsync(int agentPoolId, int agentId)
{ {
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId); return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
} }
public Task DeleteAgentAsync(ulong agentId) public Task DeleteAgentAsync(int agentId)
{ {
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
} }
@@ -272,10 +272,10 @@ namespace GitHub.Runner.Common
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken); return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
} }
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, string os, string architecture, CancellationToken cancellationToken) public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken)
{ {
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, runnerVersion, os, architecture, cancellationToken: cancellationToken); return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, runnerVersion, cancellationToken: cancellationToken);
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
@@ -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, ulong agentId, string currentState, string trace) public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int 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);

View File

@@ -6,7 +6,13 @@ 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);

View File

@@ -1,41 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Runner.Sdk;
using GitHub.Runner.Common;
namespace GitHub.Runner.Common.Util
{
public static class StringEscapingUtil
{
public static string UnescapeString(string escaped, EscapeMapping[] _escapeDataMappings)
{
if (string.IsNullOrEmpty(escaped))
{
return string.Empty;
}
string unescaped = escaped;
foreach (EscapeMapping mapping in _escapeDataMappings)
{
unescaped = unescaped.Replace(mapping.Replacement, mapping.Token);
}
return unescaped;
}
public class EscapeMapping
{
public string Replacement { get; }
public string Token { get; }
public EscapeMapping(string token, string replacement)
{
ArgUtil.NotNullOrEmpty(token, nameof(token));
ArgUtil.NotNullOrEmpty(replacement, nameof(replacement));
Token = token;
Replacement = replacement;
}
}
}
}

View File

@@ -73,7 +73,7 @@ namespace GitHub.Runner.Listener
_getMessagesTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token); _getMessagesTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
try try
{ {
message = await _brokerServer.GetRunnerMessageAsync(_getMessagesTokenSource.Token, runnerStatus, BuildConstants.RunnerPackage.Version, VarUtil.OS, VarUtil.OSArchitecture); message = await _brokerServer.GetRunnerMessageAsync(_getMessagesTokenSource.Token, runnerStatus, BuildConstants.RunnerPackage.Version);
if (message == null) if (message == null)
{ {
@@ -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.ErrorCode == 1) catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
{ {
throw; throw;
} }
@@ -108,7 +108,7 @@ namespace GitHub.Runner.Listener
if (!IsGetNextMessageExceptionRetriable(ex)) if (!IsGetNextMessageExceptionRetriable(ex))
{ {
throw new NonRetryableException("Get next message failed with non-retryable error.", ex); throw;
} }
else else
{ {

View File

@@ -351,39 +351,21 @@ namespace GitHub.Runner.Listener.Check
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new() private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new()
{ {
{ {
"System.Net.Http", "Microsoft-System-Net-Http",
new HashSet<string> new HashSet<string>
{ {
"Info", "Info",
"Associate", "Associate",
"Enter",
"Exit"
} }
}, },
{ {
"System.Net.Security", "Microsoft-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",
@@ -409,8 +391,8 @@ namespace GitHub.Runner.Listener.Check
{ {
base.OnEventSourceCreated(eventSource); base.OnEventSourceCreated(eventSource);
if (eventSource.Name.Contains("System.Net.Http") || if (eventSource.Name == "Microsoft-System-Net-Http" ||
eventSource.Name.Contains("System.Net.Security")) eventSource.Name == "Microsoft-System-Net-Security")
{ {
EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All); EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All);
} }

View File

@@ -244,11 +244,11 @@ namespace GitHub.Runner.Listener.Configuration
List<TaskAgent> agents; List<TaskAgent> agents;
if (runnerSettings.UseV2Flow) if (runnerSettings.UseV2Flow)
{ {
agents = await _dotcomServer.GetRunnerByNameAsync(runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName); agents = await _dotcomServer.GetRunnersAsync(runnerSettings.PoolId, runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName);
} }
else else
{ {
agents = await _runnerServer.GetAgentsAsync(runnerSettings.AgentName); agents = await _runnerServer.GetAgentsAsync(runnerSettings.PoolId, runnerSettings.AgentName);
} }
Trace.Verbose("Returns {0} agents", agents.Count); Trace.Verbose("Returns {0} agents", agents.Count);
@@ -263,23 +263,7 @@ namespace GitHub.Runner.Listener.Configuration
try try
{ {
if (runnerSettings.UseV2Flow) agent = await _runnerServer.ReplaceAgentAsync(runnerSettings.PoolId, agent);
{
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)
{ {
@@ -725,7 +709,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 = UrlUtil.GetGitHubRequestId(response.Headers); var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -744,7 +728,7 @@ namespace GitHub.Runner.Listener.Configuration
catch (Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound) catch (Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound)
{ {
retryCount++; retryCount++;
Trace.Error($"Failed to get JIT runner token -- Attempt: {retryCount}"); Trace.Error($"Failed to get JIT runner token -- Atempt: {retryCount}");
Trace.Error(ex); Trace.Error(ex);
} }
} }
@@ -788,7 +772,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 = UrlUtil.GetGitHubRequestId(response.Headers); var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -807,7 +791,7 @@ namespace GitHub.Runner.Listener.Configuration
catch (Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound) catch (Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound)
{ {
retryCount++; retryCount++;
Trace.Error($"Failed to get tenant credentials -- Attempt: {retryCount}"); Trace.Error($"Failed to get tenant credentials -- Atempt: {retryCount}");
Trace.Error(ex); Trace.Error(ex);
} }
} }

View File

@@ -46,7 +46,7 @@ namespace GitHub.Runner.Listener.Configuration
if (!store.HasCredentials()) if (!store.HasCredentials())
{ {
throw new InvalidOperationException("Credentials not stored. Must reconfigure."); throw new InvalidOperationException("Credentials not stored. Must reconfigure.");
} }
CredentialData credData = store.GetCredentials(); CredentialData credData = store.GetCredentials();

View File

@@ -514,25 +514,9 @@ namespace GitHub.Runner.Listener.Configuration
failureActions.Add(new FailureAction(RecoverAction.Restart, 60000)); failureActions.Add(new FailureAction(RecoverAction.Restart, 60000));
// Lock the Service Database // Lock the Service Database
int svcLockRetries = 10; svcLock = LockServiceDatabase(scmHndl);
int svcLockRetryTimeout = 5000; if (svcLock.ToInt64() <= 0)
while (true)
{ {
svcLock = LockServiceDatabase(scmHndl);
if (svcLock.ToInt64() > 0)
{
break;
}
_term.WriteLine("Retrying Lock Service Database...");
svcLockRetries--;
if (svcLockRetries > 0)
{
Thread.Sleep(svcLockRetryTimeout);
continue;
}
throw new Exception("Failed to Lock Service Database for Write"); throw new Exception("Failed to Lock Service Database for Write");
} }

View File

@@ -98,7 +98,7 @@ namespace GitHub.Runner.Listener
Guid dispatchedJobId = _jobDispatchedQueue.Dequeue(); Guid dispatchedJobId = _jobDispatchedQueue.Dequeue();
if (_jobInfos.TryGetValue(dispatchedJobId, out currentDispatch)) if (_jobInfos.TryGetValue(dispatchedJobId, out currentDispatch))
{ {
Trace.Verbose($"Retrive previous WorkerDispatcher for job {currentDispatch.JobId}."); Trace.Verbose($"Retrive previous WorkerDispather for job {currentDispatch.JobId}.");
} }
} }
@@ -162,12 +162,12 @@ namespace GitHub.Runner.Listener
dispatchedJobId = _jobDispatchedQueue.Dequeue(); dispatchedJobId = _jobDispatchedQueue.Dequeue();
if (_jobInfos.TryGetValue(dispatchedJobId, out currentDispatch)) if (_jobInfos.TryGetValue(dispatchedJobId, out currentDispatch))
{ {
Trace.Verbose($"Retrive previous WorkerDispatcher for job {currentDispatch.JobId}."); Trace.Verbose($"Retrive previous WorkerDispather for job {currentDispatch.JobId}.");
} }
} }
else else
{ {
Trace.Verbose($"There is no running WorkerDispatcher needs to await."); Trace.Verbose($"There is no running WorkerDispather needs to await.");
} }
if (currentDispatch != null) if (currentDispatch != null)
@@ -176,7 +176,7 @@ namespace GitHub.Runner.Listener
{ {
try try
{ {
Trace.Info($"Waiting WorkerDispatcher for job {currentDispatch.JobId} run to finish."); Trace.Info($"Waiting WorkerDispather for job {currentDispatch.JobId} run to finish.");
await currentDispatch.WorkerDispatch; await currentDispatch.WorkerDispatch;
Trace.Info($"Job request {currentDispatch.JobId} processed succeed."); Trace.Info($"Job request {currentDispatch.JobId} processed succeed.");
} }
@@ -190,7 +190,7 @@ namespace GitHub.Runner.Listener
WorkerDispatcher workerDispatcher; WorkerDispatcher workerDispatcher;
if (_jobInfos.TryRemove(currentDispatch.JobId, out workerDispatcher)) if (_jobInfos.TryRemove(currentDispatch.JobId, out workerDispatcher))
{ {
Trace.Verbose($"Remove WorkerDispatcher from {nameof(_jobInfos)} dictionary for job {currentDispatch.JobId}."); Trace.Verbose($"Remove WorkerDispather from {nameof(_jobInfos)} dictionary for job {currentDispatch.JobId}.");
workerDispatcher.Dispose(); workerDispatcher.Dispose();
} }
} }
@@ -209,7 +209,7 @@ namespace GitHub.Runner.Listener
{ {
try try
{ {
Trace.Info($"Ensure WorkerDispatcher for job {currentDispatch.JobId} run to finish, cancel any running job."); Trace.Info($"Ensure WorkerDispather for job {currentDispatch.JobId} run to finish, cancel any running job.");
await EnsureDispatchFinished(currentDispatch, cancelRunningJob: true); await EnsureDispatchFinished(currentDispatch, cancelRunningJob: true);
} }
catch (Exception ex) catch (Exception ex)
@@ -222,7 +222,7 @@ namespace GitHub.Runner.Listener
WorkerDispatcher workerDispatcher; WorkerDispatcher workerDispatcher;
if (_jobInfos.TryRemove(currentDispatch.JobId, out workerDispatcher)) if (_jobInfos.TryRemove(currentDispatch.JobId, out workerDispatcher))
{ {
Trace.Verbose($"Remove WorkerDispatcher from {nameof(_jobInfos)} dictionary for job {currentDispatch.JobId}."); Trace.Verbose($"Remove WorkerDispather from {nameof(_jobInfos)} dictionary for job {currentDispatch.JobId}.");
workerDispatcher.Dispose(); workerDispatcher.Dispose();
} }
} }
@@ -327,7 +327,7 @@ namespace GitHub.Runner.Listener
WorkerDispatcher workerDispatcher; WorkerDispatcher workerDispatcher;
if (_jobInfos.TryRemove(jobDispatch.JobId, out workerDispatcher)) if (_jobInfos.TryRemove(jobDispatch.JobId, out workerDispatcher))
{ {
Trace.Verbose($"Remove WorkerDispatcher from {nameof(_jobInfos)} dictionary for job {jobDispatch.JobId}."); Trace.Verbose($"Remove WorkerDispather from {nameof(_jobInfos)} dictionary for job {jobDispatch.JobId}.");
workerDispatcher.Dispose(); workerDispatcher.Dispose();
} }
} }

View File

@@ -9,7 +9,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Listener.Configuration; using GitHub.Runner.Listener.Configuration;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
@@ -124,15 +123,8 @@ 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 vssOAuthEx && creds.Federated is VssOAuthCredential vssOAuthCred) if (ex is VssOAuthTokenRequestException && 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. Runner registrations are automatically deleted for runners that have not connected to the service recently.");
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.");
@@ -140,7 +132,7 @@ namespace GitHub.Runner.Listener
var authError = await oauthTokenProvider.ValidateCredentialAsync(token); var authError = await oauthTokenProvider.ValidateCredentialAsync(token);
if (string.Equals(authError, "invalid_client", StringComparison.OrdinalIgnoreCase)) if (string.Equals(authError, "invalid_client", StringComparison.OrdinalIgnoreCase))
{ {
_term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure. Runner registrations are automatically deleted for runners that have not connected to the service recently."); _term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure.");
return false; return false;
} }
} }
@@ -220,8 +212,6 @@ namespace GitHub.Runner.Listener
_lastMessageId, _lastMessageId,
runnerStatus, runnerStatus,
BuildConstants.RunnerPackage.Version, BuildConstants.RunnerPackage.Version,
VarUtil.OS,
VarUtil.OSArchitecture,
_getMessagesTokenSource.Token); _getMessagesTokenSource.Token);
// Decrypt the message body if the session is using encryption // Decrypt the message body if the session is using encryption
@@ -255,7 +245,7 @@ namespace GitHub.Runner.Listener
_accessTokenRevoked = true; _accessTokenRevoked = true;
throw; throw;
} }
catch (AccessDeniedException e) when (e.ErrorCode == 1) catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
{ {
throw; throw;
} }

View File

@@ -138,7 +138,7 @@ namespace GitHub.Runner.Listener
} }
} }
catch (AccessDeniedException e) when (e.ErrorCode == 1) catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
{ {
terminal.WriteError($"An error occured: {e.Message}"); terminal.WriteError($"An error occured: {e.Message}");
trace.Error(e); trace.Error(e);

View File

@@ -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.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<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" />

View File

@@ -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 ulong _agentId; private int _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;

View File

@@ -6,8 +6,6 @@ using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using GitHub.Services.Common;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {
@@ -74,25 +72,6 @@ namespace GitHub.Runner.Sdk
} }
} }
public static async Task<string> GetFileContentSha256HashAsync(string path)
{
if (!File.Exists(path))
{
return string.Empty;
}
using (FileStream stream = File.OpenRead(path))
{
using (SHA256 sha256 = SHA256.Create())
{
byte[] srcHashBytes = await sha256.ComputeHashAsync(stream);
var hash = PrimitiveExtensions.ConvertToHexString(srcHashBytes);
return hash;
}
}
}
public static void Delete(string path, CancellationToken cancellationToken) public static void Delete(string path, CancellationToken cancellationToken)
{ {
DeleteDirectory(path, cancellationToken); DeleteDirectory(path, cancellationToken);

View File

@@ -1,6 +1,4 @@
using System; using System;
using System.Linq;
using System.Net.Http.Headers;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {
@@ -50,15 +48,5 @@ 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;
}
} }
} }

View File

@@ -85,35 +85,6 @@ namespace GitHub.Runner.Sdk
VssCredentials credentials, VssCredentials credentials,
IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null,
TimeSpan? timeout = null) TimeSpan? timeout = null)
{
RawClientHttpRequestSettings settings = GetHttpRequestSettings(timeout);
RawConnection connection = new(serverUri, new RawHttpMessageHandler(credentials.Federated, settings), additionalDelegatingHandler);
return connection;
}
public static VssCredentials GetVssCredential(ServiceEndpoint serviceEndpoint)
{
ArgUtil.NotNull(serviceEndpoint, nameof(serviceEndpoint));
ArgUtil.NotNull(serviceEndpoint.Authorization, nameof(serviceEndpoint.Authorization));
ArgUtil.NotNullOrEmpty(serviceEndpoint.Authorization.Scheme, nameof(serviceEndpoint.Authorization.Scheme));
if (serviceEndpoint.Authorization.Parameters.Count == 0)
{
throw new ArgumentOutOfRangeException(nameof(serviceEndpoint));
}
VssCredentials credentials = null;
string accessToken;
if (serviceEndpoint.Authorization.Scheme == EndpointAuthorizationSchemes.OAuth &&
serviceEndpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.AccessToken, out accessToken))
{
credentials = new VssCredentials(new VssOAuthAccessTokenCredential(accessToken), CredentialPromptType.DoNotPrompt);
}
return credentials;
}
public static RawClientHttpRequestSettings GetHttpRequestSettings(TimeSpan? timeout = null)
{ {
RawClientHttpRequestSettings settings = RawClientHttpRequestSettings.Default.Clone(); RawClientHttpRequestSettings settings = RawClientHttpRequestSettings.Default.Clone();
@@ -145,7 +116,30 @@ namespace GitHub.Runner.Sdk
// settings are applied to an HttpRequestMessage. // settings are applied to an HttpRequestMessage.
settings.AcceptLanguages.Remove(CultureInfo.InvariantCulture); settings.AcceptLanguages.Remove(CultureInfo.InvariantCulture);
return settings; RawConnection connection = new(serverUri, new RawHttpMessageHandler(credentials.Federated, settings), additionalDelegatingHandler);
return connection;
}
public static VssCredentials GetVssCredential(ServiceEndpoint serviceEndpoint)
{
ArgUtil.NotNull(serviceEndpoint, nameof(serviceEndpoint));
ArgUtil.NotNull(serviceEndpoint.Authorization, nameof(serviceEndpoint.Authorization));
ArgUtil.NotNullOrEmpty(serviceEndpoint.Authorization.Scheme, nameof(serviceEndpoint.Authorization.Scheme));
if (serviceEndpoint.Authorization.Parameters.Count == 0)
{
throw new ArgumentOutOfRangeException(nameof(serviceEndpoint));
}
VssCredentials credentials = null;
string accessToken;
if (serviceEndpoint.Authorization.Scheme == EndpointAuthorizationSchemes.OAuth &&
serviceEndpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.AccessToken, out accessToken))
{
credentials = new VssCredentials(new VssOAuthAccessTokenCredential(accessToken), CredentialPromptType.DoNotPrompt);
}
return credentials;
} }
} }
} }

View File

@@ -114,128 +114,6 @@ namespace GitHub.Runner.Sdk
} }
} }
#if OS_WINDOWS
trace?.Info($"{command}: command not found. Make sure '{command}' is installed and its location included in the 'Path' environment variable.");
#else
trace?.Info($"{command}: command not found. Make sure '{command}' is installed and its location included in the 'PATH' environment variable.");
#endif
if (require)
{
throw new FileNotFoundException(
message: $"{command}: command not found",
fileName: command);
}
return null;
}
public static string Which2(string command, bool require = false, ITraceWriter trace = null, string prependPath = null)
{
ArgUtil.NotNullOrEmpty(command, nameof(command));
trace?.Info($"Which2: '{command}'");
if (Path.IsPathFullyQualified(command) && File.Exists(command))
{
trace?.Info($"Fully qualified path: '{command}'");
return command;
}
string path = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
if (string.IsNullOrEmpty(path))
{
trace?.Info("PATH environment variable not defined.");
path = path ?? string.Empty;
}
if (!string.IsNullOrEmpty(prependPath))
{
path = PathUtil.PrependPath(prependPath, path);
}
string[] pathSegments = path.Split(new Char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < pathSegments.Length; i++)
{
pathSegments[i] = Environment.ExpandEnvironmentVariables(pathSegments[i]);
}
foreach (string pathSegment in pathSegments)
{
if (!string.IsNullOrEmpty(pathSegment) && Directory.Exists(pathSegment))
{
#if OS_WINDOWS
string pathExt = Environment.GetEnvironmentVariable("PATHEXT");
if (string.IsNullOrEmpty(pathExt))
{
// XP's system default value for PATHEXT system variable
pathExt = ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh";
}
string[] pathExtSegments = pathExt.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
// if command already has an extension.
if (pathExtSegments.Any(ext => command.EndsWith(ext, StringComparison.OrdinalIgnoreCase)))
{
try
{
foreach (var file in Directory.EnumerateFiles(pathSegment, command))
{
if (IsPathValid(file, trace))
{
trace?.Info($"Location: '{file}'");
return file;
}
}
}
catch (UnauthorizedAccessException ex)
{
trace?.Info("Ignore UnauthorizedAccess exception during Which.");
trace?.Verbose(ex.ToString());
}
}
else
{
string searchPattern;
searchPattern = StringUtil.Format($"{command}.*");
try
{
foreach (var file in Directory.EnumerateFiles(pathSegment, searchPattern))
{
// add extension.
for (int i = 0; i < pathExtSegments.Length; i++)
{
string fullPath = Path.Combine(pathSegment, $"{command}{pathExtSegments[i]}");
if (string.Equals(file, fullPath, StringComparison.OrdinalIgnoreCase) && IsPathValid(fullPath, trace))
{
trace?.Info($"Location: '{fullPath}'");
return fullPath;
}
}
}
}
catch (UnauthorizedAccessException ex)
{
trace?.Info("Ignore UnauthorizedAccess exception during Which.");
trace?.Verbose(ex.ToString());
}
}
#else
try
{
foreach (var file in Directory.EnumerateFiles(pathSegment, command))
{
if (IsPathValid(file, trace))
{
trace?.Info($"Location: '{file}'");
return file;
}
}
}
catch (UnauthorizedAccessException ex)
{
trace?.Info("Ignore UnauthorizedAccess exception during Which.");
trace?.Verbose(ex.ToString());
}
#endif
}
}
#if OS_WINDOWS #if OS_WINDOWS
trace?.Info($"{command}: command not found. Make sure '{command}' is installed and its location included in the 'Path' environment variable."); trace?.Info($"{command}: command not found. Make sure '{command}' is installed and its location included in the 'Path' environment variable.");
#else #else
@@ -256,12 +134,7 @@ namespace GitHub.Runner.Sdk
{ {
var fileInfo = new FileInfo(path); var fileInfo = new FileInfo(path);
var linkTargetFullPath = fileInfo.Directory?.FullName + Path.DirectorySeparatorChar + fileInfo.LinkTarget; var linkTargetFullPath = fileInfo.Directory?.FullName + Path.DirectorySeparatorChar + fileInfo.LinkTarget;
if (fileInfo.LinkTarget == null || if (fileInfo.LinkTarget == null || File.Exists(linkTargetFullPath) || File.Exists(fileInfo.LinkTarget)) return true;
File.Exists(linkTargetFullPath) ||
File.Exists(fileInfo.LinkTarget))
{
return true;
}
trace?.Info($"the target '{fileInfo.LinkTarget}' of the symbolic link '{path}', does not exist"); trace?.Info($"the target '{fileInfo.LinkTarget}' of the symbolic link '{path}', does not exist");
return false; return false;
} }

View File

@@ -6,20 +6,19 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Security.Cryptography;
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.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 WebApi = GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
namespace GitHub.Runner.Worker namespace GitHub.Runner.Worker
{ {
@@ -53,6 +52,7 @@ namespace GitHub.Runner.Worker
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k). //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
private const int _defaultCopyBufferSize = 81920; private const int _defaultCopyBufferSize = 81920;
private const string _dotcomApiUrl = "https://api.github.com";
private readonly Dictionary<Guid, ContainerInfo> _cachedActionContainers = new(); private readonly Dictionary<Guid, ContainerInfo> _cachedActionContainers = new();
public Dictionary<Guid, ContainerInfo> CachedActionContainers => _cachedActionContainers; public Dictionary<Guid, ContainerInfo> CachedActionContainers => _cachedActionContainers;
@@ -115,14 +115,6 @@ 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)
@@ -739,7 +731,10 @@ namespace GitHub.Runner.Worker
ArgUtil.NotNull(actionDownloadInfos, nameof(actionDownloadInfos)); ArgUtil.NotNull(actionDownloadInfos, nameof(actionDownloadInfos));
ArgUtil.NotNull(actionDownloadInfos.Actions, nameof(actionDownloadInfos.Actions)); ArgUtil.NotNull(actionDownloadInfos.Actions, nameof(actionDownloadInfos.Actions));
var apiUrl = GetApiUrl(executionContext);
var defaultAccessToken = executionContext.GetGitHubContext("token"); var defaultAccessToken = executionContext.GetGitHubContext("token");
var configurationStore = HostContext.GetService<IConfigurationStore>();
var runnerSettings = configurationStore.GetSettings();
foreach (var actionDownloadInfo in actionDownloadInfos.Actions.Values) foreach (var actionDownloadInfo in actionDownloadInfos.Actions.Values)
{ {
@@ -763,8 +758,6 @@ namespace GitHub.Runner.Worker
ArgUtil.NotNull(downloadInfo, nameof(downloadInfo)); ArgUtil.NotNull(downloadInfo, nameof(downloadInfo));
ArgUtil.NotNullOrEmpty(downloadInfo.NameWithOwner, nameof(downloadInfo.NameWithOwner)); ArgUtil.NotNullOrEmpty(downloadInfo.NameWithOwner, nameof(downloadInfo.NameWithOwner));
ArgUtil.NotNullOrEmpty(downloadInfo.Ref, nameof(downloadInfo.Ref)); ArgUtil.NotNullOrEmpty(downloadInfo.Ref, nameof(downloadInfo.Ref));
ArgUtil.NotNullOrEmpty(downloadInfo.Ref, nameof(downloadInfo.ResolvedNameWithOwner));
ArgUtil.NotNullOrEmpty(downloadInfo.Ref, nameof(downloadInfo.ResolvedSha));
string destDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), downloadInfo.NameWithOwner.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), downloadInfo.Ref); string destDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), downloadInfo.NameWithOwner.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), downloadInfo.Ref);
string watermarkFile = GetWatermarkFilePath(destDirectory); string watermarkFile = GetWatermarkFilePath(destDirectory);
@@ -781,6 +774,31 @@ namespace GitHub.Runner.Worker
executionContext.Output($"Download action repository '{downloadInfo.NameWithOwner}@{downloadInfo.Ref}' (SHA:{downloadInfo.ResolvedSha})"); executionContext.Output($"Download action repository '{downloadInfo.NameWithOwner}@{downloadInfo.Ref}' (SHA:{downloadInfo.ResolvedSha})");
} }
await DownloadRepositoryActionAsync(executionContext, downloadInfo, destDirectory);
}
private string GetApiUrl(IExecutionContext executionContext)
{
string apiUrl = executionContext.GetGitHubContext("api_url");
if (!string.IsNullOrEmpty(apiUrl))
{
return apiUrl;
}
// Once the api_url is set for hosted, we can remove this fallback (it doesn't make sense for GHES)
return _dotcomApiUrl;
}
private static string BuildLinkToActionArchive(string apiUrl, string repository, string @ref)
{
#if OS_WINDOWS
return $"{apiUrl}/repos/{repository}/zipball/{@ref}";
#else
return $"{apiUrl}/repos/{repository}/tarball/{@ref}";
#endif
}
private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, WebApi.ActionDownloadInfo downloadInfo, string destDirectory)
{
//download and extract action in a temp folder and rename it on success //download and extract action in a temp folder and rename it on success
string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), "_temp_" + Guid.NewGuid()); string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), "_temp_" + Guid.NewGuid());
Directory.CreateDirectory(tempDirectory); Directory.CreateDirectory(tempDirectory);
@@ -793,76 +811,108 @@ namespace GitHub.Runner.Worker
string link = downloadInfo?.TarballUrl; string link = downloadInfo?.TarballUrl;
#endif #endif
Trace.Info($"Save archive '{link}' into {archiveFile}.");
try try
{ {
var useActionArchiveCache = false; int retryCount = 0;
if (executionContext.Global.Variables.GetBoolean("DistributedTask.UseActionArchiveCache") == true)
// Allow up to 20 * 60s for any action to be downloaded from github graph.
int timeoutSeconds = 20 * 60;
while (retryCount < 3)
{ {
var hasActionArchiveCache = false; using (var actionDownloadTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)))
var actionArchiveCacheDir = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ActionArchiveCacheDirectory); using (var actionDownloadCancellation = CancellationTokenSource.CreateLinkedTokenSource(actionDownloadTimeout.Token, executionContext.CancellationToken))
if (!string.IsNullOrEmpty(actionArchiveCacheDir) &&
Directory.Exists(actionArchiveCacheDir))
{ {
hasActionArchiveCache = true; try
Trace.Info($"Check if action archive '{downloadInfo.ResolvedNameWithOwner}@{downloadInfo.ResolvedSha}' already exists in cache directory '{actionArchiveCacheDir}'");
#if OS_WINDOWS
var cacheArchiveFile = Path.Combine(actionArchiveCacheDir, downloadInfo.ResolvedNameWithOwner.Replace(Path.DirectorySeparatorChar, '_').Replace(Path.AltDirectorySeparatorChar, '_'), $"{downloadInfo.ResolvedSha}.zip");
#else
var cacheArchiveFile = Path.Combine(actionArchiveCacheDir, downloadInfo.ResolvedNameWithOwner.Replace(Path.DirectorySeparatorChar, '_').Replace(Path.AltDirectorySeparatorChar, '_'), $"{downloadInfo.ResolvedSha}.tar.gz");
#endif
if (File.Exists(cacheArchiveFile))
{ {
try //open zip stream in async mode
using (FileStream fs = new(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var httpClient = new HttpClient(httpClientHandler))
{ {
Trace.Info($"Found action archive '{cacheArchiveFile}' in cache directory '{actionArchiveCacheDir}'"); httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(downloadInfo.Authentication?.Token);
File.Copy(cacheArchiveFile, archiveFile);
useActionArchiveCache = true; httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
executionContext.Debug($"Copied action archive '{cacheArchiveFile}' to '{archiveFile}'"); using (var response = await httpClient.GetAsync(link))
{
if (response.IsSuccessStatusCode)
{
using (var result = await response.Content.ReadAsStreamAsync())
{
await result.CopyToAsync(fs, _defaultCopyBufferSize, actionDownloadCancellation.Token);
await fs.FlushAsync(actionDownloadCancellation.Token);
// download succeed, break out the retry loop.
break;
}
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
// It doesn't make sense to retry in this case, so just stop
throw new ActionNotFoundException(new Uri(link));
}
else
{
// Something else bad happened, let's go to our retry logic
response.EnsureSuccessStatusCode();
}
}
} }
catch (Exception ex) }
catch (OperationCanceledException) when (executionContext.CancellationToken.IsCancellationRequested)
{
Trace.Info("Action download has been cancelled.");
throw;
}
catch (ActionNotFoundException)
{
Trace.Info($"The action at '{link}' does not exist");
throw;
}
catch (Exception ex) when (retryCount < 2)
{
retryCount++;
Trace.Error($"Fail to download archive '{link}' -- Attempt: {retryCount}");
Trace.Error(ex);
if (actionDownloadTimeout.Token.IsCancellationRequested)
{ {
Trace.Error($"Failed to copy action archive '{cacheArchiveFile}' to '{archiveFile}'. Error: {ex}"); // action download didn't finish within timeout
executionContext.Warning($"Action '{link}' didn't finish download within {timeoutSeconds} seconds.");
}
else
{
executionContext.Warning($"Failed to download action '{link}'. Error: {ex.Message}");
} }
} }
} }
executionContext.Global.JobTelemetry.Add(new JobTelemetry() if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_DOWNLOAD_NO_BACKOFF")))
{ {
Type = JobTelemetryType.General, var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
Message = $"Action archive cache usage: {downloadInfo.ResolvedNameWithOwner}@{downloadInfo.ResolvedSha} use cache {useActionArchiveCache} has cache {hasActionArchiveCache}" executionContext.Warning($"Back off {backOff.TotalSeconds} seconds before retry.");
}); await Task.Delay(backOff);
}
} }
if (!useActionArchiveCache) ArgUtil.NotNullOrEmpty(archiveFile, nameof(archiveFile));
{ executionContext.Debug($"Download '{link}' to '{archiveFile}'");
await DownloadRepositoryArchive(executionContext, link, downloadInfo.Authentication?.Token, archiveFile);
}
var stagingDirectory = Path.Combine(tempDirectory, "_staging"); var stagingDirectory = Path.Combine(tempDirectory, "_staging");
Directory.CreateDirectory(stagingDirectory); Directory.CreateDirectory(stagingDirectory);
#if OS_WINDOWS #if OS_WINDOWS
try ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
{
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);
// tar -xzf // tar -xzf
using (var processInvoker = HostContext.CreateService<IProcessInvoker>()) using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
{ {
var tarOutputs = new List<string>();
processInvoker.OutputDataReceived += new EventHandler<ProcessDataReceivedEventArgs>((sender, args) => processInvoker.OutputDataReceived += new EventHandler<ProcessDataReceivedEventArgs>((sender, args) =>
{ {
if (!string.IsNullOrEmpty(args.Data)) if (!string.IsNullOrEmpty(args.Data))
{ {
Trace.Info(args.Data); Trace.Info(args.Data);
tarOutputs.Add($"STDOUT: {args.Data}");
} }
}); });
@@ -871,23 +921,13 @@ namespace GitHub.Runner.Worker
if (!string.IsNullOrEmpty(args.Data)) if (!string.IsNullOrEmpty(args.Data))
{ {
Trace.Error(args.Data); Trace.Error(args.Data);
tarOutputs.Add($"STDERR: {args.Data}");
} }
}); });
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)
{ {
if (executionContext.Global.Variables.GetBoolean("DistributedTask.DetailUntarFailure") == true) throw new NotSupportedException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. return code: {exitCode}.");
{
var fileInfo = new FileInfo(archiveFile);
var sha256hash = await IOUtil.GetFileContentSha256HashAsync(archiveFile);
throw new InvalidActionArchiveException($"Can't use 'tar -xzf' extract archive file: {archiveFile} (SHA256 '{sha256hash}', size '{fileInfo.Length}' bytes, tar outputs '{string.Join(' ', tarOutputs)}'). Action being checked out: {downloadInfo.NameWithOwner}@{downloadInfo.Ref}. return code: {exitCode}.");
}
else
{
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
@@ -905,6 +945,7 @@ namespace GitHub.Runner.Worker
} }
Trace.Verbose("Create watermark file indicate action download succeed."); Trace.Verbose("Create watermark file indicate action download succeed.");
string watermarkFile = GetWatermarkFilePath(destDirectory);
File.WriteAllText(watermarkFile, DateTime.UtcNow.ToString()); File.WriteAllText(watermarkFile, DateTime.UtcNow.ToString());
executionContext.Debug($"Archive '{archiveFile}' has been unzipped into '{destDirectory}'."); executionContext.Debug($"Archive '{archiveFile}' has been unzipped into '{destDirectory}'.");
@@ -929,6 +970,29 @@ namespace GitHub.Runner.Worker
} }
} }
private void ConfigureAuthorizationFromContext(IExecutionContext executionContext, HttpClient httpClient)
{
var authToken = Environment.GetEnvironmentVariable("_GITHUB_ACTION_TOKEN");
if (string.IsNullOrEmpty(authToken))
{
// TODO: Deprecate the PREVIEW_ACTION_TOKEN
authToken = executionContext.Global.Variables.Get("PREVIEW_ACTION_TOKEN");
}
if (!string.IsNullOrEmpty(authToken))
{
HostContext.SecretMasker.AddValue(authToken);
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"PAT:{authToken}"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken);
}
else
{
var accessToken = executionContext.GetGitHubContext("token");
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{accessToken}"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken);
}
}
private string GetWatermarkFilePath(string directory) => directory + ".completed"; private string GetWatermarkFilePath(string directory) => directory + ".completed";
private ActionSetupInfo PrepareRepositoryActionAsync(IExecutionContext executionContext, Pipelines.ActionStep repositoryAction) private ActionSetupInfo PrepareRepositoryActionAsync(IExecutionContext executionContext, Pipelines.ActionStep repositoryAction)
@@ -1101,6 +1165,13 @@ namespace GitHub.Runner.Worker
return $"{repositoryReference.Name}@{repositoryReference.Ref}"; return $"{repositoryReference.Name}@{repositoryReference.Ref}";
} }
private static string GetDownloadInfoLookupKey(WebApi.ActionDownloadInfo info)
{
ArgUtil.NotNullOrEmpty(info.NameWithOwner, nameof(info.NameWithOwner));
ArgUtil.NotNullOrEmpty(info.Ref, nameof(info.Ref));
return $"{info.NameWithOwner}@{info.Ref}";
}
private AuthenticationHeaderValue CreateAuthHeader(string token) private AuthenticationHeaderValue CreateAuthHeader(string token)
{ {
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@@ -1112,104 +1183,6 @@ namespace GitHub.Runner.Worker
HostContext.SecretMasker.AddValue(base64EncodingToken); HostContext.SecretMasker.AddValue(base64EncodingToken);
return new AuthenticationHeaderValue("Basic", base64EncodingToken); return new AuthenticationHeaderValue("Basic", base64EncodingToken);
} }
private async Task DownloadRepositoryArchive(IExecutionContext executionContext, string downloadUrl, string downloadAuthToken, string archiveFile)
{
Trace.Info($"Save archive '{downloadUrl}' into {archiveFile}.");
int retryCount = 0;
// Allow up to 20 * 60s for any action to be downloaded from github graph.
int timeoutSeconds = 20 * 60;
while (retryCount < 3)
{
using (var actionDownloadTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)))
using (var actionDownloadCancellation = CancellationTokenSource.CreateLinkedTokenSource(actionDownloadTimeout.Token, executionContext.CancellationToken))
{
try
{
//open zip stream in async mode
using (FileStream fs = new(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var httpClient = new HttpClient(httpClientHandler))
{
httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(downloadAuthToken);
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
using (var response = await httpClient.GetAsync(downloadUrl))
{
var requestId = UrlUtil.GetGitHubRequestId(response.Headers);
if (!string.IsNullOrEmpty(requestId))
{
Trace.Info($"Request URL: {downloadUrl} X-GitHub-Request-Id: {requestId} Http Status: {response.StatusCode}");
}
if (response.IsSuccessStatusCode)
{
using (var result = await response.Content.ReadAsStreamAsync())
{
await result.CopyToAsync(fs, _defaultCopyBufferSize, actionDownloadCancellation.Token);
await fs.FlushAsync(actionDownloadCancellation.Token);
// download succeed, break out the retry loop.
break;
}
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
// It doesn't make sense to retry in this case, so just stop
throw new ActionNotFoundException(new Uri(downloadUrl), requestId);
}
else
{
// Something else bad happened, let's go to our retry logic
response.EnsureSuccessStatusCode();
}
}
}
}
catch (OperationCanceledException) when (executionContext.CancellationToken.IsCancellationRequested)
{
Trace.Info("Action download has been cancelled.");
throw;
}
catch (OperationCanceledException ex) when (!executionContext.CancellationToken.IsCancellationRequested && retryCount >= 2)
{
Trace.Info($"Action download final retry timeout after {timeoutSeconds} seconds.");
throw new TimeoutException($"Action '{downloadUrl}' download has timed out. Error: {ex.Message}");
}
catch (ActionNotFoundException)
{
Trace.Info($"The action at '{downloadUrl}' does not exist");
throw;
}
catch (Exception ex) when (retryCount < 2)
{
retryCount++;
Trace.Error($"Fail to download archive '{downloadUrl}' -- Attempt: {retryCount}");
Trace.Error(ex);
if (actionDownloadTimeout.Token.IsCancellationRequested)
{
// action download didn't finish within timeout
executionContext.Warning($"Action '{downloadUrl}' didn't finish download within {timeoutSeconds} seconds.");
}
else
{
executionContext.Warning($"Failed to download action '{downloadUrl}'. Error: {ex.Message}");
}
}
}
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_DOWNLOAD_NO_BACKOFF")))
{
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
executionContext.Warning($"Back off {backOff.TotalSeconds} seconds before retry.");
await Task.Delay(backOff);
}
}
ArgUtil.NotNullOrEmpty(archiveFile, nameof(archiveFile));
executionContext.Debug($"Download '{downloadUrl}' to '{archiveFile}'");
}
} }
public sealed class Definition public sealed class Definition

View File

@@ -449,8 +449,7 @@ 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))
{ {
@@ -490,7 +489,7 @@ namespace GitHub.Runner.Worker
} }
else else
{ {
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12', 'node16' or 'node20' instead."); throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12' or 'node16' instead.");
} }
} }
else if (pluginToken != null) else if (pluginToken != null)
@@ -501,7 +500,7 @@ namespace GitHub.Runner.Worker
}; };
} }
throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12', 'node16' or 'node20'."); throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.");
} }
private void ConvertInputs( private void ConvertInputs(

View File

@@ -5,8 +5,8 @@ namespace GitHub.Runner.Worker
{ {
public class ActionNotFoundException : Exception public class ActionNotFoundException : Exception
{ {
public ActionNotFoundException(Uri actionUri, string requestId) public ActionNotFoundException(Uri actionUri)
: base(FormatMessage(actionUri, requestId)) : base(FormatMessage(actionUri))
{ {
} }
@@ -25,13 +25,8 @@ namespace GitHub.Runner.Worker
{ {
} }
private static string FormatMessage(Uri actionUri, string requestId) private static string FormatMessage(Uri actionUri)
{ {
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}'";
} }
} }

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Channels; using System.Threading.Channels;
@@ -47,9 +46,7 @@ namespace GitHub.Runner.Worker.Container
{ {
base.Initialize(hostContext); base.Initialize(hostContext);
DockerPath = WhichUtil.Which("docker", true, Trace); DockerPath = WhichUtil.Which("docker", true, Trace);
string path = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), ".runner"); DockerInstanceLabel = IOUtil.GetSha256Hash(hostContext.GetDirectory(WellKnownDirectory.Root)).Substring(0, 6);
string json = File.ReadAllText(path, Encoding.UTF8);
DockerInstanceLabel = IOUtil.GetSha256Hash(json).Substring(0, 6);
} }
public async Task<DockerVersion> DockerVersion(IExecutionContext context) public async Task<DockerVersion> DockerVersion(IExecutionContext context)

View File

@@ -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();
ulong runnerId = settings.AgentId; int runnerId = settings.AgentId;
string runnerName = settings.AgentName; string runnerName = settings.AgentName;
int poolId = settings.PoolId; int poolId = settings.PoolId;

View File

@@ -807,9 +807,9 @@ namespace GitHub.Runner.Worker
Global.Variables = new Variables(HostContext, variables); Global.Variables = new Variables(HostContext, variables);
if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo16") ?? false) if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo12") ?? false)
{ {
Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion, "node16"); Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion, "node12");
} }
// Environment variables shared across all actions // Environment variables shared across all actions

View File

@@ -141,28 +141,6 @@ 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);
} }
} }
@@ -176,11 +154,6 @@ 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
@@ -349,21 +322,9 @@ namespace GitHub.Runner.Worker
var equalsIndex = line.IndexOf("=", StringComparison.Ordinal); var equalsIndex = line.IndexOf("=", StringComparison.Ordinal);
var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal); var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal);
// Normal style NAME=VALUE // Heredoc style NAME<<EOF (where EOF is typically randomly-generated Base64 and may include an '=' character)
if (equalsIndex >= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex)) // see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
{ if (heredocIndex >= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex))
var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None);
if (string.IsNullOrEmpty(line))
{
throw new Exception($"Invalid format '{line}'. Name must not be empty");
}
key = split[0];
output = split[1];
}
// Heredoc style NAME<<EOF
else if (heredocIndex >= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex))
{ {
var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None); var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None);
if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1])) if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1]))
@@ -391,6 +352,18 @@ namespace GitHub.Runner.Worker
output = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty; output = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty;
} }
// Normal style NAME=VALUE
else if (equalsIndex >= 0 && heredocIndex < 0)
{
var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None);
if (string.IsNullOrEmpty(line))
{
throw new Exception($"Invalid format '{line}'. Name must not be empty");
}
key = split[0];
output = split[1];
}
else else
{ {
throw new Exception($"Invalid format '{line}'"); throw new Exception($"Invalid format '{line}'");

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -228,10 +228,6 @@ 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)
{ {

View File

@@ -58,31 +58,40 @@ 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))
{ {
var repoAction = action as Pipelines.RepositoryPathReference; // 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
if (repoAction != null) executionContext.Global.EnvironmentVariables.TryGetValue(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, out var workflowOptOut);
var isWorkflowOptOutSet = !string.IsNullOrEmpty(workflowOptOut);
var isLocalOptOut = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion));
bool isOptOut = isWorkflowOptOutSet ? StringUtil.ConvertToBoolean(workflowOptOut) : isLocalOptOut;
if (!isOptOut)
{ {
var warningActions = new HashSet<string>(); var repoAction = action as Pipelines.RepositoryPathReference;
if (executionContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings)) if (repoAction != null)
{ {
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings); var warningActions = new HashSet<string>();
} if (executionContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
{
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings);
}
string repoActionFullName; var repoActionFullName = "";
if (string.IsNullOrEmpty(repoAction.Name)) if (string.IsNullOrEmpty(repoAction.Name))
{ {
repoActionFullName = repoAction.Path; // local actions don't have a 'Name' repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
} }
else else
{ {
repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}"; repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
} }
warningActions.Add(repoActionFullName); warningActions.Add(repoActionFullName);
executionContext.Global.Variables.Set("Node16ForceActionsWarnings", StringUtil.ConvertToJson(warningActions)); executionContext.Global.Variables.Set("Node16ForceActionsWarnings", StringUtil.ConvertToJson(warningActions));
}
nodeData.NodeVersion = "node16";
} }
nodeData.NodeVersion = "node16";
} }
(handler as INodeScriptActionHandler).Data = nodeData; (handler as INodeScriptActionHandler).Data = nodeData;
} }

View File

@@ -63,10 +63,6 @@ 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;
@@ -102,14 +98,20 @@ 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))
{ {
ExecutionContext.Output($"The node12 is not supported. Use node16 instead."); #if OS_OSX
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";
@@ -134,26 +136,27 @@ 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 (string.Equals(Data.NodeVersion, Constants.Runner.DeprecatedNodeVersion, StringComparison.OrdinalIgnoreCase) && (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.Node16Warning) ?? false)) if (Data.NodeVersion == "node12" && (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.Node12Warning) ?? false))
{ {
var repoAction = Action as RepositoryPathReference; var repoAction = Action as RepositoryPathReference;
var warningActions = new HashSet<string>(); var warningActions = new HashSet<string>();
if (ExecutionContext.Global.Variables.TryGetValue(Constants.Runner.DeprecatedNodeDetectedAfterEndOfLifeActions, out var deprecatedNodeWarnings)) if (ExecutionContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
{ {
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(deprecatedNodeWarnings); warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings);
} }
var repoActionFullName = "";
if (string.IsNullOrEmpty(repoAction.Name)) if (string.IsNullOrEmpty(repoAction.Name))
{ {
// local actions don't have a 'Name' repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
warningActions.Add(repoAction.Path);
} }
else else
{ {
warningActions.Add($"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}"); repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
} }
ExecutionContext.Global.Variables.Set(Constants.Runner.DeprecatedNodeDetectedAfterEndOfLifeActions, StringUtil.ConvertToJson(warningActions)); 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))

View File

@@ -83,40 +83,19 @@ namespace GitHub.Runner.Worker.Handlers
shellCommand = "pwsh"; shellCommand = "pwsh";
if (validateShellOnHost) if (validateShellOnHost)
{ {
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) shellCommandPath = WhichUtil.Which(shellCommand, require: false, Trace, prependPath);
{
shellCommandPath = WhichUtil.Which2(shellCommand, require: false, Trace, prependPath);
}
else
{
shellCommandPath = WhichUtil.Which(shellCommand, require: false, Trace, prependPath);
}
if (string.IsNullOrEmpty(shellCommandPath)) if (string.IsNullOrEmpty(shellCommandPath))
{ {
shellCommand = "powershell"; shellCommand = "powershell";
Trace.Info($"Defaulting to {shellCommand}"); Trace.Info($"Defaulting to {shellCommand}");
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) shellCommandPath = WhichUtil.Which(shellCommand, require: true, Trace, prependPath);
{
shellCommandPath = WhichUtil.Which2(shellCommand, require: true, Trace, prependPath);
}
else
{
shellCommandPath = WhichUtil.Which(shellCommand, require: true, Trace, prependPath);
}
} }
} }
#else #else
shellCommand = "sh"; shellCommand = "sh";
if (validateShellOnHost) if (validateShellOnHost)
{ {
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) shellCommandPath = WhichUtil.Which("bash", false, Trace, prependPath) ?? WhichUtil.Which("sh", true, Trace, prependPath);
{
shellCommandPath = WhichUtil.Which2("bash", false, Trace, prependPath) ?? WhichUtil.Which2("sh", true, Trace, prependPath);
}
else
{
shellCommandPath = WhichUtil.Which("bash", false, Trace, prependPath) ?? WhichUtil.Which("sh", true, Trace, prependPath);
}
} }
#endif #endif
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand); argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand);
@@ -127,14 +106,7 @@ namespace GitHub.Runner.Worker.Handlers
shellCommand = parsed.shellCommand; shellCommand = parsed.shellCommand;
if (validateShellOnHost) if (validateShellOnHost)
{ {
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) shellCommandPath = WhichUtil.Which(parsed.shellCommand, true, Trace, prependPath);
{
shellCommandPath = WhichUtil.Which2(parsed.shellCommand, true, Trace, prependPath);
}
else
{
shellCommandPath = WhichUtil.Which(parsed.shellCommand, true, Trace, prependPath);
}
} }
argFormat = $"{parsed.shellArgs}".TrimStart(); argFormat = $"{parsed.shellArgs}".TrimStart();
@@ -216,38 +188,17 @@ namespace GitHub.Runner.Worker.Handlers
{ {
#if OS_WINDOWS #if OS_WINDOWS
shellCommand = "pwsh"; shellCommand = "pwsh";
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) commandPath = WhichUtil.Which(shellCommand, require: false, Trace, prependPath);
{
commandPath = WhichUtil.Which2(shellCommand, require: false, Trace, prependPath);
}
else
{
commandPath = WhichUtil.Which(shellCommand, require: false, Trace, prependPath);
}
if (string.IsNullOrEmpty(commandPath)) if (string.IsNullOrEmpty(commandPath))
{ {
shellCommand = "powershell"; shellCommand = "powershell";
Trace.Info($"Defaulting to {shellCommand}"); Trace.Info($"Defaulting to {shellCommand}");
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) commandPath = WhichUtil.Which(shellCommand, require: true, Trace, prependPath);
{
commandPath = WhichUtil.Which2(shellCommand, require: true, Trace, prependPath);
}
else
{
commandPath = WhichUtil.Which(shellCommand, require: true, Trace, prependPath);
}
} }
ArgUtil.NotNullOrEmpty(commandPath, "Default Shell"); ArgUtil.NotNullOrEmpty(commandPath, "Default Shell");
#else #else
shellCommand = "sh"; shellCommand = "sh";
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) commandPath = WhichUtil.Which("bash", false, Trace, prependPath) ?? WhichUtil.Which("sh", true, Trace, prependPath);
{
commandPath = WhichUtil.Which2("bash", false, Trace, prependPath) ?? WhichUtil.Which2("sh", true, Trace, prependPath);
}
else
{
commandPath = WhichUtil.Which("bash", false, Trace, prependPath) ?? WhichUtil.Which("sh", true, Trace, prependPath);
}
#endif #endif
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand); argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand);
} }
@@ -258,14 +209,7 @@ namespace GitHub.Runner.Worker.Handlers
if (!IsActionStep && systemShells.Contains(shell)) if (!IsActionStep && systemShells.Contains(shell))
{ {
shellCommand = shell; shellCommand = shell;
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) commandPath = WhichUtil.Which(shell, !isContainerStepHost, Trace, prependPath);
{
commandPath = WhichUtil.Which2(shell, !isContainerStepHost, Trace, prependPath);
}
else
{
commandPath = WhichUtil.Which(shell, !isContainerStepHost, Trace, prependPath);
}
if (shell == "bash") if (shell == "bash")
{ {
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat("sh"); argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat("sh");
@@ -280,14 +224,7 @@ namespace GitHub.Runner.Worker.Handlers
var parsed = ScriptHandlerHelpers.ParseShellOptionString(shell); var parsed = ScriptHandlerHelpers.ParseShellOptionString(shell);
shellCommand = parsed.shellCommand; shellCommand = parsed.shellCommand;
// For non-ContainerStepHost, the command must be located on the host by Which // For non-ContainerStepHost, the command must be located on the host by Which
if (ExecutionContext.Global.Variables.GetBoolean("DistributedTask.UseWhich2") == true) commandPath = WhichUtil.Which(parsed.shellCommand, !isContainerStepHost, Trace, prependPath);
{
commandPath = WhichUtil.Which2(parsed.shellCommand, !isContainerStepHost, Trace, prependPath);
}
else
{
commandPath = WhichUtil.Which(parsed.shellCommand, !isContainerStepHost, Trace, prependPath);
}
argFormat = $"{parsed.shellArgs}".TrimStart(); argFormat = $"{parsed.shellArgs}".TrimStart();
if (string.IsNullOrEmpty(argFormat)) if (string.IsNullOrEmpty(argFormat))
{ {

View File

@@ -51,13 +51,6 @@ namespace GitHub.Runner.Worker
HostContext.UserAgents.Add(new ProductInfoHeaderValue("OrchestrationId", orchestrationId.Value)); HostContext.UserAgents.Add(new ProductInfoHeaderValue("OrchestrationId", orchestrationId.Value));
} }
var jobServerQueueTelemetry = false;
if (message.Variables.TryGetValue("DistributedTask.EnableJobServerQueueTelemetry", out VariableValue enableJobServerQueueTelemetry) &&
!string.IsNullOrEmpty(enableJobServerQueueTelemetry?.Value))
{
jobServerQueueTelemetry = StringUtil.ConvertToBoolean(enableJobServerQueueTelemetry.Value);
}
ServiceEndpoint systemConnection = message.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase)); ServiceEndpoint systemConnection = message.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
if (MessageUtil.IsRunServiceJob(message.MessageType)) if (MessageUtil.IsRunServiceJob(message.MessageType))
{ {
@@ -79,7 +72,7 @@ namespace GitHub.Runner.Worker
launchServer.InitializeLaunchClient(new Uri(launchReceiverEndpoint), accessToken); launchServer.InitializeLaunchClient(new Uri(launchReceiverEndpoint), accessToken);
} }
_jobServerQueue = HostContext.GetService<IJobServerQueue>(); _jobServerQueue = HostContext.GetService<IJobServerQueue>();
_jobServerQueue.Start(message, resultsServiceOnly: true, enableTelemetry: jobServerQueueTelemetry); _jobServerQueue.Start(message, resultServiceOnly: true);
} }
else else
{ {
@@ -91,17 +84,10 @@ 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>();
var delegatingHandlers = new List<DelegatingHandler>() { new ThrottlingReportHandler(_jobServerQueue) }; VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential, new 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, enableTelemetry: jobServerQueueTelemetry); _jobServerQueue.Start(message);
server = jobServer; server = jobServer;
} }
@@ -283,16 +269,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(Constants.Runner.DeprecatedNodeDetectedAfterEndOfLifeActions, out var deprecatedNodeWarnings)) if (jobContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
{ {
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(deprecatedNodeWarnings)); var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings));
jobContext.Warning(string.Format(Constants.Runner.DetectedNodeAfterEndOfLifeMessage, actions)); jobContext.Warning(string.Format(Constants.Runner.Node12DetectedAfterEndOfLife, actions));
}
if (jobContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
{
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings));
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.
@@ -388,10 +368,10 @@ namespace GitHub.Runner.Worker
} }
} }
if (jobContext.Global.Variables.TryGetValue(Constants.Runner.DeprecatedNodeDetectedAfterEndOfLifeActions, out var deprecatedNodeWarnings)) if (jobContext.Global.Variables.TryGetValue("Node12ActionsWarnings", out var node12Warnings))
{ {
var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(deprecatedNodeWarnings)); var actions = string.Join(", ", StringUtil.ConvertFromJson<HashSet<string>>(node12Warnings));
jobContext.Warning(string.Format(Constants.Runner.DetectedNodeAfterEndOfLifeMessage, actions)); jobContext.Warning(string.Format(Constants.Runner.Node12DetectedAfterEndOfLife, actions));
} }
if (jobContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings)) if (jobContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
@@ -402,12 +382,7 @@ namespace GitHub.Runner.Worker
try try
{ {
var jobQueueTelemetry = await ShutdownQueue(throwOnFailure: true); await ShutdownQueue(throwOnFailure: true);
// include any job telemetry from the background upload process.
if (jobQueueTelemetry.Count > 0)
{
jobContext.Global.JobTelemetry.AddRange(jobQueueTelemetry);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -509,7 +484,7 @@ namespace GitHub.Runner.Worker
} }
} }
private async Task<IList<JobTelemetry>> ShutdownQueue(bool throwOnFailure) private async Task ShutdownQueue(bool throwOnFailure)
{ {
if (_jobServerQueue != null) if (_jobServerQueue != null)
{ {
@@ -517,7 +492,6 @@ namespace GitHub.Runner.Worker
{ {
Trace.Info("Shutting down the job server queue."); Trace.Info("Shutting down the job server queue.");
await _jobServerQueue.ShutdownAsync(); await _jobServerQueue.ShutdownAsync();
return _jobServerQueue.JobTelemetries;
} }
catch (Exception ex) when (!throwOnFailure) catch (Exception ex) when (!throwOnFailure)
{ {
@@ -529,8 +503,6 @@ namespace GitHub.Runner.Worker
_jobServerQueue = null; // Prevent multiple attempts. _jobServerQueue = null; // Prevent multiple attempts.
} }
} }
return Array.Empty<JobTelemetry>();
} }
} }
} }

View File

@@ -1,22 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace GitHub.Services.Common
{
// Set of classes used to bypass token operations
// Results Service and External services follow a different auth model but
// we are required to pass in a credentials object to create a RawHttpMessageHandler
public class NoOpCredentials : FederatedCredential
{
public NoOpCredentials(IssuedToken initialToken) : base(initialToken)
{
}
public override VssCredentialsType CredentialType { get; }
protected override IssuedTokenProvider OnCreateTokenProvider(Uri serverUrl, IHttpResponse response)
{
return null;
}
}
}

View File

@@ -109,7 +109,7 @@ namespace GitHub.Services.Common
lock (m_thisLock) lock (m_thisLock)
{ {
// Ensure that we attempt to use the most appropriate authentication mechanism by default. // Ensure that we attempt to use the most appropriate authentication mechanism by default.
if (m_tokenProvider == null && !(this.Credentials is NoOpCredentials)) if (m_tokenProvider == null)
{ {
m_tokenProvider = this.Credentials.CreateTokenProvider(request.RequestUri, null, null); m_tokenProvider = this.Credentials.CreateTokenProvider(request.RequestUri, null, null);
} }
@@ -121,8 +121,7 @@ namespace GitHub.Services.Common
HttpResponseMessageWrapper responseWrapper; HttpResponseMessageWrapper responseWrapper;
Boolean lastResponseDemandedProxyAuth = false; Boolean lastResponseDemandedProxyAuth = false;
// do not retry if we cannot recreate tokens Int32 retries = m_maxAuthRetries;
Int32 retries = this.Credentials is NoOpCredentials ? 0 : m_maxAuthRetries;
try try
{ {
tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
@@ -139,12 +138,8 @@ namespace GitHub.Services.Common
} }
// Let's start with sending a token // Let's start with sending a token
IssuedToken token = null; IssuedToken token = await m_tokenProvider.GetTokenAsync(null, tokenSource.Token).ConfigureAwait(false);
if (m_tokenProvider != null) ApplyToken(request, token, applyICredentialsToWebProxy: lastResponseDemandedProxyAuth);
{
token = await m_tokenProvider.GetTokenAsync(null, tokenSource.Token).ConfigureAwait(false);
ApplyToken(request, token, applyICredentialsToWebProxy: lastResponseDemandedProxyAuth);
}
// The WinHttpHandler will chunk any content that does not have a computed length which is // The WinHttpHandler will chunk any content that does not have a computed length which is
// not what we want. By loading into a buffer up-front we bypass this behavior and there is // not what we want. By loading into a buffer up-front we bypass this behavior and there is

View File

@@ -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,
ulong agentId, int 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,
ulong agentId, int agentId,
TaskAgent agent, TaskAgent agent,
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
@@ -461,8 +461,6 @@ namespace GitHub.DistributedTask.WebApi
long? lastMessageId = null, long? lastMessageId = null,
TaskAgentStatus? status = null, TaskAgentStatus? status = null,
string runnerVersion = null, string runnerVersion = null,
string os = null,
string architecture = null,
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -485,16 +483,6 @@ namespace GitHub.DistributedTask.WebApi
queryParams.Add("runnerVersion", runnerVersion); queryParams.Add("runnerVersion", runnerVersion);
} }
if (os != null)
{
queryParams.Add("os", os);
}
if (architecture != null)
{
queryParams.Add("architecture", architecture);
}
return SendAsync<TaskAgentMessage>( return SendAsync<TaskAgentMessage>(
httpMethod, httpMethod,
locationId, locationId,
@@ -798,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,
ulong agentId, int agentId,
string currentState, string currentState,
string updateTrace, string updateTrace,
object userState = null, object userState = null,

View File

@@ -123,11 +123,8 @@ namespace GitHub.DistributedTask.Logging
var secretSection = string.Empty; var secretSection = string.Empty;
if (value.Contains("&+")) if (value.Contains("&+"))
{ {
if (value.Length > value.IndexOf("&+") + "&+".Length + 1) // +1 to skip the letter that got colored
{ secretSection = value.Substring(value.IndexOf("&+") + "&+".Length + 1);
// +1 to skip the letter that got colored
secretSection = value.Substring(value.IndexOf("&+") + "&+".Length + 1);
}
} }
else else
{ {

View File

@@ -16,7 +16,7 @@ namespace GitHub.DistributedTask.WebApi
} }
public AgentRefreshMessage( public AgentRefreshMessage(
ulong agentId, Int32 agentId,
String targetVersion, String targetVersion,
TimeSpan? timeout = null) TimeSpan? timeout = null)
{ {
@@ -26,7 +26,7 @@ namespace GitHub.DistributedTask.WebApi
} }
[DataMember] [DataMember]
public ulong AgentId public Int32 AgentId
{ {
get; get;
private set; private set;

View File

@@ -5,7 +5,7 @@ namespace GitHub.DistributedTask.WebApi
[DataContract] [DataContract]
public sealed class DiagnosticLogMetadata public sealed class DiagnosticLogMetadata
{ {
public DiagnosticLogMetadata(string agentName, ulong agentId, int poolId, string phaseName, string fileName, string phaseResult) public DiagnosticLogMetadata(string agentName, int 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 ulong AgentId { get; set; } public int AgentId { get; set; }
[DataMember] [DataMember]
public int PoolId { get; set; } public int PoolId { get; set; }

View File

@@ -2516,23 +2516,4 @@ 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)
{
}
}
} }

View File

@@ -2,7 +2,6 @@
namespace GitHub.DistributedTask.WebApi namespace GitHub.DistributedTask.WebApi
{ {
// do NOT add new enum since it will break backward compatibility with GHES
public enum JobTelemetryType public enum JobTelemetryType
{ {
[EnumMember] [EnumMember]

View File

@@ -41,7 +41,7 @@ namespace GitHub.DistributedTask.WebApi
public List<TaskAgent> ToTaskAgents() public List<TaskAgent> ToTaskAgents()
{ {
return Runners.Select(runner => new TaskAgent() { Id = runner.Id, Name = runner.Name }).ToList(); return Runners.Select(runner => new TaskAgent() { Name = runner.Name }).ToList();
} }
} }

View File

@@ -47,7 +47,7 @@ namespace GitHub.DistributedTask.WebApi
} }
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id public Int32 Id
{ {
get; get;
internal set; internal set;

View File

@@ -16,7 +16,7 @@ namespace GitHub.DistributedTask.WebApi
} }
public RunnerRefreshMessage( public RunnerRefreshMessage(
ulong runnerId, Int32 runnerId,
String targetVersion, String targetVersion,
int? timeoutInSeconds = null) int? timeoutInSeconds = null)
{ {
@@ -26,7 +26,7 @@ namespace GitHub.DistributedTask.WebApi
} }
[DataMember] [DataMember]
public ulong RunnerId public Int32 RunnerId
{ {
get; get;
private set; private set;

View File

@@ -37,7 +37,7 @@ namespace GitHub.DistributedTask.WebApi
/// Identifier of the agent. /// Identifier of the agent.
/// </summary> /// </summary>
[DataMember] [DataMember]
public ulong Id public Int32 Id
{ {
get; get;
set; set;

View File

@@ -14,16 +14,14 @@
<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.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.4" />
<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" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" /> <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
<PackageReference Include="Minimatch" Version="2.0.0" /> <PackageReference Include="Minimatch" Version="2.0.0" />
<PackageReference Include="YamlDotNet.Signed" Version="5.3.0" /> <PackageReference Include="YamlDotNet.Signed" Version="5.3.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -59,8 +59,6 @@ namespace GitHub.Actions.RunService.WebApi
public async Task<TaskAgentMessage> GetRunnerMessageAsync( public async Task<TaskAgentMessage> GetRunnerMessageAsync(
string runnerVersion, string runnerVersion,
TaskAgentStatus? status, TaskAgentStatus? status,
string os = null,
string architecture = null,
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
) )
{ {
@@ -77,16 +75,6 @@ namespace GitHub.Actions.RunService.WebApi
queryParams.Add("runnerVersion", runnerVersion); queryParams.Add("runnerVersion", runnerVersion);
} }
if (os != null)
{
queryParams.Add("os", os);
}
if (architecture != null)
{
queryParams.Add("architecture", architecture);
}
var result = await SendAsync<TaskAgentMessage>( var result = await SendAsync<TaskAgentMessage>(
new HttpMethod("GET"), new HttpMethod("GET"),
requestUri: requestUri, requestUri: requestUri,
@@ -98,11 +86,6 @@ 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}");
} }
} }

View File

@@ -258,38 +258,6 @@ namespace GitHub.Services.Results.Client
await StepSummaryUploadCompleteAsync(planId, jobId, stepId, fileSize, cancellationToken); await StepSummaryUploadCompleteAsync(planId, jobId, stepId, fileSize, cancellationToken);
} }
private async Task<HttpResponseMessage> UploadLogFile(string file, bool finalize, bool firstBlock, string sasUrl, string blobStorageType,
CancellationToken cancellationToken)
{
HttpResponseMessage response;
if (firstBlock && finalize)
{
// This is the one and only block, just use a block blob
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
response = await UploadBlockFileAsync(sasUrl, blobStorageType, fileStream, cancellationToken);
}
}
else
{
// This is either not the first block, which means it's using appendBlob; or first block and need to wait for additional blocks. Using append blob in either case.
// Create the Append blob
if (firstBlock)
{
await CreateAppendFileAsync(sasUrl, blobStorageType, cancellationToken);
}
// Upload content
var fileSize = new FileInfo(file).Length;
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
response = await UploadAppendFileAsync(sasUrl, blobStorageType, fileStream, finalize, fileSize, cancellationToken);
}
}
return response;
}
// Handle file upload for step log // Handle file upload for step log
public async Task UploadResultsStepLogAsync(string planId, string jobId, Guid stepId, string file, bool finalize, bool firstBlock, long lineCount, CancellationToken cancellationToken) public async Task UploadResultsStepLogAsync(string planId, string jobId, Guid stepId, string file, bool finalize, bool firstBlock, long lineCount, CancellationToken cancellationToken)
{ {
@@ -300,7 +268,18 @@ namespace GitHub.Services.Results.Client
throw new Exception("Failed to get step log upload url"); throw new Exception("Failed to get step log upload url");
} }
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken); // Create the Append blob
if (firstBlock)
{
await CreateAppendFileAsync(uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken);
}
// Upload content
var fileSize = new FileInfo(file).Length;
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
var response = await UploadAppendFileAsync(uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, fileStream, finalize, fileSize, cancellationToken);
}
// Update metadata // Update metadata
if (finalize) if (finalize)
@@ -320,7 +299,18 @@ namespace GitHub.Services.Results.Client
throw new Exception("Failed to get job log upload url"); throw new Exception("Failed to get job log upload url");
} }
await UploadLogFile(file, finalize, firstBlock, uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken); // Create the Append blob
if (firstBlock)
{
await CreateAppendFileAsync(uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, cancellationToken);
}
// Upload content
var fileSize = new FileInfo(file).Length;
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
var response = await UploadAppendFileAsync(uploadUrlResponse.LogsUrl, uploadUrlResponse.BlobStorageType, fileStream, finalize, fileSize, cancellationToken);
}
// Update metadata // Update metadata
if (finalize) if (finalize)

View File

@@ -120,7 +120,6 @@ namespace GitHub.Runner.Common.Tests
[InlineData("secret&+secret&secret", "secret&+\x0033[96ms\x0033[0mecret&secret", "***\x0033[96ms\x0033[0m***")] [InlineData("secret&+secret&secret", "secret&+\x0033[96ms\x0033[0mecret&secret", "***\x0033[96ms\x0033[0m***")]
[InlineData("secret&+secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&+secret", "***\x0033[96ms\x0033[0m***")] [InlineData("secret&+secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&+secret", "***\x0033[96ms\x0033[0m***")]
[InlineData("secret&+secret&secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&secret&+secret", "***\x0033[96ms\x0033[0m***")] [InlineData("secret&+secret&secret&+secret", "secret&+\x0033[96ms\x0033[0mecret&secret&+secret", "***\x0033[96ms\x0033[0m***")]
[InlineData("secret&secret&+", "secret&secret&+\x0033[96m\x0033[0m", "***\x0033[96m\x0033[0m")]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Common")] [Trait("Category", "Common")]
public void SecretSectionMasking(string secret, string rawOutput, string maskedOutput) public void SecretSectionMasking(string secret, string rawOutput, string maskedOutput)

View File

@@ -110,12 +110,12 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
_runnerServer.Setup(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.IsAny<TaskAgentPoolType>())).Returns(Task.FromResult(expectedPools)); _runnerServer.Setup(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.IsAny<TaskAgentPoolType>())).Returns(Task.FromResult(expectedPools));
var expectedAgents = new List<TaskAgent>(); var expectedAgents = new List<TaskAgent>();
_runnerServer.Setup(x => x.GetAgentsAsync(It.IsAny<string>())).Returns(Task.FromResult(expectedAgents)); _runnerServer.Setup(x => x.GetAgentsAsync(It.IsAny<int>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgents));
_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.GetRunnerByNameAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgents)); _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.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));

View File

@@ -192,8 +192,8 @@ namespace GitHub.Runner.Common.Tests.Listener
_runnerServer _runnerServer
.Setup(x => x.GetAgentMessageAsync( .Setup(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>())) _settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, string os, string architecture, CancellationToken cancellationToken) => .Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken) =>
{ {
await Task.Yield(); await Task.Yield();
return messages.Dequeue(); return messages.Dequeue();
@@ -208,7 +208,7 @@ namespace GitHub.Runner.Common.Tests.Listener
//Assert //Assert
_runnerServer _runnerServer
.Verify(x => x.GetAgentMessageAsync( .Verify(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(arMessages.Length)); _settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(arMessages.Length));
} }
} }
@@ -293,7 +293,7 @@ namespace GitHub.Runner.Common.Tests.Listener
_runnerServer _runnerServer
.Setup(x => x.GetAgentMessageAsync( .Setup(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>())) _settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Throws(new TaskAgentAccessTokenExpiredException("test")); .Throws(new TaskAgentAccessTokenExpiredException("test"));
try try
{ {
@@ -311,7 +311,7 @@ namespace GitHub.Runner.Common.Tests.Listener
//Assert //Assert
_runnerServer _runnerServer
.Verify(x => x.GetAgentMessageAsync( .Verify(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once); _settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_runnerServer _runnerServer
.Verify(x => x.DeleteAgentSessionAsync( .Verify(x => x.DeleteAgentSessionAsync(

View File

@@ -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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int 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, ulong a, string s, string t) => .Callback((int p, int a, string s, string t) =>
{ {
hc.GetTrace().Info(t); hc.GetTrace().Info(t);
}) })

View File

@@ -273,29 +273,5 @@ namespace GitHub.Runner.Common.Tests
Assert.True(string.Equals(hashResult, File.ReadAllText(externalsHashFile).Trim()), $"Hash mismatch for externals. You might need to update `Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}` or check if `hashFiles.ts` ever changed recently."); Assert.True(string.Equals(hashResult, File.ReadAllText(externalsHashFile).Trim()), $"Hash mismatch for externals. You might need to update `Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}` or check if `hashFiles.ts` ever changed recently.");
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public Task RunnerLayoutParts_ContentHashFilesNoNewline()
{
using (TestHostContext hc = new(this))
{
Tracing trace = hc.GetTrace();
var dotnetRuntimeHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/dotnetRuntime/{BuildConstants.RunnerPackage.PackageName}");
var dotnetRuntimeHash = File.ReadAllText(dotnetRuntimeHashFile);
trace.Info($"Current hash: {dotnetRuntimeHash}");
var externalsHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}");
var externalsHash = File.ReadAllText(externalsHashFile);
trace.Info($"Current hash: {externalsHash}");
Assert.False(externalsHash.Any(x => char.IsWhiteSpace(x)), $"Found whitespace in externals hash file.");
Assert.False(dotnetRuntimeHash.Any(x => char.IsWhiteSpace(x)), $"Found whitespace in dotnet runtime hash file.");
return Task.CompletedTask;
}
}
} }
} }

View File

@@ -1,10 +1,21 @@
using System.IO; using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using Xunit; using Xunit;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System.Runtime.CompilerServices; using System.Linq;
namespace GitHub.Runner.Common.Tests namespace GitHub.Runner.Common.Tests
{ {
public enum LineEndingType
{
Native,
Linux = 0x__0A,
Windows = 0x0D0A
}
public static class TestUtil public static class TestUtil
{ {
private const string Src = "src"; private const string Src = "src";
@@ -41,5 +52,24 @@ namespace GitHub.Runner.Common.Tests
Assert.True(Directory.Exists(testDataDir)); Assert.True(Directory.Exists(testDataDir));
return testDataDir; return testDataDir;
} }
public static void WriteContent(string path, string content, LineEndingType lineEnding = LineEndingType.Native)
{
WriteContent(path, Enumerable.Repeat(content, 1), lineEnding);
}
public static void WriteContent(string path, IEnumerable<string> content, LineEndingType lineEnding = LineEndingType.Native)
{
string newline = lineEnding switch
{
LineEndingType.Linux => "\n",
LineEndingType.Windows => "\r\n",
_ => Environment.NewLine,
};
var encoding = new UTF8Encoding(true); // Emit BOM
var contentStr = string.Join(newline, content);
File.WriteAllText(path, contentStr, encoding);
}
} }
} }

View File

@@ -212,210 +212,5 @@ namespace GitHub.Runner.Common.Tests.Util
File.Delete(brokenSymlink); File.Delete(brokenSymlink);
Environment.SetEnvironmentVariable(PathUtil.PathVariable, oldValue); Environment.SetEnvironmentVariable(PathUtil.PathVariable, oldValue);
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void UseWhich2FindGit()
{
using (TestHostContext hc = new(this))
{
//Arrange
Tracing trace = hc.GetTrace();
// Act.
string gitPath = WhichUtil.Which2("git", trace: trace);
trace.Info($"Which(\"git\") returns: {gitPath ?? string.Empty}");
// Assert.
Assert.True(!string.IsNullOrEmpty(gitPath) && File.Exists(gitPath), $"Unable to find Git through: {nameof(WhichUtil.Which)}");
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2ReturnsNullWhenNotFound()
{
using (TestHostContext hc = new(this))
{
//Arrange
Tracing trace = hc.GetTrace();
// Act.
string nosuch = WhichUtil.Which2("no-such-file-cf7e351f", trace: trace);
trace.Info($"result: {nosuch ?? string.Empty}");
// Assert.
Assert.True(string.IsNullOrEmpty(nosuch), "Path should not be resolved");
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2ThrowsWhenRequireAndNotFound()
{
using (TestHostContext hc = new(this))
{
//Arrange
Tracing trace = hc.GetTrace();
// Act.
try
{
WhichUtil.Which2("no-such-file-cf7e351f", require: true, trace: trace);
throw new Exception("which should have thrown");
}
catch (FileNotFoundException ex)
{
Assert.Equal("no-such-file-cf7e351f", ex.FileName);
}
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2HandleFullyQualifiedPath()
{
using (TestHostContext hc = new(this))
{
//Arrange
Tracing trace = hc.GetTrace();
// Act.
var gitPath = WhichUtil.Which2("git", require: true, trace: trace);
var gitPath2 = WhichUtil.Which2(gitPath, require: true, trace: trace);
// Assert.
Assert.Equal(gitPath, gitPath2);
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2HandlesSymlinkToTargetFullPath()
{
// Arrange
using TestHostContext hc = new TestHostContext(this);
Tracing trace = hc.GetTrace();
string oldValue = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
#if OS_WINDOWS
string newValue = oldValue + @$";{Path.GetTempPath()}";
string symlinkName = $"symlink-{Guid.NewGuid()}";
string symlink = Path.GetTempPath() + $"{symlinkName}.exe";
string target = Path.GetTempPath() + $"target-{Guid.NewGuid()}.exe";
#else
string newValue = oldValue + @$":{Path.GetTempPath()}";
string symlinkName = $"symlink-{Guid.NewGuid()}";
string symlink = Path.GetTempPath() + $"{symlinkName}";
string target = Path.GetTempPath() + $"target-{Guid.NewGuid()}";
#endif
Environment.SetEnvironmentVariable(PathUtil.PathVariable, newValue);
using (File.Create(target))
{
File.CreateSymbolicLink(symlink, target);
// Act.
var result = WhichUtil.Which2(symlinkName, require: true, trace: trace);
// Assert
Assert.True(!string.IsNullOrEmpty(result) && File.Exists(result), $"Unable to find symlink through: {nameof(WhichUtil.Which)}");
}
// Cleanup
File.Delete(symlink);
File.Delete(target);
Environment.SetEnvironmentVariable(PathUtil.PathVariable, oldValue);
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2HandlesSymlinkToTargetRelativePath()
{
// Arrange
using TestHostContext hc = new TestHostContext(this);
Tracing trace = hc.GetTrace();
string oldValue = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
#if OS_WINDOWS
string newValue = oldValue + @$";{Path.GetTempPath()}";
string symlinkName = $"symlink-{Guid.NewGuid()}";
string symlink = Path.GetTempPath() + $"{symlinkName}.exe";
string targetName = $"target-{Guid.NewGuid()}.exe";
string target = Path.GetTempPath() + targetName;
#else
string newValue = oldValue + @$":{Path.GetTempPath()}";
string symlinkName = $"symlink-{Guid.NewGuid()}";
string symlink = Path.GetTempPath() + $"{symlinkName}";
string targetName = $"target-{Guid.NewGuid()}";
string target = Path.GetTempPath() + targetName;
#endif
Environment.SetEnvironmentVariable(PathUtil.PathVariable, newValue);
using (File.Create(target))
{
File.CreateSymbolicLink(symlink, targetName);
// Act.
var result = WhichUtil.Which2(symlinkName, require: true, trace: trace);
// Assert
Assert.True(!string.IsNullOrEmpty(result) && File.Exists(result), $"Unable to find {symlinkName} through: {nameof(WhichUtil.Which)}");
}
// Cleanup
File.Delete(symlink);
File.Delete(target);
Environment.SetEnvironmentVariable(PathUtil.PathVariable, oldValue);
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Common")]
public void Which2ThrowsWhenSymlinkBroken()
{
// Arrange
using TestHostContext hc = new TestHostContext(this);
Tracing trace = hc.GetTrace();
string oldValue = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
#if OS_WINDOWS
string newValue = oldValue + @$";{Path.GetTempPath()}";
string brokenSymlinkName = $"broken-symlink-{Guid.NewGuid()}";
string brokenSymlink = Path.GetTempPath() + $"{brokenSymlinkName}.exe";
#else
string newValue = oldValue + @$":{Path.GetTempPath()}";
string brokenSymlinkName = $"broken-symlink-{Guid.NewGuid()}";
string brokenSymlink = Path.GetTempPath() + $"{brokenSymlinkName}";
#endif
string target = "no-such-file-cf7e351f";
Environment.SetEnvironmentVariable(PathUtil.PathVariable, newValue);
File.CreateSymbolicLink(brokenSymlink, target);
// Act.
var exception = Assert.Throws<FileNotFoundException>(() => WhichUtil.Which2(brokenSymlinkName, require: true, trace: trace));
// Assert
Assert.Equal(brokenSymlinkName, exception.FileName);
// Cleanup
File.Delete(brokenSymlink);
Environment.SetEnvironmentVariable(PathUtil.PathVariable, oldValue);
}
} }
} }

View File

@@ -139,7 +139,7 @@ namespace GitHub.Runner.Common.Tests.Worker
message = "::do-something k1=;=%252C=%250D=%250A=]=%253A,::;-%250D-%250A-]-:-,"; message = "::do-something k1=;=%252C=%250D=%250A=]=%253A,::;-%250D-%250A-]-:-,";
test = new ActionCommand("do-something") test = new ActionCommand("do-something")
{ {
Data = ";-%250D-%250A-]-:-,", Data = ";-%0D-%0A-]-:-,",
}; };
test.Properties.Add("k1", ";=%2C=%0D=%0A=]=%3A"); test.Properties.Add("k1", ";=%2C=%0D=%0A=]=%3A");
Assert.True(ActionCommand.TryParseV2(message, commands, out verify)); Assert.True(ActionCommand.TryParseV2(message, commands, out verify));

Some files were not shown because too many files have changed in this diff Show More