Compare commits

..

32 Commits

Author SHA1 Message Date
Tatyana Kostromskaya
0d1eb56adb Small refactoring 2022-06-10 11:25:57 +00:00
Tatyana Kostromskaya
fa0dd79c30 Add common retry func 2022-06-10 11:21:14 +00:00
Ferenc Hammerl
9623a44c2f Allow admins to fail jobs without container (#1895)
* Allow admins to fail jobs without container

* Make method static

* Update src/Runner.Common/Constants.cs

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>

* Update src/Runner.Worker/JobExtension.cs

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>

* Update src/Runner.Worker/JobExtension.cs

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>

* Rename env

* Add test for throwing when no container but required

* Update src/Runner.Worker/JobExtension.cs

* Update src/Test/L0/Worker/JobExtensionL0.cs

* Update src/Runner.Common/Constants.cs

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
2022-06-09 17:17:11 -04:00
Rob Herley
b2e2aa68c8 remove job summary feature flag (#1936) 2022-06-09 15:49:04 -04:00
eric sciple
a9ce6b92c4 Allow redirect get message call to broker (#1935) 2022-06-09 18:36:55 +00:00
eric sciple
a1bf8401d7 Handle message from broker (#1934) 2022-06-09 14:07:44 -04:00
eric sciple
a7152f1370 server wrapper for pulling full job message (#1933) 2022-06-09 17:50:52 +00:00
eric sciple
af285115e7 http client updates for broker flow (#1931) 2022-06-09 12:46:08 -04:00
Ferenc Hammerl
0431b6fd40 Revert bash and shell -e filePath escape (#1932)
It generated invalid arguments for `Process()` when the `bash` command itself was an argument as well, for example:

```
            _proc.StartInfo.FileName = "/usr/bin/docker";
            _proc.StartInfo.Arguments = "exec -i --workdir /__w/container-hook-e2e/container-hook-e2e 47105c66144d8809d9fa2bce9a58ea0564cd14def0ae7952cd6231fba3576db1 sh -e '/__w/_temp/fd086560-cb92-4f3b-a99c-35a6b7b1bbdb.sh'";
```
2022-06-09 14:37:08 +02:00
Nikola Jokic
c3d5449146 Job hook provider now sets shell name for script handler (#1826)
* Job hook provider now sets shell name for script handler

* fixed script handler and job hook provider to work with the name without fail

* returned used import by osx

* fixed order of imports

* added quotes around resolved script path allowing space in script path

* added quotes around bash and sh _defaultArguments

* Changed double quotes to single quotes in sh -e

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>

* Changed double quotes to single quotes in bash

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
2022-06-08 13:54:23 +02:00
Tingluo Huang
9c5300b5b2 Handle HostedRunnerShutdownMessage from service to shutdown hosted runner faster. (#1922) 2022-06-02 13:14:50 -04:00
ruvceskistefan
183b1f387c targetArchitecture removed from launch.json after macos arm64 release (#1908) 2022-05-23 21:46:54 -04:00
Thomas Boop
42ad85741e 292 release (#1906) 2022-05-23 09:53:08 -04:00
Ferenc Hammerl
88ee16fb02 Save original, pre-parsed string from workflow input for the user's custom volume mounts (#1889)
* Save pre parsed string from workflow input for volume mounts that have one

* Use property

* Use named params
2022-05-23 12:07:38 +02:00
Thomas Boop
5cca207314 Port the 291.1 hotfix to main (#1905)
* Revert "Added ability to run Dockerfile.SUFFIX ContainerAction (#1738)"

20b7e86e47

* port release notes
2022-05-22 16:24:18 -04:00
Tingluo Huang
0b73794267 Set timeout on sending live console log. (#1903) 2022-05-20 21:31:21 -04:00
Tingluo Huang
d7694774a4 Update release note, workflow, doc for osx-arm64. (#1904) 2022-05-20 12:28:52 -04:00
Tingluo Huang
0398f57125 Create runner layout for osx-arm64 (Apple M1) platform. (#1618)
* Create runner layout for osx-arm64 (Apple M1) platform.

* bypass m1 macos

* l0
2022-05-20 11:00:54 -04:00
Tingluo Huang
fade0f46e7 Bump dotnet SDK to 6.0.300 (#1900)
* Bump dotnet SDK to 6.0.300
2022-05-17 22:51:32 -04:00
Thomas Boop
02b52e8497 ADR: Runner Job Started/Completed Hooks (#1751)
* RunnerHookADR

* Rename 0000-runner-job-hooks.md to 1751-runner-job-hooks.md

* Update docs/adrs/1751-runner-job-hooks.md

Co-authored-by: Edward Thomson <ethomson@github.com>

* Update docs/adrs/1751-runner-job-hooks.md

Co-authored-by: Edward Thomson <ethomson@github.com>

* update step names

Co-authored-by: Edward Thomson <ethomson@github.com>
2022-05-12 15:18:11 -04:00
Ferenc Hammerl
628f462ab7 Use header of redirect instead of parsing content (#1874)
* Use header of redirect instead of parsing content

* Add exception so we don't hit 404s later

* Fix typo

* Update SelfUpdaterL0.cs
2022-05-09 14:04:18 +02:00
Ferenc Hammerl
7ba4f8587e 2.291.0 Release Notes (#1854)
* Update releaseNote.md

* Update runnerversion

* Update releaseNote.md

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
2022-04-29 12:53:36 +02:00
ruvceskistefan
88f7c56757 Issue 1528: use OS specific path separator (#1617)
* Issue 1528: use OS specific path separator

* Using Path.Combine instead of OS specific c_defaultPathSeparator
2022-04-27 22:16:03 -04:00
Nikola Jokic
20b7e86e47 Added ability to run Dockerfile.SUFFIX ContainerAction (#1738)
* Added ability to run Dockerfile.SUFFIX ContainerAction

* Extracted IsDockerFile method

* reformatted, moved from index to Last()

* extracted IsDockerfile to DockerUtil with L0

* added check for IsDockerfile to account for docker://

* updated test to clearly show path/dockerfile:tag

* fail if Data.Image is not Dockerfile or docker://[image]
2022-04-27 21:23:12 -04:00
Tingluo Huang
bd5f275830 Update runnerversion to match latest release. 2022-04-26 09:54:42 -04:00
Yang Cao
a7aadf5615 Update Actions Summary limit to 1MiB (#1839)
* Update Actions Summary limit to 1MiB

* Making limit a public const so other part of the codebase is aware of the limit too
2022-04-20 17:08:50 -04:00
Tingluo Huang
1c582abc8b Skip running L0 tests in release workflow to prevent package pollution (#1832) 2022-04-19 16:10:47 -04:00
Tingluo Huang
44d4d076fe Capture telemetry when git errors on unsafe repository. (#1823) 2022-04-13 12:48:52 -04:00
Ferenc Hammerl
b6195624ac 2.290.0 Release notes (#1820)
* 2.290.0 rel notes

* Update releaseNote.md
2022-04-12 10:34:15 -04:00
ruvceskistefan
ead3509d5a Added warning in case of invalid combination of command and flags and/or arguments (#1781)
* Added warning in case of invalid combination of command and flags and/or arguments

* Deleting unnecessary comments

* Added separate list for generic options

* Added PAT to the valid remove options

* Added command name to the error message
2022-04-11 09:23:58 -04:00
Nikola Jokic
fee24199cb Added input context to shell in composite run-step (#1767)
* Added input context to shell in composite run-step

* moved from string-shell-context to string-steps-context
2022-04-11 14:50:45 +02:00
Nikola Jokic
c8cb600ac7 Use StepHost when evaluating inputs to actions (#1762)
* composite action github.action_path set based on the StepHost

* in progress on updating github context for input template

* Fixed updating the context data for evaluation

* refactored logic so it is a little cleaner

* removed resolving the action_path in CompositeActionHandler

* removed added DeepClone

* added feature flag and modified the dict in place

* refactored step host to change context data. Added L0

* repaired spaces

* moved logic from step host to execution context, added recursive translation

* removed empty lines

* moved to extension methods

* Update src/Test/L0/Worker/StepHostL0.cs

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
2022-04-11 12:43:24 +00:00
86 changed files with 1048 additions and 777 deletions

View File

@@ -18,7 +18,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ] runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ]
include: include:
- runtime: linux-x64 - runtime: linux-x64
os: ubuntu-latest os: ubuntu-latest
@@ -36,13 +36,17 @@ jobs:
os: macOS-latest os: macOS-latest
devScript: ./dev.sh devScript: ./dev.sh
- runtime: osx-arm64
os: macOS-latest
devScript: ./dev.sh
- runtime: win-x64 - runtime: win-x64
os: windows-2019 os: windows-2019
devScript: ./dev devScript: ./dev
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
# Build runner layout # Build runner layout
- name: Build & Layout Release - name: Build & Layout Release
@@ -78,7 +82,7 @@ jobs:
run: | run: |
${{ matrix.devScript }} test ${{ matrix.devScript }} test
working-directory: src working-directory: src
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64'
# Create runner package tar.gz/zip # Create runner package tar.gz/zip
- name: Package Release - name: Package Release

View File

@@ -23,7 +23,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@@ -11,7 +11,7 @@ jobs:
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main' if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
# Make sure ./releaseVersion match ./src/runnerversion # Make sure ./releaseVersion match ./src/runnerversion
# Query GitHub release ensure version is not used # Query GitHub release ensure version is not used
@@ -51,24 +51,28 @@ jobs:
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }} linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }} win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }} osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }}
linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }} linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }}
linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }} linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }}
linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }} linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }}
win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }} win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }}
osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }} osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }}
osx-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-arm64-sha256 }}
linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }} linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }}
linux-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm64-sha256 }} linux-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm64-sha256 }}
linux-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }} linux-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }}
win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }} win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }}
osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }} osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }}
osx-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-arm64-sha256 }}
linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }} linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }}
linux-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm64-sha256 }} linux-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm64-sha256 }}
linux-arm-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm-sha256 }} linux-arm-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm-sha256 }}
win-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-x64-sha256 }} win-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-x64-sha256 }}
osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }} osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }}
osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }}
strategy: strategy:
matrix: matrix:
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ] runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ]
include: include:
- runtime: linux-x64 - runtime: linux-x64
os: ubuntu-latest os: ubuntu-latest
@@ -85,6 +89,10 @@ jobs:
- runtime: osx-x64 - runtime: osx-x64
os: macOS-latest os: macOS-latest
devScript: ./dev.sh devScript: ./dev.sh
- runtime: osx-arm64
os: macOS-latest
devScript: ./dev.sh
- runtime: win-x64 - runtime: win-x64
os: windows-2019 os: windows-2019
@@ -92,7 +100,7 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
# Build runner layout # Build runner layout
- name: Build & Layout Release - name: Build & Layout Release
@@ -100,13 +108,6 @@ jobs:
${{ matrix.devScript }} layout Release ${{ matrix.runtime }} ${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
working-directory: src working-directory: src
# Run tests
- name: L0
run: |
${{ matrix.devScript }} test
working-directory: src
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
# Create runner package tar.gz/zip # Create runner package tar.gz/zip
- name: Package Release - name: Package Release
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
@@ -217,7 +218,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
# Download runner package tar.gz/zip produced by 'build' job # Download runner package tar.gz/zip produced by 'build' job
- name: Download Artifact - name: Download Artifact
@@ -239,21 +240,25 @@ jobs:
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion) var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime-noexternals}}')
@@ -267,6 +272,7 @@ jobs:
ls -l ls -l
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.linux-arm-sha}} actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.linux-arm-sha}} actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.linux-arm64-sha}} actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.linux-arm64-sha}} actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
@@ -314,6 +320,16 @@ jobs:
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (osx-arm64)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-arm) - name: Upload Release Asset (linux-arm)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -365,6 +381,16 @@ jobs:
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (osx-arm64-noexternals)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-arm-noexternals) - name: Upload Release Asset (linux-arm-noexternals)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -416,6 +442,16 @@ jobs:
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (osx-arm64-noruntime)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-arm-noruntime) - name: Upload Release Asset (linux-arm-noruntime)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -467,6 +503,16 @@ jobs:
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (osx-arm64-noruntime-noexternals)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime_externals/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-arm-noruntime-noexternals) - name: Upload Release Asset (linux-arm-noruntime-noexternals)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -518,6 +564,16 @@ jobs:
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (osx-arm64-trimmedpackages.json)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/osx-arm64-trimmedpackages.json
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-arm-trimmedpackages.json) - name: Upload Release Asset (linux-arm-trimmedpackages.json)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:

15
.vscode/launch.json vendored
View File

@@ -12,8 +12,7 @@
], ],
"cwd": "${workspaceFolder}/src", "cwd": "${workspaceFolder}/src",
"console": "integratedTerminal", "console": "integratedTerminal",
"requireExactSource": false, "requireExactSource": false
"targetArchitecture": "x86_64"
}, },
{ {
"name": "Run", "name": "Run",
@@ -25,8 +24,7 @@
], ],
"cwd": "${workspaceFolder}/src", "cwd": "${workspaceFolder}/src",
"console": "integratedTerminal", "console": "integratedTerminal",
"requireExactSource": false, "requireExactSource": false
"targetArchitecture": "x86_64"
}, },
{ {
"name": "Configure", "name": "Configure",
@@ -39,24 +37,21 @@
], ],
"cwd": "${workspaceFolder}/src", "cwd": "${workspaceFolder}/src",
"console": "integratedTerminal", "console": "integratedTerminal",
"requireExactSource": false, "requireExactSource": false
"targetArchitecture": "x86_64"
}, },
{ {
"name": "Debug Worker", "name": "Debug Worker",
"type": "coreclr", "type": "coreclr",
"request": "attach", "request": "attach",
"processName": "Runner.Worker", "processName": "Runner.Worker",
"requireExactSource": false, "requireExactSource": false
"targetArchitecture": "x86_64"
}, },
{ {
"name": "Attach Debugger", "name": "Attach Debugger",
"type": "coreclr", "type": "coreclr",
"request": "attach", "request": "attach",
"processId": "${command:pickProcess}", "processId": "${command:pickProcess}",
"requireExactSource": false, "requireExactSource": false
"targetArchitecture": "x86_64"
}, },
], ],
} }

View File

@@ -0,0 +1,83 @@
# ADR: Notification Hooks for Runners
## Context
This ADR details the design changes for supporting custom configurable hooks for on various runner events. This has been a long requested user feature [here](https://github.com/actions/runner/issues/1543), [here](https://github.com/actions/runner/issues/699) and [here](https://github.com/actions/runner/issues/1116) for users to have more information on runner observability, and for the ability to run cleanup and teardown jobs.
This feature is mainly intended for self hosted runner administrators.
**What we hope to solve with this feature**
1. A runner admininstrator is able to add custom scripts to cleanup their runner environment at the start or end of a job
2. A runner admininstrator is able to add custom scripts to help setup their runner environment at the beginning of a job, for reasons like [caching](https://github.com/actions/runner/issues/1543#issuecomment-1050346279)
3. A runner administrator is able to grab custom telemetry of jobs running on their self hosted runner
**What we don't think this will solve**
- Policy features that require certain steps run at the beginning or end of all jobs
- This would be better solved to in a central place in settings, rather then decentralized on each runner.
- The Proposed `Notification Hooks for Runners` is limited to self hosted runners, we don't beileve Policy features should be
- Reuse scenarios between jobs are covered by [composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) and [resuable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows)
- Security applications, security should be handled on the policy side on the server, not decentralized on each runner
## Hooks
- We will expose 2 variables that users can set to enable hooks
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
You can set these variables to the **absolute** path of a a `.sh` or `.ps1` file.
We will execute `pwsh` (fallback to `powershell`) or `bash` (fallback to `sh`) as appropriate.
- `.sh` files will execute with the args `-e {pathtofile}`
- `.ps1` files will execute with the args `-command \". '{pathtofile}'\"`
We will **not** set the [standard flags we typically set](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell) for `runs` commands. So, if you want to set `pipefail` on `bash` for example, you will need to do that in your script.
### UI
We want to ensure the experience for users invoking workflows is good, if hooks take too long, you may feel your job is delayed or broken. So, much like `Set Up Job`, we will generate two new steps automatically in your job, one for each configured hook:
- `Set up runner`
- `Complete runner`
These steps will contain all of the output from invoking your hook, so you will have visibility into the runtime. We will also provide information on the path to the hook, and what shell we are invoking it as, much like we do for `run: ` steps.
### Contexts
When running your hooks, some context on your job may be helpful.
- The scripts will have access to the standard [default environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables)
- Some of these variables are step specific like `GITHUB_ACTION`, in which case they will not be set
- You can pull the full webhook event payload from `GITHUB_EVENT_PATH`
### Commands
Should we expose [Commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions) and [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files)
**Yes**. Imagine a scenario where a runner administrator is deprecating a runner pool, and they need to [warn users](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message) to swap to a different pool, we should support them in doing this. However, there are some limitations:
- [save-state](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions) will **not** be supported, these are not traditional steps with pre and post actions
- [set-output](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions) will **not** be supported, there is no `id` as this is not a traditional step
### Environment Files
We will also enable [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files) to support setup scenarios for the runner environment.
While a self hosted runner admin can [set env variables](https://docs.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners#using-a-env-file-to-set-the-proxy-configuration), these apply to all jobs. By enabling the ability to `add a path` and `set an env` we give runner admins the ability to do this dynamically based on the [workflows environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables) to empower setup scenarios.
### Exit codes
These are **synchronous** hooks, so they will block job execution while they are being run. Exit code 0 will indicate a successful run of the hook and we will proceed with the job, any other exit code will fail the job with an appropriate annotation.
- There will be no support for `continue-on-error`
## Key Decisions
- We will expose 2 variables that users can set to enable hooks
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
- Users can set these variables to the path of a `.sh` or `.ps1` file, which we will execute when Jobs are started or completed.
- Output from these will be added to a new step at the start/end of a job named `Set up runner` or `Complete runner`.
- These steps will only be generated on runs with these hooks
- These hooks `always()` execute if the env variable is set
- These files will execute as the Runner user, outside of any container specification on the job
- These are **synchronous** hooks
- Runner admins can execute a background process for async hooks if they want
- We will fail the job and halt execution on any exit code that is not 0. The Runner admin is responsible for returning the correct exit code and ensuring resilency.
- This includes that the runner user needs access to the file in the env and the file must exist
- There will be no `continue-on-error` type option on launch
- There will be no `timeout` option on launch
## Consequences
- Runner admins have the ability to tie into the runner job execution to publish their own telemetry or perform their own cleanup or setup
- New steps will be added to the UI showcasing the output of these hooks

View File

@@ -5,12 +5,6 @@
## Supported Versions ## Supported Versions
- macOS High Sierra (10.13) and later versions - macOS High Sierra (10.13) and later versions
- x64 and arm64 (Apple Silicon)
## Apple Silicon M1
The runner is currently not supported on devices with an Apple M1 chip.
We are waiting for official .NET support. You can read more here about the [current state of support here](https://github.com/orgs/dotnet/projects/18#card-56812463).
Current .NET project board about M1 support:
https://github.com/orgs/dotnet/projects/18#card-56812463
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30) ## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)

View File

@@ -1,8 +1,11 @@
## Features ## Features
- Added a pre-release package for the `macOS-arm64` architecture
- Note that this packages is pre-release status and may not work with all existing actions
## Bugs ## Bugs
- Fixed an issue where websockets failed to successfully close when posting log lines (#1790) - Fixed an issue where live console logs would fail to close (#1903)
## Misc
## Windows x64 ## Windows x64
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
@@ -18,7 +21,7 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD") [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
``` ```
## OSX ## OSX x64
``` bash ``` bash
# Create a folder # Create a folder
@@ -29,6 +32,17 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
``` ```
## [Pre-release] OSX arm64 (Apple silicon)
``` bash
# Create a folder
mkdir actions-runner && cd actions-runner
# Download the latest runner package
curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
# Extract the installer
tar xzf ./actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
```
## Linux x64 ## Linux x64
``` bash ``` bash
@@ -71,24 +85,28 @@ The SHA-256 checksums for the packages included in this build are shown below:
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 --> - actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
- actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 --> - actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 -->
- actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 -->
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 --> - actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
- actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 --> - actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 -->
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm --> - actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
- actions-runner-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals --> - actions-runner-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-x64_noexternals --> - actions-runner-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-x64_noexternals -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noexternals --><OSX_ARM64_SHA_NOEXTERNALS><!-- END SHA osx-arm64_noexternals -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noexternals --><LINUX_X64_SHA_NOEXTERNALS><!-- END SHA linux-x64_noexternals --> - actions-runner-linux-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noexternals --><LINUX_X64_SHA_NOEXTERNALS><!-- END SHA linux-x64_noexternals -->
- actions-runner-linux-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm64_noexternals --><LINUX_ARM64_SHA_NOEXTERNALS><!-- END SHA linux-arm64_noexternals --> - actions-runner-linux-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm64_noexternals --><LINUX_ARM64_SHA_NOEXTERNALS><!-- END SHA linux-arm64_noexternals -->
- actions-runner-linux-arm-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noexternals --><LINUX_ARM_SHA_NOEXTERNALS><!-- END SHA linux-arm_noexternals --> - actions-runner-linux-arm-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noexternals --><LINUX_ARM_SHA_NOEXTERNALS><!-- END SHA linux-arm_noexternals -->
- actions-runner-win-x64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-x64_noruntime --><WIN_X64_SHA_NORUNTIME><!-- END SHA win-x64_noruntime --> - actions-runner-win-x64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-x64_noruntime --><WIN_X64_SHA_NORUNTIME><!-- END SHA win-x64_noruntime -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-x64_noruntime --> - actions-runner-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-x64_noruntime -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-arm64_noruntime --><OSX_ARM64_SHA_NORUNTIME><!-- END SHA osx-arm64_noruntime -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-x64_noruntime --><LINUX_X64_SHA_NORUNTIME><!-- END SHA linux-x64_noruntime --> - actions-runner-linux-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-x64_noruntime --><LINUX_X64_SHA_NORUNTIME><!-- END SHA linux-x64_noruntime -->
- actions-runner-linux-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm64_noruntime --><LINUX_ARM64_SHA_NORUNTIME><!-- END SHA linux-arm64_noruntime --> - actions-runner-linux-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm64_noruntime --><LINUX_ARM64_SHA_NORUNTIME><!-- END SHA linux-arm64_noruntime -->
- actions-runner-linux-arm-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm_noruntime --><LINUX_ARM_SHA_NORUNTIME><!-- END SHA linux-arm_noruntime --> - actions-runner-linux-arm-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm_noruntime --><LINUX_ARM_SHA_NORUNTIME><!-- END SHA linux-arm_noruntime -->
- actions-runner-win-x64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-x64_noruntime_noexternals --><WIN_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-x64_noruntime_noexternals --> - actions-runner-win-x64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-x64_noruntime_noexternals --><WIN_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-x64_noruntime_noexternals -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noruntime_noexternals --><OSX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-x64_noruntime_noexternals --> - actions-runner-osx-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noruntime_noexternals --><OSX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-x64_noruntime_noexternals -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noruntime_noexternals --><OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-arm64_noruntime_noexternals -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noruntime_noexternals --><LINUX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-x64_noruntime_noexternals --> - actions-runner-linux-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noruntime_noexternals --><LINUX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-x64_noruntime_noexternals -->
- actions-runner-linux-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-arm64_noruntime_noexternals --><LINUX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-arm64_noruntime_noexternals --> - actions-runner-linux-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-arm64_noruntime_noexternals --><LINUX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-arm64_noruntime_noexternals -->
- actions-runner-linux-arm-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noruntime_noexternals --><LINUX_ARM_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-arm_noruntime_noexternals --> - actions-runner-linux-arm-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noruntime_noexternals --><LINUX_ARM_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-arm_noruntime_noexternals -->

View File

@@ -25,9 +25,12 @@
<DefineConstants>$(DefineConstants);X86</DefineConstants> <DefineConstants>$(DefineConstants);X86</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'"> <PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
<DefineConstants>$(DefineConstants);X64</DefineConstants> <DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-arm64'">
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')"> <PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
<DefineConstants>$(DefineConstants);X64</DefineConstants> <DefineConstants>$(DefineConstants);X64</DefineConstants>
@@ -47,11 +50,6 @@
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants> <DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
</PropertyGroup> </PropertyGroup>
<!-- Set USE_BROKER vars -->
<PropertyGroup Condition="'$(USE_BROKER)' == 'true'">
<DefineConstants>$(DefineConstants);USE_BROKER</DefineConstants>
</PropertyGroup>
<!-- Set Treat tarnings as errors --> <!-- Set Treat tarnings as errors -->
<PropertyGroup> <PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>

View File

@@ -1 +1 @@
de62d296708908cfd1236e58869aebbc2bae8a8c3d629276968542626c508e37 1d709d93e5d3c6c6c656a61aa6c1781050224788a05b0e6ecc4c3c0408bdf89c

View File

@@ -1 +1 @@
44fcd0422dd98ed17d2c8e9057ff2260c50165f20674236a4ae7d2645a07df25 b92a47cfeaad02255b1f7a377060651b73ae5e5db22a188dbbcb4183ab03a03d

View File

@@ -1 +1 @@
e57652cf322ee16ce3af4f9e58f80858746b9e1e60279e991a3b3d9a6baf8d79 68a9a8ef0843a8bb74241894f6f63fd76241a82295c5337d3cc7a940a314c78e

View File

@@ -0,0 +1 @@
02c7126ff4d63ee2a0ae390c81434c125630522aadf35903bbeebb1a99d8af99

View File

@@ -1 +1 @@
bdd247b2ff3f51095524412e2ac588e7a87af805e114d6caf2368366ee7be1ea c9d5a542f8d765168855a89e83ae0a8970d00869041c4f9a766651c04c72b212

View File

@@ -1 +1 @@
d23a0cb9f20c0aa1cddb7a39567cd097020cdeb06a1e952940601d1a405c53b8 d94f2fbaf210297162bc9f3add819d73682c3aa6899e321c3872412b924d5504

View File

@@ -0,0 +1 @@
cc4708962a80325de0baa5ae8484e0cb9ae976ac6a4178c1c0d448b8c52bd7f7

View File

@@ -140,6 +140,11 @@ if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
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
fi fi
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
# 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
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 "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir

View File

@@ -3,6 +3,7 @@ api-ms-win-core-console-l1-2-0.dll
api-ms-win-core-datetime-l1-1-0.dll api-ms-win-core-datetime-l1-1-0.dll
api-ms-win-core-debug-l1-1-0.dll api-ms-win-core-debug-l1-1-0.dll
api-ms-win-core-errorhandling-l1-1-0.dll api-ms-win-core-errorhandling-l1-1-0.dll
api-ms-win-core-fibers-l1-1-0.dll
api-ms-win-core-file-l1-1-0.dll api-ms-win-core-file-l1-1-0.dll
api-ms-win-core-file-l1-2-0.dll api-ms-win-core-file-l1-2-0.dll
api-ms-win-core-file-l2-1-0.dll api-ms-win-core-file-l2-1-0.dll
@@ -70,7 +71,7 @@ Microsoft.VisualBasic.dll
Microsoft.Win32.Primitives.dll Microsoft.Win32.Primitives.dll
Microsoft.Win32.Registry.dll Microsoft.Win32.Registry.dll
mscordaccore.dll mscordaccore.dll
mscordaccore_amd64_amd64_6.0.21.52210.dll mscordaccore_amd64_amd64_6.0.522.21309.dll
mscordbi.dll mscordbi.dll
mscorlib.dll mscorlib.dll
mscorrc.debug.dll mscorrc.debug.dll

View File

@@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using GitHub.DistributedTask.WebApi;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Runner.Common.Util;
using GitHub.Services.WebApi;
using GitHub.Services.Common;
using GitHub.Runner.Sdk;
using System.Net;
using System.Net.Http;
namespace GitHub.Runner.Common
{
[ServiceLocator(Default = typeof(BrokerServer))]
public interface IBrokerServer : IRunnerService
{
Task ConnectAsync(Uri serverUrl, CancellationToken cancellationToken);
Task<string> GetMessageAsync(TaskAgentSession session, RunnerSettings settings, long? lastMessageId, CancellationToken cancellationToken);
}
public sealed class BrokerServer : RunnerService, IBrokerServer
{
private HttpClient _httpClient;
public async Task ConnectAsync(Uri serverUrl, CancellationToken cancellationToken)
{
_httpClient = new HttpClient();
_httpClient.BaseAddress = serverUrl;
_httpClient.Timeout = TimeSpan.FromSeconds(100);
await _httpClient.GetAsync("health", cancellationToken);
}
public async Task<string> GetMessageAsync(TaskAgentSession session, RunnerSettings settings, long? lastMessageId, CancellationToken cancellationToken)
{
var response = await _httpClient.GetAsync($"message?tenant=org:github&root_tenant=org:github&group_id={settings.PoolId}&group_name={settings.PoolName}&runner_id={settings.AgentId}&runner_name={settings.AgentName}&labels=self-hosted,linux", cancellationToken);
if (!response.IsSuccessStatusCode)
{
var content = default(string);
try
{
content = await response.Content.ReadAsStringAsync();
}
catch
{
}
var error = $"HTTP {(int)response.StatusCode} {Enum.GetName(typeof(HttpStatusCode), response.StatusCode)}";
if (!string.IsNullOrEmpty(content))
{
error = $"{error}: {content}";
}
throw new Exception(error);
}
return await response.Content.ReadAsStringAsync();
}
}
}

View File

@@ -86,7 +86,7 @@ namespace GitHub.Runner.Common
public static class CommandLine public static class CommandLine
{ {
//if you are adding a new arg, please make sure you update the //if you are adding a new arg, please make sure you update the
//validArgs array as well present in the CommandSettings.cs //validOptions dictionary as well present in the CommandSettings.cs
public static class Args public static class Args
{ {
public static readonly string Auth = "auth"; public static readonly string Auth = "auth";
@@ -121,7 +121,7 @@ namespace GitHub.Runner.Common
} }
//if you are adding a new flag, please make sure you update the //if you are adding a new flag, please make sure you update the
//validFlags array as well present in the CommandSettings.cs //validOptions dictionary as well present in the CommandSettings.cs
public static class Flags public static class Flags
{ {
public static readonly string Check = "check"; public static readonly string Check = "check";
@@ -150,6 +150,7 @@ namespace GitHub.Runner.Common
{ {
public static readonly string DiskSpaceWarning = "runner.diskspace.warning"; public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action"; public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
} }
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry"; public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
@@ -226,6 +227,7 @@ namespace GitHub.Runner.Common
// //
public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS"; public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS";
public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS"; public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS";
public static readonly string RequireJobContainer = "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER";
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG"; public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG"; public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION"; public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";

View File

@@ -1,5 +1,4 @@
using GitHub.DistributedTask.WebApi; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -9,6 +8,7 @@ using System.Net.WebSockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
@@ -140,8 +140,8 @@ namespace GitHub.Runner.Common
public void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint) public void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint)
{ {
this._serviceEndpoint = serviceEndpoint; this._serviceEndpoint = serviceEndpoint;
InitializeWebsocketClient(TimeSpan.Zero); InitializeWebsocketClient(TimeSpan.Zero);
} }
public ValueTask DisposeAsync() public ValueTask DisposeAsync()
@@ -163,9 +163,9 @@ namespace GitHub.Runner.Common
private void InitializeWebsocketClient(TimeSpan delay) private void InitializeWebsocketClient(TimeSpan delay)
{ {
if (_serviceEndpoint.Authorization != null && if (_serviceEndpoint.Authorization != null &&
_serviceEndpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.AccessToken, out var accessToken) && _serviceEndpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.AccessToken, out var accessToken) &&
!string.IsNullOrEmpty(accessToken)) !string.IsNullOrEmpty(accessToken))
{ {
if (_serviceEndpoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl) && !string.IsNullOrEmpty(feedStreamUrl)) if (_serviceEndpoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl) && !string.IsNullOrEmpty(feedStreamUrl))
{ {
@@ -177,7 +177,7 @@ namespace GitHub.Runner.Common
var userAgentValues = new List<ProductInfoHeaderValue>(); var userAgentValues = new List<ProductInfoHeaderValue>();
userAgentValues.AddRange(UserAgentUtility.GetDefaultRestUserAgent()); userAgentValues.AddRange(UserAgentUtility.GetDefaultRestUserAgent());
userAgentValues.AddRange(HostContext.UserAgents); userAgentValues.AddRange(HostContext.UserAgents);
this._websocketClient.Options.SetRequestHeader("User-Agent", string.Join(" ", userAgentValues.Select(x=>x.ToString()))); this._websocketClient.Options.SetRequestHeader("User-Agent", string.Join(" ", userAgentValues.Select(x => x.ToString())));
this._websocketConnectTask = ConnectWebSocketClient(feedStreamUrl, delay); this._websocketConnectTask = ConnectWebSocketClient(feedStreamUrl, delay);
} }
@@ -201,7 +201,7 @@ namespace GitHub.Runner.Common
await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), default(CancellationToken)); await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), default(CancellationToken));
Trace.Info($"Successfully started websocket client."); Trace.Info($"Successfully started websocket client.");
} }
catch(Exception ex) catch (Exception ex)
{ {
Trace.Info("Exception caught during websocket client connect, fallback of HTTP would be used now instead of websocket."); Trace.Info("Exception caught during websocket client connect, fallback of HTTP would be used now instead of websocket.");
Trace.Error(ex); Trace.Error(ex);
@@ -231,7 +231,7 @@ namespace GitHub.Runner.Common
// ...in other words, if websocket client is null, we will skip sending to websocket and just use rest api calls to send data // ...in other words, if websocket client is null, we will skip sending to websocket and just use rest api calls to send data
if (_websocketClient != null) if (_websocketClient != null)
{ {
var linesWrapper = startLine.HasValue? new TimelineRecordFeedLinesWrapper(stepId, lines, startLine.Value): new TimelineRecordFeedLinesWrapper(stepId, lines); var linesWrapper = startLine.HasValue ? new TimelineRecordFeedLinesWrapper(stepId, lines, startLine.Value) : new TimelineRecordFeedLinesWrapper(stepId, lines);
var jsonData = StringUtil.ConvertToJson(linesWrapper); var jsonData = StringUtil.ConvertToJson(linesWrapper);
try try
{ {
@@ -242,7 +242,7 @@ namespace GitHub.Runner.Common
{ {
var lastChunk = i + (1 * 1024) >= jsonDataBytes.Length; var lastChunk = i + (1 * 1024) >= jsonDataBytes.Length;
var chunk = new ArraySegment<byte>(jsonDataBytes, i, Math.Min(1 * 1024, jsonDataBytes.Length - i)); var chunk = new ArraySegment<byte>(jsonDataBytes, i, Math.Min(1 * 1024, jsonDataBytes.Length - i));
await _websocketClient.SendAsync(chunk, WebSocketMessageType.Text, endOfMessage:lastChunk, cancellationToken); await _websocketClient.SendAsync(chunk, WebSocketMessageType.Text, endOfMessage: lastChunk, cancellationToken);
} }
pushedLinesViaWebsocket = true; pushedLinesViaWebsocket = true;
@@ -274,7 +274,7 @@ namespace GitHub.Runner.Common
} }
} }
if (!pushedLinesViaWebsocket) if (!pushedLinesViaWebsocket && !cancellationToken.IsCancellationRequested)
{ {
if (startLine.HasValue) if (startLine.HasValue)
{ {

View File

@@ -299,7 +299,11 @@ namespace GitHub.Runner.Common
{ {
try try
{ {
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, default(CancellationToken)); // Give at most 60s for each request.
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
{
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
}
if (_firstConsoleOutputs) if (_firstConsoleOutputs)
{ {

View File

@@ -1,14 +1,14 @@
using GitHub.DistributedTask.WebApi; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common.Util;
using GitHub.Services.WebApi;
using GitHub.Services.Common;
using GitHub.Runner.Sdk;
using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk;
using GitHub.Services.Common;
using GitHub.Services.WebApi;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -17,7 +17,7 @@ namespace GitHub.Runner.Common
{ {
Task ConnectAsync(Uri serverUrl, VssCredentials credentials); Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
Task<AgentJobRequestMessage> GetJobMessageAsync(Guid scopeId, Guid hostId, string planType, string planGroup, Guid planId, IList<InstanceRef> instanceRefsJson); Task<AgentJobRequestMessage> GetJobMessageAsync(string id);
} }
public sealed class RunServer : RunnerService, IRunServer public sealed class RunServer : RunnerService, IRunServer
@@ -28,7 +28,6 @@ namespace GitHub.Runner.Common
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials) public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
{ {
// System.Console.WriteLine("RunServer.ConnectAsync");
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100)); _connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>(); _taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
_hasConnection = true; _hasConnection = true;
@@ -36,7 +35,6 @@ namespace GitHub.Runner.Common
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout) private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
{ {
// System.Console.WriteLine("EstablishVssConnection");
Trace.Info($"EstablishVssConnection"); Trace.Info($"EstablishVssConnection");
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout."); Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
int attemptCount = 5; int attemptCount = 5;
@@ -69,52 +67,10 @@ namespace GitHub.Runner.Common
} }
} }
public Task<AgentJobRequestMessage> GetJobMessageAsync( public Task<AgentJobRequestMessage> GetJobMessageAsync(string id)
Guid scopeId,
Guid hostId,
string planType,
string planGroup,
Guid planId,
IList<InstanceRef> instanceRefsJson)
{ {
// System.Console.WriteLine("RunServer.GetMessageAsync");
CheckConnection(); CheckConnection();
return _taskAgentClient.GetJobMessageAsync(scopeId, hostId, planType, planGroup, planId, StringUtil.ConvertToJson(instanceRefsJson, Newtonsoft.Json.Formatting.None)); return _taskAgentClient.GetJobMessageAsync(id);
} }
} }
// todo: move to SDK?
[DataContract]
public sealed class MessageRef
{
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "token")]
public string Token { get; set; }
[DataMember(Name = "scopeId")]
public Guid ScopeId { get; set; }
[DataMember(Name = "hostId")]
public Guid HostId { get; set; }
[DataMember(Name = "planType")]
public string PlanType { get; set; }
[DataMember(Name = "planGroup")]
public string PlanGroup { get; set; }
[DataMember(Name = "planId")]
public Guid PlanId { get; set; }
[DataMember(Name = "instanceRefs")]
public InstanceRef[] InstanceRefs { get; set; }
[DataMember(Name = "labels")]
public string[] Labels { get; set; }
}
[DataContract]
public sealed class InstanceRef
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "instanceType")]
public string InstanceType { get; set; }
[DataMember(Name = "attempt")]
public int Attempt { get; set; }
}
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -44,7 +44,7 @@ namespace GitHub.Runner.Common
// job request // job request
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken); Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, CancellationToken cancellationToken); Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, CancellationToken cancellationToken);
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, Guid targetHostId, CancellationToken cancellationToken); Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
// agent package // agent package
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken); Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken);
@@ -68,23 +68,11 @@ namespace GitHub.Runner.Common
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials) public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
{ {
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create message connection");
var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
await Task.WhenAll(createMessageConnection);
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create generic connection");
var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100)); var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
await Task.WhenAll(createGenericConnection); var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create request connection");
var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60)); var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
await Task.WhenAll(createRequestConnection);
// var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100)); await Task.WhenAll(createGenericConnection, createMessageConnection, createRequestConnection);
// var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
// var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
// await Task.WhenAll(createGenericConnection, createMessageConnection, createRequestConnection);
_genericConnection = await createGenericConnection; _genericConnection = await createGenericConnection;
_messageConnection = await createMessageConnection; _messageConnection = await createMessageConnection;
@@ -194,8 +182,6 @@ namespace GitHub.Runner.Common
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout) private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
{ {
// System.Console.WriteLine("EstablishVssConnection");
Trace.Info($"EstablishVssConnection");
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout."); Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
int attemptCount = 5; int attemptCount = 5;
while (attemptCount-- > 0) while (attemptCount-- > 0)
@@ -252,48 +238,41 @@ namespace GitHub.Runner.Common
public Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation) public Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation)
{ {
// System.Console.WriteLine("RunnerServer.GetAgentPoolsAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetAgentPoolsAsync(agentPoolName, poolType: poolType); return _genericTaskAgentClient.GetAgentPoolsAsync(agentPoolName, poolType: poolType);
} }
public Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent) public Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent)
{ {
// System.Console.WriteLine("RunnerServer.AddAgentAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.AddAgentAsync(agentPoolId, agent); return _genericTaskAgentClient.AddAgentAsync(agentPoolId, agent);
} }
public Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null) public Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null)
{ {
// System.Console.WriteLine("RunnerServer.GetAgentsAsync 1");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false); return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
} }
public Task<List<TaskAgent>> GetAgentsAsync(string agentName) public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
{ {
// System.Console.WriteLine("RunnerServer.GetAgentsAsync 2");
return GetAgentsAsync(0, agentName); // search in all all agentPools return GetAgentsAsync(0, agentName); // search in all all agentPools
} }
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent) public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
{ {
// System.Console.WriteLine("RunnerServer.ReplaceAgentAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent); return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
} }
public Task DeleteAgentAsync(int agentPoolId, int agentId) public Task DeleteAgentAsync(int agentPoolId, int agentId)
{ {
// System.Console.WriteLine("RunnerServer.DeleteAgentAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId); return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
} }
public Task DeleteAgentAsync(int agentId) public Task DeleteAgentAsync(int agentId)
{ {
// System.Console.WriteLine("RunnerServer.DeleteAgentAsync");
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
} }
@@ -303,28 +282,24 @@ namespace GitHub.Runner.Common
public Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken) public Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.CreateAgentSessionAsync");
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.CreateAgentSessionAsync(poolId, session, cancellationToken: cancellationToken); return _messageTaskAgentClient.CreateAgentSessionAsync(poolId, session, cancellationToken: cancellationToken);
} }
public Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken) public Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.DeleteAgentMessageAsync");
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.DeleteMessageAsync(poolId, messageId, sessionId, cancellationToken: cancellationToken); return _messageTaskAgentClient.DeleteMessageAsync(poolId, messageId, sessionId, cancellationToken: cancellationToken);
} }
public Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken) public Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.DeleteAgentSessionAsync");
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken); return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
} }
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.GetAgentMessageAsync");
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken); return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
} }
@@ -335,21 +310,18 @@ namespace GitHub.Runner.Common
public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId = null, CancellationToken cancellationToken = default(CancellationToken)) public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("RunnerServer.RenewAgentRequestAsync");
CheckConnection(RunnerConnectionType.JobRequest); CheckConnection(RunnerConnectionType.JobRequest);
return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId: orchestrationId, cancellationToken: cancellationToken); return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId: orchestrationId, cancellationToken: cancellationToken);
} }
public Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, Guid targetHostId, CancellationToken cancellationToken = default(CancellationToken)) public Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("RunnerServer.FinishAgentRequestAsync");
CheckConnection(RunnerConnectionType.JobRequest); CheckConnection(RunnerConnectionType.JobRequest);
return _requestTaskAgentClient.FinishAgentRequestAsync(poolId, requestId, lockToken, finishTime, result, targetHostId, cancellationToken: cancellationToken); return _requestTaskAgentClient.FinishAgentRequestAsync(poolId, requestId, lockToken, finishTime, result, cancellationToken: cancellationToken);
} }
public Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken = default(CancellationToken)) public Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("RunnerServer.GetAgentRequestAsync");
CheckConnection(RunnerConnectionType.JobRequest); CheckConnection(RunnerConnectionType.JobRequest);
return _requestTaskAgentClient.GetAgentRequestAsync(poolId, requestId, cancellationToken: cancellationToken); return _requestTaskAgentClient.GetAgentRequestAsync(poolId, requestId, cancellationToken: cancellationToken);
} }
@@ -359,21 +331,18 @@ namespace GitHub.Runner.Common
//----------------------------------------------------------------- //-----------------------------------------------------------------
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken) public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.GetPackagesAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken); return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken);
} }
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken) public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("RunnerServer.GetPackageAsync");
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken); return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
} }
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace) public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
{ {
// System.Console.WriteLine("RunnerServer.UpdateAgentUpdateStateAsync");
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[] {"node12", "node16"});
#if OS_OSX && 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 forcedNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion); var forcedNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);

View File

@@ -17,43 +17,57 @@ namespace GitHub.Runner.Listener
private readonly IPromptManager _promptManager; private readonly IPromptManager _promptManager;
private readonly Tracing _trace; private readonly Tracing _trace;
private readonly string[] validCommands = // Valid flags for all commands
private readonly string[] genericOptions =
{ {
Constants.Runner.CommandLine.Commands.Configure,
Constants.Runner.CommandLine.Commands.Remove,
Constants.Runner.CommandLine.Commands.Run,
Constants.Runner.CommandLine.Commands.Warmup,
};
private readonly string[] validFlags =
{
Constants.Runner.CommandLine.Flags.Check,
Constants.Runner.CommandLine.Flags.Commit,
Constants.Runner.CommandLine.Flags.DisableUpdate,
Constants.Runner.CommandLine.Flags.Ephemeral,
Constants.Runner.CommandLine.Flags.Help, Constants.Runner.CommandLine.Flags.Help,
Constants.Runner.CommandLine.Flags.Once, Constants.Runner.CommandLine.Flags.Version,
Constants.Runner.CommandLine.Flags.Replace, Constants.Runner.CommandLine.Flags.Commit,
Constants.Runner.CommandLine.Flags.RunAsService, Constants.Runner.CommandLine.Flags.Check
Constants.Runner.CommandLine.Flags.Unattended,
Constants.Runner.CommandLine.Flags.Version
}; };
private readonly string[] validArgs = // Valid flags and args for specific command - key: command, value: array of valid flags and args
private readonly Dictionary<string, string[]> validOptions = new Dictionary<string, string[]>
{ {
Constants.Runner.CommandLine.Args.Auth, // Valid configure flags and args
Constants.Runner.CommandLine.Args.Labels, [Constants.Runner.CommandLine.Commands.Configure] =
Constants.Runner.CommandLine.Args.MonitorSocketAddress, new string[]
Constants.Runner.CommandLine.Args.Name, {
Constants.Runner.CommandLine.Args.PAT, Constants.Runner.CommandLine.Flags.DisableUpdate,
Constants.Runner.CommandLine.Args.RunnerGroup, Constants.Runner.CommandLine.Flags.Ephemeral,
Constants.Runner.CommandLine.Args.StartupType, Constants.Runner.CommandLine.Flags.Replace,
Constants.Runner.CommandLine.Args.Token, Constants.Runner.CommandLine.Flags.RunAsService,
Constants.Runner.CommandLine.Args.Url, Constants.Runner.CommandLine.Flags.Unattended,
Constants.Runner.CommandLine.Args.UserName, Constants.Runner.CommandLine.Args.Auth,
Constants.Runner.CommandLine.Args.WindowsLogonAccount, Constants.Runner.CommandLine.Args.Labels,
Constants.Runner.CommandLine.Args.WindowsLogonPassword, Constants.Runner.CommandLine.Args.MonitorSocketAddress,
Constants.Runner.CommandLine.Args.Work Constants.Runner.CommandLine.Args.Name,
Constants.Runner.CommandLine.Args.PAT,
Constants.Runner.CommandLine.Args.RunnerGroup,
Constants.Runner.CommandLine.Args.Token,
Constants.Runner.CommandLine.Args.Url,
Constants.Runner.CommandLine.Args.UserName,
Constants.Runner.CommandLine.Args.WindowsLogonAccount,
Constants.Runner.CommandLine.Args.WindowsLogonPassword,
Constants.Runner.CommandLine.Args.Work
},
// Valid remove flags and args
[Constants.Runner.CommandLine.Commands.Remove] =
new string[]
{
Constants.Runner.CommandLine.Args.Token,
Constants.Runner.CommandLine.Args.PAT
},
// Valid run flags and args
[Constants.Runner.CommandLine.Commands.Run] =
new string[]
{
Constants.Runner.CommandLine.Flags.Once,
Constants.Runner.CommandLine.Args.StartupType
},
// valid warmup flags and args
[Constants.Runner.CommandLine.Commands.Warmup] =
new string[] { }
}; };
// Commands. // Commands.
@@ -126,17 +140,48 @@ namespace GitHub.Runner.Listener
List<string> unknowns = new List<string>(); List<string> unknowns = new List<string>();
// detect unknown commands // detect unknown commands
unknowns.AddRange(_parser.Commands.Where(x => !validCommands.Contains(x, StringComparer.OrdinalIgnoreCase))); unknowns.AddRange(_parser.Commands.Where(x => !validOptions.Keys.Contains(x, StringComparer.OrdinalIgnoreCase)));
// detect unknown flags if (unknowns.Count == 0)
unknowns.AddRange(_parser.Flags.Where(x => !validFlags.Contains(x, StringComparer.OrdinalIgnoreCase))); {
// detect unknown flags and args for valid commands
// detect unknown args foreach (var command in _parser.Commands)
unknowns.AddRange(_parser.Args.Keys.Where(x => !validArgs.Contains(x, StringComparer.OrdinalIgnoreCase))); {
if (validOptions.TryGetValue(command, out string[] options))
{
unknowns.AddRange(_parser.Flags.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase) && !genericOptions.Contains(x, StringComparer.OrdinalIgnoreCase)));
unknowns.AddRange(_parser.Args.Keys.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase)));
}
}
}
return unknowns; return unknowns;
} }
public string GetCommandName()
{
string command = string.Empty;
if (Configure)
{
command = Constants.Runner.CommandLine.Commands.Configure;
}
else if (Remove)
{
command = Constants.Runner.CommandLine.Commands.Remove;
}
else if (Run)
{
command = Constants.Runner.CommandLine.Commands.Run;
}
else if (Warmup)
{
command = Constants.Runner.CommandLine.Commands.Warmup;
}
return command;
}
// //
// Interactive flags. // Interactive flags.
// //

View File

@@ -40,12 +40,6 @@ namespace GitHub.Runner.Listener.Configuration
return creds; return creds;
} }
#if USE_BROKER
public VssCredentials LoadCredentials()
{
return new VssCredentials();
}
#else
public VssCredentials LoadCredentials() public VssCredentials LoadCredentials()
{ {
IConfigurationStore store = HostContext.GetService<IConfigurationStore>(); IConfigurationStore store = HostContext.GetService<IConfigurationStore>();
@@ -75,7 +69,6 @@ namespace GitHub.Runner.Listener.Configuration
return creds; return creds;
} }
#endif
} }
[DataContract] [DataContract]

View File

@@ -23,7 +23,7 @@ namespace GitHub.Runner.Listener
{ {
bool Busy { get; } bool Busy { get; }
TaskCompletionSource<bool> RunOnceJobCompleted { get; } TaskCompletionSource<bool> RunOnceJobCompleted { get; }
void Run(Guid targetHostId, Pipelines.AgentJobRequestMessage message, bool runOnce = false); void Run(Pipelines.AgentJobRequestMessage message, bool runOnce = false);
bool Cancel(JobCancelMessage message); bool Cancel(JobCancelMessage message);
Task WaitAsync(CancellationToken token); Task WaitAsync(CancellationToken token);
Task ShutdownAsync(); Task ShutdownAsync();
@@ -79,7 +79,7 @@ namespace GitHub.Runner.Listener
public bool Busy { get; private set; } public bool Busy { get; private set; }
public void Run(Guid targetHostId, Pipelines.AgentJobRequestMessage jobRequestMessage, bool runOnce = false) public void Run(Pipelines.AgentJobRequestMessage jobRequestMessage, bool runOnce = false)
{ {
Trace.Info($"Job request {jobRequestMessage.RequestId} for plan {jobRequestMessage.Plan.PlanId} job {jobRequestMessage.JobId} received."); Trace.Info($"Job request {jobRequestMessage.RequestId} for plan {jobRequestMessage.Plan.PlanId} job {jobRequestMessage.JobId} received.");
@@ -112,11 +112,11 @@ namespace GitHub.Runner.Listener
if (runOnce) if (runOnce)
{ {
Trace.Info("Start dispatcher for one time used runner."); Trace.Info("Start dispatcher for one time used runner.");
newDispatch.WorkerDispatch = RunOnceAsync(targetHostId, jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token); newDispatch.WorkerDispatch = RunOnceAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
} }
else else
{ {
newDispatch.WorkerDispatch = RunAsync(targetHostId, jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token); newDispatch.WorkerDispatch = RunAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
} }
_jobInfos.TryAdd(newDispatch.JobId, newDispatch); _jobInfos.TryAdd(newDispatch.JobId, newDispatch);
@@ -317,11 +317,11 @@ namespace GitHub.Runner.Listener
} }
} }
private async Task RunOnceAsync(Guid targetHostId, Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken) private async Task RunOnceAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
{ {
try try
{ {
await RunAsync(targetHostId, message, orchestrationId, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken); await RunAsync(message, orchestrationId, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken);
} }
finally finally
{ {
@@ -330,7 +330,7 @@ namespace GitHub.Runner.Listener
} }
} }
private async Task RunAsync(Guid targetHostId, Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken) private async Task RunAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
{ {
Busy = true; Busy = true;
try try
@@ -383,7 +383,7 @@ namespace GitHub.Runner.Listener
await renewJobRequest; await renewJobRequest;
// complete job request with result Cancelled // complete job request with result Cancelled
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, TaskResult.Canceled); await CompleteJobRequestAsync(_poolId, message, lockToken, TaskResult.Canceled);
return; return;
} }
@@ -540,7 +540,7 @@ namespace GitHub.Runner.Listener
await renewJobRequest; await renewJobRequest;
// complete job request // complete job request
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, result, detailInfo); await CompleteJobRequestAsync(_poolId, message, lockToken, result, detailInfo);
// print out unhandled exception happened in worker after we complete job request. // print out unhandled exception happened in worker after we complete job request.
// when we run out of disk space, report back to server has higher priority. // when we run out of disk space, report back to server has higher priority.
@@ -637,7 +637,7 @@ namespace GitHub.Runner.Listener
await renewJobRequest; await renewJobRequest;
// complete job request // complete job request
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, resultOnAbandonOrCancel); await CompleteJobRequestAsync(_poolId, message, lockToken, resultOnAbandonOrCancel);
} }
finally finally
{ {
@@ -666,25 +666,17 @@ namespace GitHub.Runner.Listener
{ {
try try
{ {
// #if USE_BROKER request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
if (!firstJobRequestRenewed.Task.IsCompleted) if (!firstJobRequestRenewed.Task.IsCompleted)
{ {
// fire first renew succeed event. // fire first renew succeed event.
firstJobRequestRenewed.TrySetResult(0); firstJobRequestRenewed.TrySetResult(0);
// Update settings if the runner name has been changed server-side
UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
} }
// #else
// request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
// Trace.Info($"Successfully renew job request {requestId}, job is valid till {request?.LockedUntil.Value}");
// if (!firstJobRequestRenewed.Task.IsCompleted)
// {
// // fire first renew succeed event.
// firstJobRequestRenewed.TrySetResult(0);
// // Update settings if the runner name has been changed server-side
// UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
// }
// #endif
if (encounteringError > 0) if (encounteringError > 0)
{ {
@@ -919,7 +911,7 @@ namespace GitHub.Runner.Listener
} }
} }
private async Task CompleteJobRequestAsync(Guid targetHostId, int poolId, Pipelines.AgentJobRequestMessage message, Guid lockToken, TaskResult result, string detailInfo = null) private async Task CompleteJobRequestAsync(int poolId, Pipelines.AgentJobRequestMessage message, Guid lockToken, TaskResult result, string detailInfo = null)
{ {
Trace.Entering(); Trace.Entering();
@@ -936,7 +928,7 @@ namespace GitHub.Runner.Listener
{ {
try try
{ {
await runnerServer.FinishAgentRequestAsync(poolId, message.RequestId, lockToken, DateTime.UtcNow, result, targetHostId, CancellationToken.None); await runnerServer.FinishAgentRequestAsync(poolId, message.RequestId, lockToken, DateTime.UtcNow, result, CancellationToken.None);
return; return;
} }
catch (TaskAgentJobNotFoundException) catch (TaskAgentJobNotFoundException)

View File

@@ -2,11 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -31,13 +27,10 @@ namespace GitHub.Runner.Listener
public sealed class MessageListener : RunnerService, IMessageListener public sealed class MessageListener : RunnerService, IMessageListener
{ {
#if !USE_BROKER
private long? _lastMessageId; private long? _lastMessageId;
#endif
private RunnerSettings _settings; private RunnerSettings _settings;
private ITerminal _term; private ITerminal _term;
private IRunnerServer _runnerServer; private IRunnerServer _runnerServer;
private IBrokerServer _brokerServer;
private TaskAgentSession _session; private TaskAgentSession _session;
private TimeSpan _getNextMessageRetryInterval; private TimeSpan _getNextMessageRetryInterval;
private bool _accessTokenRevoked = false; private bool _accessTokenRevoked = false;
@@ -52,44 +45,8 @@ namespace GitHub.Runner.Listener
_term = HostContext.GetService<ITerminal>(); _term = HostContext.GetService<ITerminal>();
_runnerServer = HostContext.GetService<IRunnerServer>(); _runnerServer = HostContext.GetService<IRunnerServer>();
_brokerServer = HostContext.GetService<IBrokerServer>();
} }
#if USE_BROKER
public async Task<Boolean> CreateSessionAsync(CancellationToken token)
{
Trace.Entering();
// Settings
var configManager = HostContext.GetService<IConfigurationManager>();
_settings = configManager.LoadSettings();
var serverUrl = _settings.ServerUrl;
Trace.Info(_settings);
// Connect
token.ThrowIfCancellationRequested();
Trace.Info($"Attempt to create session.");
Trace.Info("Connecting to the Runner Server...");
_term.WriteLine($"Connecting to {new Uri(serverUrl)}");
await _brokerServer.ConnectAsync(new Uri(serverUrl), token);
_term.WriteLine();
_term.WriteSuccessMessage("Connected to GitHub");
_term.WriteLine();
// Session info
var agent = new TaskAgentReference
{
Id = _settings.AgentId,
Name = _settings.AgentName,
Version = BuildConstants.RunnerPackage.Version,
OSDescription = RuntimeInformation.OSDescription,
};
string sessionName = $"{Environment.MachineName ?? "RUNNER"}";
_session = new TaskAgentSession(sessionName, agent);
return true;
}
#else
public async Task<Boolean> CreateSessionAsync(CancellationToken token) public async Task<Boolean> CreateSessionAsync(CancellationToken token)
{ {
Trace.Entering(); Trace.Entering();
@@ -124,7 +81,6 @@ namespace GitHub.Runner.Listener
Trace.Info($"Attempt to create session."); Trace.Info($"Attempt to create session.");
try try
{ {
Trace.Info("Connecting to the Runner Server...");
Trace.Info("Connecting to the Runner Server..."); Trace.Info("Connecting to the Runner Server...");
await _runnerServer.ConnectAsync(new Uri(serverUrl), creds); await _runnerServer.ConnectAsync(new Uri(serverUrl), creds);
Trace.Info("VssConnection created"); Trace.Info("VssConnection created");
@@ -195,7 +151,6 @@ namespace GitHub.Runner.Listener
} }
} }
} }
#endif
public async Task DeleteSessionAsync() public async Task DeleteSessionAsync()
{ {
@@ -215,167 +170,6 @@ namespace GitHub.Runner.Listener
} }
} }
#if USE_BROKER
[DataContract]
public sealed class MessageRef
{
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "token")]
public string Token { get; set; }
[DataMember(Name = "scopeId")]
public string ScopeId { get; set; }
[DataMember(Name = "planType")]
public string PlanType { get; set; }
[DataMember(Name = "planGroup")]
public string PlanGroup { get; set; }
[DataMember(Name = "instanceRefs")]
public InstanceRef[] InstanceRefs { get; set; }
[DataMember(Name = "labels")]
public string[] Labels { get; set; }
}
[DataContract]
public sealed class InstanceRef
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "instanceType")]
public string InstanceType { get; set; }
[DataMember(Name = "attempt")]
public int Attempt { get; set; }
}
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
{
Trace.Entering();
ArgUtil.NotNull(_session, nameof(_session));
ArgUtil.NotNull(_settings, nameof(_settings));
bool encounteringError = false;
int continuousError = 0;
string errorMessage = string.Empty;
Stopwatch heartbeat = new Stopwatch();
heartbeat.Restart();
while (true)
{
token.ThrowIfCancellationRequested();
string message = null;
try
{
message = await _brokerServer.GetMessageAsync(_session, _settings, null/*_lastMessageId*/, token);
_term.WriteLine($"{DateTime.UtcNow:u}: {message}");
if (!string.IsNullOrEmpty(message))
{
var messageRef = StringUtil.ConvertFromJson<MessageRef>(message);
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", messageRef.Token);
var response = await client.GetAsync(messageRef.Url, token);
if (!response.IsSuccessStatusCode)
{
var content = default(string);
try
{
content = await response.Content.ReadAsStringAsync();
}
catch
{
}
var error = $"HTTP {(int)response.StatusCode} {Enum.GetName(typeof(HttpStatusCode), response.StatusCode)}";
if (!string.IsNullOrEmpty(content))
{
error = $"{error}: {content}";
}
throw new Exception(error);
}
var fullMessage = await response.Content.ReadAsStringAsync();
return StringUtil.ConvertFromJson<TaskAgentMessage>(fullMessage);
}
if (encounteringError) //print the message once only if there was an error
{
_term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
encounteringError = false;
continuousError = 0;
}
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
Trace.Info("Get next message has been cancelled.");
throw;
}
catch (TaskAgentAccessTokenExpiredException)
{
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
_accessTokenRevoked = true;
throw;
}
catch (Exception ex)
{
Trace.Error("Catch exception during get next message.");
Trace.Error(ex);
// don't retry if SkipSessionRecover = true, DT service will delete agent session to stop agent from taking more jobs.
if (ex is TaskAgentSessionExpiredException && !_settings.SkipSessionRecover && await CreateSessionAsync(token))
{
Trace.Info($"{nameof(TaskAgentSessionExpiredException)} received, recovered by recreate session.");
}
else if (!IsGetNextMessageExceptionRetriable(ex))
{
throw;
}
else
{
continuousError++;
//retry after a random backoff to avoid service throttling
//in case of there is a service error happened and all agents get kicked off of the long poll and all agent try to reconnect back at the same time.
if (continuousError <= 5)
{
// random backoff [15, 30]
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), _getNextMessageRetryInterval);
}
else
{
// more aggressive backoff [30, 60]
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(60), _getNextMessageRetryInterval);
}
if (!encounteringError)
{
//print error only on the first consecutive error
_term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
encounteringError = true;
}
// re-create VssConnection before next retry
await _runnerServer.RefreshConnectionAsync(RunnerConnectionType.MessageQueue, TimeSpan.FromSeconds(60));
Trace.Info("Sleeping for {0} seconds before retrying.", _getNextMessageRetryInterval.TotalSeconds);
await HostContext.Delay(_getNextMessageRetryInterval, token);
}
}
// if (message == null)
// {
// if (heartbeat.Elapsed > TimeSpan.FromMinutes(30))
// {
// Trace.Info($"No message retrieved from session '{_session.SessionId}' within last 30 minutes.");
// heartbeat.Restart();
// }
// else
// {
// Trace.Verbose($"No message retrieved from session '{_session.SessionId}'.");
// }
// continue;
// }
// Trace.Info($"Message '{message.MessageId}' received from session '{_session.SessionId}'.");
// return message;
}
}
#else
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token) public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
{ {
Trace.Entering(); Trace.Entering();
@@ -487,7 +281,6 @@ namespace GitHub.Runner.Listener
return message; return message;
} }
} }
#endif
public async Task DeleteMessageAsync(TaskAgentMessage message) public async Task DeleteMessageAsync(TaskAgentMessage message)
{ {

View File

@@ -95,7 +95,15 @@ namespace GitHub.Runner.Listener
var unknownCommandlines = command.Validate(); var unknownCommandlines = command.Validate();
if (unknownCommandlines.Count > 0) if (unknownCommandlines.Count > 0)
{ {
terminal.WriteError($"Unrecognized command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help"); string commandName = command.GetCommandName();
if (string.IsNullOrEmpty(commandName))
{
terminal.WriteError($"This command does not recognize the command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
}
else
{
terminal.WriteError($"Unrecognized command-line input arguments for command {commandName}: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
}
} }
// Defer to the Runner class to execute the command. // Defer to the Runner class to execute the command.

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -1,18 +1,20 @@
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Listener.Configuration;
using System; using System;
using System.Threading; using System.Collections.Generic;
using System.Threading.Tasks;
using GitHub.Services.WebApi;
using Pipelines = GitHub.DistributedTask.Pipelines;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
using System.Linq;
using GitHub.Runner.Listener.Check; using GitHub.Runner.Listener.Check;
using System.Collections.Generic; using GitHub.Runner.Listener.Configuration;
using GitHub.Runner.Sdk;
using GitHub.Services.WebApi;
using Pipelines = GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.Pipelines;
using GitHub.Services.Common;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@@ -326,6 +328,7 @@ namespace GitHub.Runner.Listener
// Should we try to cleanup ephemeral runners // Should we try to cleanup ephemeral runners
bool runOnceJobCompleted = false; bool runOnceJobCompleted = false;
bool skipSessionDeletion = false;
try try
{ {
var notification = HostContext.GetService<IJobNotification>(); var notification = HostContext.GetService<IJobNotification>();
@@ -453,7 +456,7 @@ namespace GitHub.Runner.Listener
{ {
Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'"); Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'");
var jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(message.Body); var jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(message.Body);
jobDispatcher.Run(Guid.Empty, jobMessage, runOnce); jobDispatcher.Run(jobMessage, runOnce);
if (runOnce) if (runOnce)
{ {
Trace.Info("One time used runner received job message."); Trace.Info("One time used runner received job message.");
@@ -471,19 +474,25 @@ namespace GitHub.Runner.Listener
} }
else else
{ {
var messageRef = StringUtil.ConvertFromJson<MessageRef>(message.Body); var messageRef = StringUtil.ConvertFromJson<RunnerJobRequestRef>(message.Body);
// Create connection // Create connection
var credMgr = HostContext.GetService<ICredentialManager>(); var credMgr = HostContext.GetService<ICredentialManager>();
var creds = credMgr.LoadCredentials(); var creds = credMgr.LoadCredentials();
// todo: add retries // todo: add retries https://github.com/github/actions-broker/issues/49
var runServer = HostContext.CreateService<IRunServer>(); var runServer = HostContext.CreateService<IRunServer>();
await runServer.ConnectAsync(new Uri(settings.ServerUrl), creds); await runServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
var jobMessage = await runServer.GetJobMessageAsync(messageRef.ScopeId, messageRef.HostId, messageRef.PlanType, messageRef.PlanGroup, messageRef.PlanId, messageRef.InstanceRefs);
// todo: Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'"); var jobMessage = await RetriesHelper<AgentJobRequestMessage>.RetryWithTimeoutAsync(async () =>
jobDispatcher.Run(messageRef.HostId, jobMessage, runOnce); {
return await runServer.GetJobMessageAsync(messageRef.RunnerRequestId);
},
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10),
5);
jobDispatcher.Run(jobMessage, runOnce);
if (runOnce) if (runOnce)
{ {
Trace.Info("One time used runner received job message."); Trace.Info("One time used runner received job message.");
@@ -502,6 +511,14 @@ namespace GitHub.Runner.Listener
Trace.Info($"Skip message deletion for cancellation message '{message.MessageId}'."); Trace.Info($"Skip message deletion for cancellation message '{message.MessageId}'.");
} }
} }
else if (string.Equals(message.MessageType, Pipelines.HostedRunnerShutdownMessage.MessageType, StringComparison.OrdinalIgnoreCase))
{
var HostedRunnerShutdownMessage = JsonUtility.FromString<Pipelines.HostedRunnerShutdownMessage>(message.Body);
skipMessageDeletion = true;
skipSessionDeletion = true;
Trace.Info($"Service requests the hosted runner to shutdown. Reason: '{HostedRunnerShutdownMessage.Reason}'.");
return Constants.Runner.ReturnCode.Success;
}
else else
{ {
Trace.Error($"Received message {message.MessageId} with unsupported message type {message.MessageType}."); Trace.Error($"Received message {message.MessageId} with unsupported message type {message.MessageType}.");
@@ -535,15 +552,18 @@ namespace GitHub.Runner.Listener
await jobDispatcher.ShutdownAsync(); await jobDispatcher.ShutdownAsync();
} }
try if (!skipSessionDeletion)
{ {
await _listener.DeleteSessionAsync(); try
} {
catch (Exception ex) when (runOnce) await _listener.DeleteSessionAsync();
{ }
// ignore exception during delete session for ephemeral runner since the runner might already be deleted from the server side catch (Exception ex) when (runOnce)
// and the delete session call will ends up with 401. {
Trace.Info($"Ignore any exception during DeleteSession for an ephemeral runner. {ex}"); // ignore exception during delete session for ephemeral runner since the runner might already be deleted from the server side
// and the delete session call will ends up with 401.
Trace.Info($"Ignore any exception during DeleteSession for an ephemeral runner. {ex}");
}
} }
messageQueueLoopTokenSource.Dispose(); messageQueueLoopTokenSource.Dispose();

View File

@@ -0,0 +1,13 @@
using System.Runtime.Serialization;
namespace GitHub.Runner.Listener
{
[DataContract]
public sealed class RunnerJobRequestRef
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "runner_request_id")]
public string RunnerRequestId { get; set; }
}
}

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -36,7 +36,6 @@ namespace GitHub.Runner.Sdk
public static VssConnection CreateConnection(Uri serverUri, VssCredentials credentials, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, TimeSpan? timeout = null) public static VssConnection CreateConnection(Uri serverUri, VssCredentials credentials, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, TimeSpan? timeout = null)
{ {
// System.Console.WriteLine("VssUtil.CreateConnection");
VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone(); VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone();
int maxRetryRequest; int maxRetryRequest;
@@ -58,6 +57,10 @@ namespace GitHub.Runner.Sdk
settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200)); settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200));
} }
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ALLOW_REDIRECT")))
{
settings.AllowAutoRedirect = true;
}
// Remove Invariant from the list of accepted languages. // Remove Invariant from the list of accepted languages.
// //

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {

View File

@@ -817,7 +817,6 @@ namespace GitHub.Runner.Worker
{ {
// Something else bad happened, let's go to our retry logic // Something else bad happened, let's go to our retry logic
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
throw new Exception("Unexpected response code: " + response.StatusCode);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.ObjectTemplating; using GitHub.DistributedTask.ObjectTemplating;
using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.ObjectTemplating.Tokens;
@@ -9,7 +10,6 @@ using GitHub.DistributedTask.Pipelines.ObjectTemplating;
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;
using GitHub.Runner.Worker.Handlers; using GitHub.Runner.Worker.Handlers;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
@@ -171,8 +171,16 @@ namespace GitHub.Runner.Worker
// Load the inputs. // Load the inputs.
ExecutionContext.Debug("Loading inputs"); ExecutionContext.Debug("Loading inputs");
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator(); Dictionary<string, string> inputs;
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions); if (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.UseContainerPathForTemplate) ?? false)
{
inputs = EvaluateStepInputs(stepHost);
}
else
{
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
}
var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> input in inputs) foreach (KeyValuePair<string, string> input in inputs)
@@ -299,6 +307,15 @@ namespace GitHub.Runner.Worker
return didFullyEvaluate; return didFullyEvaluate;
} }
private Dictionary<String, String> EvaluateStepInputs(IStepHost stepHost)
{
DictionaryContextData expressionValues = ExecutionContext.GetExpressionValues(stepHost);
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, expressionValues, ExecutionContext.ExpressionFunctions);
return inputs;
}
private string GenerateDisplayName(ActionStep action, DictionaryContextData contextData, IExecutionContext context, out bool didFullyEvaluate) private string GenerateDisplayName(ActionStep action, DictionaryContextData contextData, IExecutionContext context, out bool didFullyEvaluate)
{ {
ArgUtil.NotNull(context, nameof(context)); ArgUtil.NotNull(context, nameof(context));

View File

@@ -1,16 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using System.Collections.ObjectModel;
using System.Linq;
namespace GitHub.Runner.Worker.Container namespace GitHub.Runner.Worker.Container
{ {
public class ContainerInfo public class ContainerInfo
{ {
private IDictionary<string, string> _userMountVolumes;
private List<MountVolume> _mountVolumes; private List<MountVolume> _mountVolumes;
private IDictionary<string, string> _userPortMappings; private IDictionary<string, string> _userPortMappings;
private List<PortMapping> _portMappings; private List<PortMapping> _portMappings;
@@ -68,8 +68,7 @@ namespace GitHub.Runner.Worker.Container
{ {
foreach (var volume in container.Volumes) foreach (var volume in container.Volumes)
{ {
UserMountVolumes[volume] = volume; MountVolumes.Add(new MountVolume(volume, isUserProvided: true));
MountVolumes.Add(new MountVolume(volume));
} }
} }
@@ -104,19 +103,20 @@ namespace GitHub.Runner.Worker.Container
return _environmentVariables; return _environmentVariables;
} }
} }
public ReadOnlyCollection<MountVolume> UserMountVolumes
public IDictionary<string, string> UserMountVolumes
{ {
get get
{ {
if (_userMountVolumes == null) return MountVolumes.Where(v => !string.IsNullOrEmpty(v.UserProvidedValue)).ToList().AsReadOnly();
{ }
_userMountVolumes = new Dictionary<string, string>(); }
} public ReadOnlyCollection<MountVolume> SystemMountVolumes
return _userMountVolumes; {
get
{
return MountVolumes.Where(v => string.IsNullOrEmpty(v.UserProvidedValue)).ToList().AsReadOnly();
} }
} }
public List<MountVolume> MountVolumes public List<MountVolume> MountVolumes
{ {
get get
@@ -260,18 +260,27 @@ namespace GitHub.Runner.Worker.Container
public class MountVolume public class MountVolume
{ {
public string UserProvidedValue { get; set; }
public MountVolume(string sourceVolumePath, string targetVolumePath, bool readOnly = false) public MountVolume(string sourceVolumePath, string targetVolumePath, bool readOnly = false)
{ {
this.SourceVolumePath = sourceVolumePath; this.SourceVolumePath = sourceVolumePath;
this.TargetVolumePath = targetVolumePath; this.TargetVolumePath = targetVolumePath;
this.ReadOnly = readOnly; this.ReadOnly = readOnly;
} }
public MountVolume(string fromString) public MountVolume(string fromString)
{ {
ParseVolumeString(fromString); ParseVolumeString(fromString);
} }
public MountVolume(string fromString, bool isUserProvided)
{
ParseVolumeString(fromString);
if (isUserProvided)
{
UserProvidedValue = fromString;
}
}
private void ParseVolumeString(string volume) private void ParseVolumeString(string volume)
{ {
var volumeSplit = volume.Split(":"); var volumeSplit = volume.Split(":");

View File

@@ -192,13 +192,12 @@ namespace GitHub.Runner.Worker
{ {
Trace.Info($"User provided port: {port.Value}"); Trace.Info($"User provided port: {port.Value}");
} }
foreach (var volume in container.UserMountVolumes) foreach (var mount in container.UserMountVolumes)
{ {
Trace.Info($"User provided volume: {volume.Value}"); Trace.Info($"User provided volume: {mount.UserProvidedValue}");
var mount = new MountVolume(volume.Value);
if (string.Equals(mount.SourceVolumePath, "/", StringComparison.OrdinalIgnoreCase)) if (string.Equals(mount.SourceVolumePath, "/", StringComparison.OrdinalIgnoreCase))
{ {
executionContext.Warning($"Volume mount {volume.Value} is going to mount '/' into the container which may cause file ownership change in the entire file system and cause Actions Runner to lose permission to access the disk."); executionContext.Warning($"Volume mount {mount.UserProvidedValue} is going to mount '/' into the container which may cause file ownership change in the entire file system and cause Actions Runner to lose permission to access the disk.");
} }
} }

View File

@@ -1,18 +1,13 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web;
using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.Expressions2;
using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.ObjectTemplating.Tokens;
using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.Pipelines.ObjectTemplating; using GitHub.DistributedTask.Pipelines.ObjectTemplating;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
@@ -20,7 +15,7 @@ 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.WebApi; using GitHub.Runner.Worker.Handlers;
using Newtonsoft.Json; using Newtonsoft.Json;
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating; using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
@@ -115,7 +110,6 @@ namespace GitHub.Runner.Worker
void UpdateGlobalStepsContext(); void UpdateGlobalStepsContext();
void WriteWebhookPayload(); void WriteWebhookPayload();
} }
public sealed class ExecutionContext : RunnerService, IExecutionContext public sealed class ExecutionContext : RunnerService, IExecutionContext
@@ -1199,6 +1193,66 @@ namespace GitHub.Runner.Worker
{ {
return new TemplateTraceWriter(context); return new TemplateTraceWriter(context);
} }
public static DictionaryContextData GetExpressionValues(this IExecutionContext context, IStepHost stepHost)
{
if (stepHost is ContainerStepHost)
{
var expressionValues = context.ExpressionValues.Clone() as DictionaryContextData;
context.UpdatePathsInExpressionValues("github", expressionValues, stepHost);
context.UpdatePathsInExpressionValues("runner", expressionValues, stepHost);
return expressionValues;
}
else
{
return context.ExpressionValues.Clone() as DictionaryContextData;
}
}
private static void UpdatePathsInExpressionValues(this IExecutionContext context, string contextName, DictionaryContextData expressionValues, IStepHost stepHost)
{
var dict = expressionValues[contextName].AssertDictionary($"expected context {contextName} to be a dictionary");
context.ResolvePathsInExpressionValuesDictionary(dict, stepHost);
expressionValues[contextName] = dict;
}
private static void ResolvePathsInExpressionValuesDictionary(this IExecutionContext context, DictionaryContextData dict, IStepHost stepHost)
{
foreach (var key in dict.Keys.ToList())
{
if (dict[key] is StringContextData)
{
var value = dict[key].ToString();
if (!string.IsNullOrEmpty(value))
{
dict[key] = new StringContextData(stepHost.ResolvePathForStepHost(value));
}
}
else if (dict[key] is DictionaryContextData)
{
var innerDict = dict[key].AssertDictionary("expected dictionary");
context.ResolvePathsInExpressionValuesDictionary(innerDict, stepHost);
var updatedDict = new DictionaryContextData();
foreach (var k in innerDict.Keys.ToList())
{
updatedDict[k] = innerDict[k];
}
dict[key] = updatedDict;
}
else if (dict[key] is CaseSensitiveDictionaryContextData)
{
var innerDict = dict[key].AssertDictionary("expected dictionary");
context.ResolvePathsInExpressionValuesDictionary(innerDict, stepHost);
var updatedDict = new CaseSensitiveDictionaryContextData();
foreach (var k in innerDict.Keys.ToList())
{
updatedDict[k] = innerDict[k];
}
dict[key] = updatedDict;
}
}
}
} }
internal sealed class TemplateTraceWriter : ObjectTemplating.ITraceWriter internal sealed class TemplateTraceWriter : ObjectTemplating.ITraceWriter

View File

@@ -15,7 +15,7 @@ namespace GitHub.Runner.Worker
{ {
void InitializeFiles(IExecutionContext context, ContainerInfo container); void InitializeFiles(IExecutionContext context, ContainerInfo container);
void ProcessFiles(IExecutionContext context, ContainerInfo container); void ProcessFiles(IExecutionContext context, ContainerInfo container);
} }
public sealed class FileCommandManager : RunnerService, IFileCommandManager public sealed class FileCommandManager : RunnerService, IFileCommandManager
@@ -57,7 +57,7 @@ namespace GitHub.Runner.Worker
TryDeleteFile(newPath); TryDeleteFile(newPath);
File.Create(newPath).Dispose(); File.Create(newPath).Dispose();
var pathToSet = container != null ? container.TranslateToContainerPath(newPath) : newPath; var pathToSet = container != null ? container.TranslateToContainerPath(newPath) : newPath;
context.SetGitHubContext(fileCommand.ContextName, pathToSet); context.SetGitHubContext(fileCommand.ContextName, pathToSet);
} }
} }
@@ -66,7 +66,7 @@ namespace GitHub.Runner.Worker
{ {
foreach (var fileCommand in _commandExtensions) foreach (var fileCommand in _commandExtensions)
{ {
try try
{ {
fileCommand.ProcessCommand(context, Path.Combine(_fileCommandDirectory, fileCommand.FilePrefix + _fileSuffix),container); fileCommand.ProcessCommand(context, Path.Combine(_fileCommandDirectory, fileCommand.FilePrefix + _fileSuffix),container);
} }
@@ -266,7 +266,7 @@ namespace GitHub.Runner.Worker
public sealed class CreateStepSummaryCommand : RunnerService, IFileCommandExtension public sealed class CreateStepSummaryCommand : RunnerService, IFileCommandExtension
{ {
private const int _attachmentSizeLimit = 128 * 1024; public const int AttachmentSizeLimit = 1024 * 1024;
public string ContextName => "step_summary"; public string ContextName => "step_summary";
public string FilePrefix => "step_summary_"; public string FilePrefix => "step_summary_";
@@ -275,12 +275,6 @@ namespace GitHub.Runner.Worker
public void ProcessCommand(IExecutionContext context, string filePath, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string filePath, ContainerInfo container)
{ {
if (!context.Global.Variables.GetBoolean("DistributedTask.UploadStepSummary") ?? true)
{
Trace.Info("Step Summary is disabled; skipping attachment upload");
return;
}
if (String.IsNullOrEmpty(filePath) || !File.Exists(filePath)) if (String.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{ {
Trace.Info($"Step Summary file ({filePath}) does not exist; skipping attachment upload"); Trace.Info($"Step Summary file ({filePath}) does not exist; skipping attachment upload");
@@ -296,9 +290,9 @@ namespace GitHub.Runner.Worker
return; return;
} }
if (fileSize > _attachmentSizeLimit) if (fileSize > AttachmentSizeLimit)
{ {
context.Error(String.Format(Constants.Runner.UnsupportedSummarySize, _attachmentSizeLimit / 1024, fileSize / 1024)); context.Error(String.Format(Constants.Runner.UnsupportedSummarySize, AttachmentSizeLimit / 1024, fileSize / 1024));
Trace.Info($"Step Summary file ({filePath}) is too large ({fileSize} bytes); skipping attachment upload"); Trace.Info($"Step Summary file ({filePath}) is too large ({fileSize} bytes); skipping attachment upload");
return; return;

View File

@@ -94,6 +94,14 @@ namespace GitHub.Runner.Worker.Handlers
workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work); workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
} }
#if OS_OSX
if (string.Equals(Data.NodeVersion, "node12", StringComparison.OrdinalIgnoreCase) &&
Constants.Runner.PlatformArchitecture.Equals(Constants.Architecture.Arm64))
{
ExecutionContext.Output($"The node12 is not supported on macOS ARM64 platform. Use node16 instead.");
Data.NodeVersion = "node16";
}
#endif
var nodeRuntimeVersion = await StepHost.DetermineNodeRuntimeVersion(ExecutionContext, Data.NodeVersion); var nodeRuntimeVersion = await StepHost.DetermineNodeRuntimeVersion(ExecutionContext, Data.NodeVersion);
string file = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), nodeRuntimeVersion, "bin", $"node{IOUtil.ExeExtension}"); string file = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), nodeRuntimeVersion, "bin", $"node{IOUtil.ExeExtension}");

View File

@@ -151,6 +151,11 @@ namespace GitHub.Runner.Worker.Handlers
} }
} }
if (line.Contains("fatal: unsafe repository", StringComparison.OrdinalIgnoreCase))
{
_executionContext.StepTelemetry.ErrorMessages.Add(line);
}
// Regular output // Regular output
_executionContext.Output(line); _executionContext.Output(line);
} }

View File

@@ -202,14 +202,32 @@ namespace GitHub.Runner.Worker.Handlers
} }
else else
{ {
var parsed = ScriptHandlerHelpers.ParseShellOptionString(shell); // For these shells, we want to use system binaries
shellCommand = parsed.shellCommand; var systemShells = new string[] { "bash", "sh", "powershell", "pwsh" };
// For non-ContainerStepHost, the command must be located on the host by Which if (!IsActionStep && systemShells.Contains(shell))
commandPath = WhichUtil.Which(parsed.shellCommand, !isContainerStepHost, Trace, prependPath);
argFormat = $"{parsed.shellArgs}".TrimStart();
if (string.IsNullOrEmpty(argFormat))
{ {
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand); shellCommand = shell;
commandPath = WhichUtil.Which(shell, !isContainerStepHost, Trace, prependPath);
if (shell == "bash")
{
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat("sh");
}
else
{
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shell);
}
}
else
{
var parsed = ScriptHandlerHelpers.ParseShellOptionString(shell);
shellCommand = parsed.shellCommand;
// For non-ContainerStepHost, the command must be located on the host by Which
commandPath = WhichUtil.Which(parsed.shellCommand, !isContainerStepHost, Trace, prependPath);
argFormat = $"{parsed.shellArgs}".TrimStart();
if (string.IsNullOrEmpty(argFormat))
{
argFormat = ScriptHandlerHelpers.GetScriptArgumentsFormat(shellCommand);
}
} }
} }
@@ -229,7 +247,7 @@ namespace GitHub.Runner.Worker.Handlers
{ {
// We do not not the full path until we know what shell is being used, so that we can determine the file extension // We do not not the full path until we know what shell is being used, so that we can determine the file extension
scriptFilePath = Path.Combine(tempDirectory, $"{Guid.NewGuid()}{ScriptHandlerHelpers.GetScriptFileExtension(shellCommand)}"); scriptFilePath = Path.Combine(tempDirectory, $"{Guid.NewGuid()}{ScriptHandlerHelpers.GetScriptFileExtension(shellCommand)}");
resolvedScriptPath = $"{StepHost.ResolvePathForStepHost(scriptFilePath).Replace("\"", "\\\"")}"; resolvedScriptPath = StepHost.ResolvePathForStepHost(scriptFilePath).Replace("\"", "\\\"");
} }
else else
{ {

View File

@@ -82,18 +82,23 @@ namespace GitHub.Runner.Worker.Handlers
} }
} }
internal static string GetDefaultShellForScript(string path, Common.Tracing trace, string prependPath) internal static string GetDefaultShellNameForScript(string path, Common.Tracing trace, string prependPath)
{ {
var format = "{0} {1}";
switch (Path.GetExtension(path)) switch (Path.GetExtension(path))
{ {
case ".sh": case ".sh":
// use 'sh' args but prefer bash // use 'sh' args but prefer bash
var pathToShell = WhichUtil.Which("bash", false, trace, prependPath) ?? WhichUtil.Which("sh", true, trace, prependPath); if (WhichUtil.Which("bash", false, trace, prependPath) != null)
return string.Format(format, pathToShell, _defaultArguments["sh"]); {
return "bash";
}
return "sh";
case ".ps1": case ".ps1":
var pathToPowershell = WhichUtil.Which("pwsh", false, trace, prependPath) ?? WhichUtil.Which("powershell", true, trace, prependPath); if (WhichUtil.Which("pwsh", false, trace, prependPath) != null)
return string.Format(format, pathToPowershell, _defaultArguments["powershell"]); {
return "pwsh";
}
return "powershell";
default: default:
throw new ArgumentException($"{path} is not a valid path to a script. Make sure it ends in '.sh' or '.ps1'."); throw new ArgumentException($"{path} is not a valid path to a script. Make sure it ends in '.sh' or '.ps1'.");
} }

View File

@@ -1,18 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System.Linq; using System.Linq;
using GitHub.DistributedTask.Pipelines.ContextData;
namespace GitHub.Runner.Worker.Handlers namespace GitHub.Runner.Worker.Handlers
{ {

View File

@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.Expressions2;
using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.ObjectTemplating.Tokens;
using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.Pipelines.ObjectTemplating; using GitHub.DistributedTask.Pipelines.ObjectTemplating;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
@@ -206,6 +207,7 @@ namespace GitHub.Runner.Worker
// Evaluate the job container // Evaluate the job container
context.Debug("Evaluating job container"); context.Debug("Evaluating job container");
var container = templateEvaluator.EvaluateJobContainer(message.JobContainer, jobContext.ExpressionValues, jobContext.ExpressionFunctions); var container = templateEvaluator.EvaluateJobContainer(message.JobContainer, jobContext.ExpressionValues, jobContext.ExpressionFunctions);
ValidateJobContainer(container);
if (container != null) if (container != null)
{ {
jobContext.Global.Container = new Container.ContainerInfo(HostContext, container); jobContext.Global.Container = new Container.ContainerInfo(HostContext, container);
@@ -672,5 +674,13 @@ namespace GitHub.Runner.Worker
Trace.Info($"Total accessible running process: {snapshot.Count}."); Trace.Info($"Total accessible running process: {snapshot.Count}.");
return snapshot; return snapshot;
} }
private static void ValidateJobContainer(JobContainer container)
{
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.RequireJobContainer)) && container == null)
{
throw new ArgumentException("Jobs without a job container are forbidden on this runner, please add a 'container:' to your job or contact your self-hosted runner administrator.");
}
}
} }
} }

View File

@@ -18,8 +18,8 @@ namespace GitHub.Runner.Worker
public class JobHookData public class JobHookData
{ {
public string Path {get; private set;} public string Path { get; private set; }
public ActionRunStage Stage {get; private set;} public ActionRunStage Stage { get; private set; }
public JobHookData(ActionRunStage stage, string path) public JobHookData(ActionRunStage stage, string path)
{ {
@@ -60,7 +60,7 @@ namespace GitHub.Runner.Worker
Dictionary<string, string> inputs = new() Dictionary<string, string> inputs = new()
{ {
["path"] = hookData.Path, ["path"] = hookData.Path,
["shell"] = ScriptHandlerHelpers.GetDefaultShellForScript(hookData.Path, Trace, prependPath) ["shell"] = ScriptHandlerHelpers.GetDefaultShellNameForScript(hookData.Path, Trace, prependPath)
}; };
// Create the handler // Create the handler

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -132,7 +132,7 @@
"continue-on-error": "boolean-steps-context", "continue-on-error": "boolean-steps-context",
"working-directory": "string-steps-context", "working-directory": "string-steps-context",
"shell": { "shell": {
"type": "non-empty-string", "type": "string-steps-context",
"required": true "required": true
} }
} }

View File

@@ -18,7 +18,6 @@ namespace GitHub.Services.Common
public override bool IsAuthenticationChallenge(IHttpResponse webResponse) public override bool IsAuthenticationChallenge(IHttpResponse webResponse)
{ {
// System.Console.WriteLine($"FederatedCredential.IsAuthenticationChallenge");
if (webResponse == null) if (webResponse == null)
{ {
return false; return false;

View File

@@ -88,7 +88,6 @@ namespace GitHub.Services.Common
IHttpResponse response, IHttpResponse response,
IssuedToken failedToken) IssuedToken failedToken)
{ {
// System.Console.WriteLine("IssuedTokenCredential.CreateTokenProvider");
if (response != null && !IsAuthenticationChallenge(response)) if (response != null && !IsAuthenticationChallenge(response))
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
@@ -100,14 +99,12 @@ namespace GitHub.Services.Common
{ {
throw new InvalidOperationException($"The {nameof(TokenStorageUrl)} property must have a value if the {nameof(Storage)} property is set on this instance of {GetType().Name}."); throw new InvalidOperationException($"The {nameof(TokenStorageUrl)} property must have a value if the {nameof(Storage)} property is set on this instance of {GetType().Name}.");
} }
// System.Console.WriteLine($"IssuedTokenCredential.CreateTokenProvider: TokenStorageUrl: {TokenStorageUrl}");
InitialToken = Storage.RetrieveToken(TokenStorageUrl, CredentialType); InitialToken = Storage.RetrieveToken(TokenStorageUrl, CredentialType);
} }
IssuedTokenProvider provider = OnCreateTokenProvider(serverUrl, response); IssuedTokenProvider provider = OnCreateTokenProvider(serverUrl, response);
if (provider != null) if (provider != null)
{ {
// System.Console.WriteLine($"IssuedTokenCredential.CreateTokenProvider: provider: {provider}");
provider.TokenStorageUrl = TokenStorageUrl; provider.TokenStorageUrl = TokenStorageUrl;
} }
@@ -126,7 +123,6 @@ namespace GitHub.Services.Common
internal virtual string GetAuthenticationChallenge(IHttpResponse webResponse) internal virtual string GetAuthenticationChallenge(IHttpResponse webResponse)
{ {
// System.Console.WriteLine($"IssuedTokenCredential.GetAuthenticationChallenge");
IEnumerable<String> values; IEnumerable<String> values;
if (!webResponse.Headers.TryGetValues(Internal.HttpHeaders.WwwAuthenticate, out values)) if (!webResponse.Headers.TryGetValues(Internal.HttpHeaders.WwwAuthenticate, out values))
{ {

View File

@@ -108,7 +108,6 @@ namespace GitHub.Services.Common
TaskScheduler scheduler, TaskScheduler scheduler,
IVssCredentialPrompt credentialPrompt) IVssCredentialPrompt credentialPrompt)
{ {
// System.Console.WriteLine($"VssCredentials.ctor");
this.PromptType = promptType; this.PromptType = promptType;
if (promptType == CredentialPromptType.PromptIfNeeded && scheduler == null) if (promptType == CredentialPromptType.PromptIfNeeded && scheduler == null)
@@ -151,7 +150,6 @@ namespace GitHub.Services.Common
{ {
get get
{ {
// System.Console.WriteLine($"VssCredentials.get_PromptType");
return m_promptType; return m_promptType;
} }
set set
@@ -172,7 +170,6 @@ namespace GitHub.Services.Common
{ {
get get
{ {
// System.Console.WriteLine($"VssCredentials.get_Federated");
return m_federatedCredential; return m_federatedCredential;
} }
} }
@@ -187,7 +184,6 @@ namespace GitHub.Services.Common
{ {
get get
{ {
// System.Console.WriteLine($"VssCredentials.get_Storage");
return m_credentialStorage; return m_credentialStorage;
} }
set set
@@ -207,7 +203,6 @@ namespace GitHub.Services.Common
/// </summary> /// </summary>
internal virtual bool TryGetValidAdalToken(IVssCredentialPrompt prompt) internal virtual bool TryGetValidAdalToken(IVssCredentialPrompt prompt)
{ {
// System.Console.WriteLine($"VssCredentials.TryGetValidAdalToken");
return false; return false;
} }
@@ -223,7 +218,6 @@ namespace GitHub.Services.Common
IHttpResponse webResponse, IHttpResponse webResponse,
IssuedToken failedToken) IssuedToken failedToken)
{ {
// System.Console.WriteLine("VssCredential.CreateTokenProvider");
ArgumentUtility.CheckForNull(serverUrl, "serverUrl"); ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
IssuedTokenProvider tokenProvider = null; IssuedTokenProvider tokenProvider = null;
@@ -269,7 +263,6 @@ namespace GitHub.Services.Common
Uri serverUrl, Uri serverUrl,
out IssuedTokenProvider provider) out IssuedTokenProvider provider)
{ {
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider");
ArgumentUtility.CheckForNull(serverUrl, "serverUrl"); ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
lock (m_thisLock) lock (m_thisLock)
@@ -279,13 +272,11 @@ namespace GitHub.Services.Common
{ {
if (m_federatedCredential != null) if (m_federatedCredential != null)
{ {
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider: Using federated credential");
m_currentProvider = m_federatedCredential.CreateTokenProvider(serverUrl, null, null); m_currentProvider = m_federatedCredential.CreateTokenProvider(serverUrl, null, null);
} }
if (m_currentProvider != null) if (m_currentProvider != null)
{ {
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider: Issued token provider created");
VssHttpEventSource.Log.IssuedTokenProviderCreated(VssTraceActivity.Current, m_currentProvider); VssHttpEventSource.Log.IssuedTokenProviderCreated(VssTraceActivity.Current, m_currentProvider);
} }
} }
@@ -303,7 +294,6 @@ namespace GitHub.Services.Common
/// <returns>True if this is an token authentication redirect, false otherwise</returns> /// <returns>True if this is an token authentication redirect, false otherwise</returns>
internal bool IsAuthenticationChallenge(IHttpResponse webResponse) internal bool IsAuthenticationChallenge(IHttpResponse webResponse)
{ {
// System.Console.WriteLine($"VssCredentials.IsAuthenticationChallenge");
if (webResponse == null) if (webResponse == null)
{ {
return false; return false;
@@ -323,7 +313,6 @@ namespace GitHub.Services.Common
Uri serviceLocation, Uri serviceLocation,
string identityProvider) string identityProvider)
{ {
// System.Console.WriteLine($"VssCredentials.SignOut");
// Remove the token in the storage and the current token provider. Note that we don't // Remove the token in the storage and the current token provider. Note that we don't
// call InvalidateToken here because we want to remove the whole token not just its value // call InvalidateToken here because we want to remove the whole token not just its value
if ((m_currentProvider != null) && (m_currentProvider.CurrentToken != null)) if ((m_currentProvider != null) && (m_currentProvider.CurrentToken != null))
@@ -360,7 +349,6 @@ namespace GitHub.Services.Common
string token, string token,
IDictionary<string, string> attributes) IDictionary<string, string> attributes)
{ {
// System.Console.WriteLine($"VssCredentials.WriteAuthorizationToken");
int i = 0; int i = 0;
for (int j = 0; j < token.Length; i++, j += 128) for (int j = 0; j < token.Length; i++, j += 128)
{ {
@@ -372,7 +360,6 @@ namespace GitHub.Services.Common
protected static string ReadAuthorizationToken(IDictionary<string, string> attributes) protected static string ReadAuthorizationToken(IDictionary<string, string> attributes)
{ {
// System.Console.WriteLine($"VssCredentials.ReadAuthorizationToken");
string authTokenCountValue; string authTokenCountValue;
if (attributes.TryGetValue("AuthTokenSegmentCount", out authTokenCountValue)) if (attributes.TryGetValue("AuthTokenSegmentCount", out authTokenCountValue))
{ {

View File

@@ -23,7 +23,6 @@ namespace GitHub.Services.Common.ClientStorage
private readonly string m_filePath; private readonly string m_filePath;
private readonly VssFileStorageReader m_reader; private readonly VssFileStorageReader m_reader;
private readonly IVssClientStorageWriter m_writer; private readonly IVssClientStorageWriter m_writer;
private const char c_defaultPathSeparator = '\\'; private const char c_defaultPathSeparator = '\\';
private const bool c_defaultIgnoreCaseInPaths = false; private const bool c_defaultIgnoreCaseInPaths = false;
@@ -192,7 +191,7 @@ namespace GitHub.Services.Common.ClientStorage
// Windows Impersonation is being used. // Windows Impersonation is being used.
// Check to see if we can find the user's local application data directory. // Check to see if we can find the user's local application data directory.
string subDir = "GitHub\\ActionsService"; string subDir = Path.Combine("GitHub", "ActionsService");
string path = Environment.GetEnvironmentVariable("localappdata"); string path = Environment.GetEnvironmentVariable("localappdata");
SafeGetFolderPath(Environment.SpecialFolder.LocalApplicationData); SafeGetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))

View File

@@ -0,0 +1,41 @@
using System;
using System.ComponentModel;
using System.Threading.Tasks;
namespace GitHub.Services.Common
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static class RetriesHelper<T>
{
public static async Task<T> RetryWithTimeoutAsync(
Func<Task<T>> retriableAction,
TimeSpan minBackoff,
TimeSpan maxBackoff,
int maxTimeoutMinutes = 5
)
{
var remainingTime = TimeSpan.FromMinutes(maxTimeoutMinutes);
while (true)
{
try
{
return await retriableAction();
}
catch
{
if (remainingTime > TimeSpan.Zero)
{
var backOff = BackoffTimerHelper.GetRandomBackoff(minBackoff, maxBackoff);
remainingTime -= backOff;
await Task.Delay(backOff);
}
else
{
throw;
}
}
}
}
}
}

View File

@@ -49,7 +49,6 @@ namespace GitHub.Services.Common
VssHttpRequestSettings settings, VssHttpRequestSettings settings,
HttpMessageHandler innerHandler) HttpMessageHandler innerHandler)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.ctor");
this.Credentials = credentials; this.Credentials = credentials;
this.Settings = settings; this.Settings = settings;
this.ExpectContinue = settings.ExpectContinue; this.ExpectContinue = settings.ExpectContinue;
@@ -123,7 +122,6 @@ namespace GitHub.Services.Common
HttpRequestMessage request, HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync");
VssTraceActivity traceActivity = VssTraceActivity.Current; VssTraceActivity traceActivity = VssTraceActivity.Current;
var traceInfo = VssHttpMessageHandlerTraceInfo.GetTraceInfo(request); var traceInfo = VssHttpMessageHandlerTraceInfo.GetTraceInfo(request);
@@ -132,7 +130,6 @@ namespace GitHub.Services.Common
if (!m_appliedClientCertificatesToTransportHandler && if (!m_appliedClientCertificatesToTransportHandler &&
request.RequestUri.Scheme == "https") request.RequestUri.Scheme == "https")
{ {
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: !appliedClientCertificatesToTransportHandler");
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
if (httpClientHandler != null && if (httpClientHandler != null &&
this.Settings.ClientCertificateManager != null && this.Settings.ClientCertificateManager != null &&
@@ -147,7 +144,6 @@ namespace GitHub.Services.Common
if (!m_appliedServerCertificateValidationCallbackToTransportHandler && if (!m_appliedServerCertificateValidationCallbackToTransportHandler &&
request.RequestUri.Scheme == "https") request.RequestUri.Scheme == "https")
{ {
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: !appliedServerCertificateValidationCallbackToTransportHandler");
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
if (httpClientHandler != null && if (httpClientHandler != null &&
this.Settings.ServerCertificateValidationCallback != null) this.Settings.ServerCertificateValidationCallback != null)
@@ -169,7 +165,6 @@ namespace GitHub.Services.Common
IssuedTokenProvider provider; IssuedTokenProvider provider;
if (this.Credentials.TryGetTokenProvider(request.RequestUri, out provider)) if (this.Credentials.TryGetTokenProvider(request.RequestUri, out provider))
{ {
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: Got token provider from credentials");
token = provider.CurrentToken; token = provider.CurrentToken;
} }
@@ -230,7 +225,6 @@ namespace GitHub.Services.Common
traceInfo?.TraceResponseContentTime(); traceInfo?.TraceResponseContentTime();
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Creating response wrapper");
responseWrapper = new HttpResponseMessageWrapper(response); responseWrapper = new HttpResponseMessageWrapper(response);
if (!this.Credentials.IsAuthenticationChallenge(responseWrapper)) if (!this.Credentials.IsAuthenticationChallenge(responseWrapper))
@@ -238,7 +232,6 @@ namespace GitHub.Services.Common
// Validate the token after it has been successfully authenticated with the server. // Validate the token after it has been successfully authenticated with the server.
if (provider != null) if (provider != null)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: Validating token");
provider.ValidateToken(token, responseWrapper); provider.ValidateToken(token, responseWrapper);
} }
@@ -250,7 +243,6 @@ namespace GitHub.Services.Common
} }
else else
{ {
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Auth challenge. Response status code {response.StatusCode}; headers {response.Headers}");
// In the case of a Windows token, only apply it to the web proxy if it // In the case of a Windows token, only apply it to the web proxy if it
// returned a 407 Proxy Authentication Required. If we didn't get this // returned a 407 Proxy Authentication Required. If we didn't get this
// status code back, then the proxy (if there is one) is clearly working fine, // status code back, then the proxy (if there is one) is clearly working fine,
@@ -296,7 +288,6 @@ namespace GitHub.Services.Common
} }
// Now invoke the provider and await the result // Now invoke the provider and await the result
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Calling GetTokenAsync");
token = await provider.GetTokenAsync(token, tokenSource.Token).ConfigureAwait(false); token = await provider.GetTokenAsync(token, tokenSource.Token).ConfigureAwait(false);
// I always see 0 here, but the method above could take more time so keep for now // I always see 0 here, but the method above could take more time so keep for now
@@ -441,7 +432,6 @@ namespace GitHub.Services.Common
activity != VssTraceActivity.Empty && activity != VssTraceActivity.Empty &&
!request.Headers.Contains(HttpHeaders.TfsSessionHeader)) !request.Headers.Contains(HttpHeaders.TfsSessionHeader))
{ {
// System.Console.WriteLine($"VssHttpMessageHandler.ApplyHeaders: Activity ID {activity.Id}");
request.Headers.Add(HttpHeaders.TfsSessionHeader, activity.Id.ToString("D")); request.Headers.Add(HttpHeaders.TfsSessionHeader, activity.Id.ToString("D"));
} }
@@ -462,16 +452,13 @@ namespace GitHub.Services.Common
ICredentials credentialsToken = token as ICredentials; ICredentials credentialsToken = token as ICredentials;
if (credentialsToken != null) if (credentialsToken != null)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Credentials token != null");
if (applyICredentialsToWebProxy) if (applyICredentialsToWebProxy)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Apply credentials to web proxy");
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
if (httpClientHandler != null && if (httpClientHandler != null &&
httpClientHandler.Proxy != null) httpClientHandler.Proxy != null)
{ {
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Setting proxy crednetials");
httpClientHandler.Proxy.Credentials = credentialsToken; httpClientHandler.Proxy.Credentials = credentialsToken;
} }
} }
@@ -480,7 +467,6 @@ namespace GitHub.Services.Common
} }
else else
{ {
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Applying credentials to request");
token.ApplyTo(new HttpRequestMessageWrapper(request)); token.ApplyTo(new HttpRequestMessageWrapper(request));
} }
} }
@@ -493,8 +479,7 @@ namespace GitHub.Services.Common
HttpClientHandler httpClientHandler = handler as HttpClientHandler; HttpClientHandler httpClientHandler = handler as HttpClientHandler;
if (httpClientHandler != null) if (httpClientHandler != null)
{ {
// System.Console.WriteLine($"VssHttpMessageHandler.ApplySettings: Default credentials = {defaultCredentials} AllowAutoRedirect = {settings.AllowAutoRedirect}"); httpClientHandler.AllowAutoRedirect = settings.AllowAutoRedirect;
httpClientHandler.AllowAutoRedirect = true; //settings.AllowAutoRedirect;
httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual; httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
//Setting httpClientHandler.UseDefaultCredentials to false in .Net Core, clears httpClientHandler.Credentials if //Setting httpClientHandler.UseDefaultCredentials to false in .Net Core, clears httpClientHandler.Credentials if
//credentials is already set to defaultcredentials. Therefore httpClientHandler.Credentials must be //credentials is already set to defaultcredentials. Therefore httpClientHandler.Credentials must be
@@ -565,7 +550,6 @@ namespace GitHub.Services.Common
Uri uri, Uri uri,
String authType) String authType)
{ {
// System.Console.WriteLine($"CredentialWrapper.GetCredential: InnerCredentials = {InnerCredentials}");
return InnerCredentials != null ? InnerCredentials.GetCredential(uri, authType) : null; return InnerCredentials != null ? InnerCredentials.GetCredential(uri, authType) : null;
} }
} }

View File

@@ -27,7 +27,6 @@ using System.Net.Http.Headers;
using System.Net.Http.Formatting; using System.Net.Http.Formatting;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.Pipelines;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
@@ -379,7 +378,6 @@ namespace GitHub.DistributedTask.WebApi
/// <param name="requestId"></param> /// <param name="requestId"></param>
/// <param name="lockToken"></param> /// <param name="lockToken"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="targetHostId"></param>
/// <param name="userState"></param> /// <param name="userState"></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
@@ -388,7 +386,6 @@ namespace GitHub.DistributedTask.WebApi
long requestId, long requestId,
Guid lockToken, Guid lockToken,
TaskAgentJobRequest request, TaskAgentJobRequest request,
Guid targetHostId,
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -399,7 +396,6 @@ namespace GitHub.DistributedTask.WebApi
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
queryParams.Add("lockToken", lockToken.ToString()); queryParams.Add("lockToken", lockToken.ToString());
queryParams.Add("targetHostId", targetHostId.ToString());
return SendAsync<TaskAgentJobRequest>( return SendAsync<TaskAgentJobRequest>(
httpMethod, httpMethod,
@@ -707,47 +703,6 @@ namespace GitHub.DistributedTask.WebApi
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
} }
/// <summary>
/// [Preview API]
/// </summary>
/// <param name="scopeId"></param>
/// <param name="planType"></param>
/// <param name="planGroup"></param>
/// <param name="planId"></param>
/// <param name="instanceRefsJson"></param>
/// <param name="userState"></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Task<Pipelines.AgentJobRequestMessage> GetJobMessageAsync(
Guid scopeId,
Guid hostId,
string planType,
string planGroup,
Guid planId,
string instanceRefsJson,
object userState = null,
CancellationToken cancellationToken = default)
{
HttpMethod httpMethod = new HttpMethod("GET");
Guid locationId = new Guid("25adab70-1379-4186-be8e-b643061ebe3a");
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
queryParams.Add("scopeId", scopeId.ToString());
queryParams.Add("hostId", hostId.ToString());
queryParams.Add("planType", planType);
queryParams.Add("planGroup", planGroup);
queryParams.Add("planId", planId.ToString());
queryParams.Add("instanceRefsJson", instanceRefsJson);
return SendAsync<Pipelines.AgentJobRequestMessage>(
httpMethod,
locationId,
version: new ApiResourceVersion(6.0, 1),
queryParameters: queryParams,
userState: userState,
cancellationToken: cancellationToken);
}
/// <summary> /// <summary>
/// [Preview API] /// [Preview API]
/// </summary> /// </summary>
@@ -762,7 +717,6 @@ namespace GitHub.DistributedTask.WebApi
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
// System.Console.WriteLine("TaskAgentHttpClientBase.CreateAgentSessionAsync");
HttpMethod httpMethod = new HttpMethod("POST"); HttpMethod httpMethod = new HttpMethod("POST");
Guid locationId = new Guid("134e239e-2df3-4794-a6f6-24f1f19ec8dc"); Guid locationId = new Guid("134e239e-2df3-4794-a6f6-24f1f19ec8dc");
object routeValues = new { poolId = poolId }; object routeValues = new { poolId = poolId };

View File

@@ -0,0 +1,39 @@
using System;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.Pipelines
{
[DataContract]
public sealed class HostedRunnerShutdownMessage
{
public static readonly String MessageType = "RunnerShutdown";
[JsonConstructor]
internal HostedRunnerShutdownMessage()
{
}
public HostedRunnerShutdownMessage(String reason)
{
this.Reason = reason;
}
[DataMember]
public String Reason
{
get;
private set;
}
public WebApi.TaskAgentMessage GetAgentMessage()
{
return new WebApi.TaskAgentMessage
{
Body = JsonUtility.ToString(this),
MessageType = HostedRunnerShutdownMessage.MessageType,
};
}
}
}

View File

@@ -64,7 +64,6 @@ namespace GitHub.DistributedTask.WebApi
Guid lockToken, Guid lockToken,
DateTime finishTime, DateTime finishTime,
TaskResult result, TaskResult result,
Guid targetHostId,
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
@@ -75,7 +74,7 @@ namespace GitHub.DistributedTask.WebApi
Result = result, Result = result,
}; };
return UpdateAgentRequestAsync(poolId, requestId, lockToken, request, targetHostId, userState, cancellationToken); return UpdateAgentRequestAsync(poolId, requestId, lockToken, request, userState, cancellationToken);
} }
public Task<List<TaskAgent>> GetAgentsAsync( public Task<List<TaskAgent>> GetAgentsAsync(
@@ -142,6 +141,24 @@ namespace GitHub.DistributedTask.WebApi
return ReplaceAgentAsync(poolId, agent.Id, agent, userState, cancellationToken); return ReplaceAgentAsync(poolId, agent.Id, agent, userState, cancellationToken);
} }
public Task<Pipelines.AgentJobRequestMessage> GetJobMessageAsync(
string messageId,
object userState = null,
CancellationToken cancellationToken = default)
{
HttpMethod httpMethod = new HttpMethod("GET");
Guid locationId = new Guid("25adab70-1379-4186-be8e-b643061ebe3a");
object routeValues = new { messageId = messageId };
return SendAsync<Pipelines.AgentJobRequestMessage>(
httpMethod,
locationId,
routeValues: routeValues,
version: new ApiResourceVersion(6.0, 1),
userState: userState,
cancellationToken: cancellationToken);
}
protected Task<T> SendAsync<T>( protected Task<T> SendAsync<T>(
HttpMethod method, HttpMethod method,
Guid locationId, Guid locationId,
@@ -153,7 +170,6 @@ namespace GitHub.DistributedTask.WebApi
CancellationToken cancellationToken = default(CancellationToken), CancellationToken cancellationToken = default(CancellationToken),
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null) Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
{ {
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 1");
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, processResponse); return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, processResponse);
} }
@@ -172,7 +188,6 @@ namespace GitHub.DistributedTask.WebApi
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
{ {
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 2");
return await SendAsync<T>(requestMessage, userState, cancellationToken, processResponse).ConfigureAwait(false); return await SendAsync<T>(requestMessage, userState, cancellationToken, processResponse).ConfigureAwait(false);
} }
} }
@@ -183,7 +198,6 @@ namespace GitHub.DistributedTask.WebApi
CancellationToken cancellationToken = default(CancellationToken), CancellationToken cancellationToken = default(CancellationToken),
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null) Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
{ {
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 3");
if (processResponse == null) if (processResponse == null)
{ {
processResponse = ReadContentAsAsync<T>; processResponse = ReadContentAsAsync<T>;

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>

View File

@@ -801,7 +801,6 @@ namespace GitHub.Services.WebApi.Location
private async Task<ConnectionData> GetConnectionDataAsync(ConnectOptions connectOptions, int lastChangeId, CancellationToken cancellationToken) private async Task<ConnectionData> GetConnectionDataAsync(ConnectOptions connectOptions, int lastChangeId, CancellationToken cancellationToken)
{ {
// System.Console.WriteLine("ServerDataProvider.GetConnectionDataAsync");
int timeoutRetries = 1; int timeoutRetries = 1;
while (true) while (true)

View File

@@ -75,7 +75,6 @@ namespace GitHub.Services.OAuth
internal override void ApplyTo(IHttpRequest request) internal override void ApplyTo(IHttpRequest request)
{ {
// System.Console.WriteLine($"VssOAuthAccessToken.ApplyTo: Bearer {m_value}");
request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {m_value}"); request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {m_value}");
} }

View File

@@ -60,7 +60,6 @@ namespace GitHub.Services.OAuth
Uri serverUrl, Uri serverUrl,
IHttpResponse response) IHttpResponse response)
{ {
// System.Console.WriteLine($"VssOAuthAccessTokenCredential.OnCreateTokenProvider");
return new VssOAuthAccessTokenProvider(this, serverUrl, null); return new VssOAuthAccessTokenProvider(this, serverUrl, null);
} }
@@ -72,7 +71,6 @@ namespace GitHub.Services.OAuth
Uri signInUrl) Uri signInUrl)
: base(credential, serverUrl, signInUrl) : base(credential, serverUrl, signInUrl)
{ {
// System.Console.WriteLine($"VssOAuthAccessTokenProvider.ctor");
} }
public override Boolean GetTokenIsInteractive public override Boolean GetTokenIsInteractive

View File

@@ -103,23 +103,17 @@ namespace GitHub.Services.OAuth
/// <returns>True if the web response indicates an authorization challenge; otherwise, false</returns> /// <returns>True if the web response indicates an authorization challenge; otherwise, false</returns>
public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse) public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse)
{ {
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge");
if (webResponse == null) if (webResponse == null)
{ {
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: webResponse is null");
return false; return false;
} }
if (webResponse.StatusCode == HttpStatusCode.Found || if (webResponse.StatusCode == HttpStatusCode.Found ||
webResponse.StatusCode == HttpStatusCode.Unauthorized) webResponse.StatusCode == HttpStatusCode.Unauthorized)
{ {
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: found or unauthorized"); return webResponse.Headers.GetValues(Common.Internal.HttpHeaders.WwwAuthenticate).Any(x => x.IndexOf("Bearer", StringComparison.OrdinalIgnoreCase) >= 0);
var result = webResponse.Headers.GetValues(Common.Internal.HttpHeaders.WwwAuthenticate).Any(x => x.IndexOf("Bearer", StringComparison.OrdinalIgnoreCase) >= 0);
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: {result}");
return result;
} }
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: false");
return false; return false;
} }
@@ -127,7 +121,6 @@ namespace GitHub.Services.OAuth
Uri serverUrl, Uri serverUrl,
IHttpResponse response) IHttpResponse response)
{ {
// System.Console.WriteLine($"VssOAuthCredential.OnCreateTokenProvider");
return new VssOAuthTokenProvider(this, serverUrl); return new VssOAuthTokenProvider(this, serverUrl);
} }

View File

@@ -54,7 +54,6 @@ namespace GitHub.Services.OAuth
VssOAuthTokenParameters tokenParameters = null, VssOAuthTokenParameters tokenParameters = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// todo: qqq
VssTraceActivity traceActivity = VssTraceActivity.Current; VssTraceActivity traceActivity = VssTraceActivity.Current;
using (HttpClient client = new HttpClient(CreateMessageHandler(this.AuthorizationUrl))) using (HttpClient client = new HttpClient(CreateMessageHandler(this.AuthorizationUrl)))
{ {

View File

@@ -47,7 +47,6 @@ namespace GitHub.Services.OAuth
VssOAuthTokenParameters tokenParameters) VssOAuthTokenParameters tokenParameters)
: base(credential, serverUrl, authorizationUrl) : base(credential, serverUrl, authorizationUrl)
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.ctor");
m_grant = grant; m_grant = grant;
m_tokenParameters = tokenParameters; m_tokenParameters = tokenParameters;
m_clientCredential = clientCrential; m_clientCredential = clientCrential;
@@ -60,7 +59,6 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_Grant");
return m_grant; return m_grant;
} }
} }
@@ -72,7 +70,6 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_ClientCredential");
return m_clientCredential; return m_clientCredential;
} }
} }
@@ -84,7 +81,6 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_TokenParameters");
return m_tokenParameters; return m_tokenParameters;
} }
} }
@@ -96,7 +92,6 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_GetTokenIsInteractive");
return false; return false;
} }
} }
@@ -105,7 +100,6 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_AuthenticationParameter");
if (this.ClientCredential == null) if (this.ClientCredential == null)
{ {
return null; return null;
@@ -121,14 +115,12 @@ namespace GitHub.Services.OAuth
{ {
get get
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.get_AuthenticationScheme");
return "Bearer"; return "Bearer";
} }
} }
public async Task<string> ValidateCredentialAsync(CancellationToken cancellationToken) public async Task<string> ValidateCredentialAsync(CancellationToken cancellationToken)
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.ValidateCredentialAsync: Calling VssOAuthTokenHttpClient.GetTokenAsync");
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl); var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken); var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken);
@@ -147,7 +139,6 @@ namespace GitHub.Services.OAuth
IssuedToken failedToken, IssuedToken failedToken,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.OnGetTokenAsync");
if (this.SignInUrl == null || if (this.SignInUrl == null ||
this.Grant == null || this.Grant == null ||
this.ClientCredential == null) this.ClientCredential == null)
@@ -160,7 +151,6 @@ namespace GitHub.Services.OAuth
try try
{ {
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl); var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
// System.Console.WriteLine($"VssOAuthTokenProvider.OnGetTokenAsync: Calling VssOAuthTokenHttpClient.GetTokenAsync; sign-in url {this.SignInUrl.AbsoluteUri}");
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken).ConfigureAwait(false); var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken).ConfigureAwait(false);
if (!String.IsNullOrEmpty(tokenResponse.AccessToken)) if (!String.IsNullOrEmpty(tokenResponse.AccessToken))
{ {
@@ -207,7 +197,6 @@ namespace GitHub.Services.OAuth
protected virtual IssuedToken CreateIssuedToken(VssOAuthTokenResponse tokenResponse) protected virtual IssuedToken CreateIssuedToken(VssOAuthTokenResponse tokenResponse)
{ {
// System.Console.WriteLine($"VssOAuthTokenProvider.CreateIssuedToken");
if (tokenResponse.ExpiresIn > 0) if (tokenResponse.ExpiresIn > 0)
{ {
return new VssOAuthAccessToken(tokenResponse.AccessToken, DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn)); return new VssOAuthAccessToken(tokenResponse.AccessToken, DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn));

View File

@@ -100,7 +100,6 @@ namespace GitHub.Services.WebApi
IDictionary<String, String> parameters, IDictionary<String, String> parameters,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssConnection.ConnectAsync");
CheckForDisposed(); CheckForDisposed();
// Set the connectMode on the credential's FederatedPrompt // Set the connectMode on the credential's FederatedPrompt
if (Credentials.Federated != null && Credentials.Federated.Prompt != null) if (Credentials.Federated != null && Credentials.Federated.Prompt != null)

View File

@@ -390,7 +390,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 1");
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken); return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken);
} }
@@ -405,7 +404,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 2");
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
{ {
@@ -424,7 +422,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 3");
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
{ {
@@ -458,7 +455,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 4");
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
{ {
@@ -477,7 +473,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 5");
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
{ {
@@ -506,7 +501,6 @@ namespace GitHub.Services.WebApi
CancellationToken cancellationToken = default(CancellationToken), CancellationToken cancellationToken = default(CancellationToken),
String mediaType = c_jsonMediaType) String mediaType = c_jsonMediaType)
{ {
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 1");
return CreateRequestMessageAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, mediaType); return CreateRequestMessageAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, mediaType);
} }
@@ -532,7 +526,6 @@ namespace GitHub.Services.WebApi
CancellationToken cancellationToken = default(CancellationToken), CancellationToken cancellationToken = default(CancellationToken),
String mediaType = c_jsonMediaType) String mediaType = c_jsonMediaType)
{ {
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 2");
// Lookup the location // Lookup the location
ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false); ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false);
if (location == null) if (location == null)
@@ -562,7 +555,6 @@ namespace GitHub.Services.WebApi
IEnumerable<KeyValuePair<String, String>> queryParameters = null, IEnumerable<KeyValuePair<String, String>> queryParameters = null,
String mediaType = c_jsonMediaType) String mediaType = c_jsonMediaType)
{ {
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 3");
return CreateRequestMessage(method, null, location, routeValues, version, content, queryParameters, mediaType); return CreateRequestMessage(method, null, location, routeValues, version, content, queryParameters, mediaType);
} }
@@ -586,7 +578,6 @@ namespace GitHub.Services.WebApi
IEnumerable<KeyValuePair<String, String>> queryParameters = null, IEnumerable<KeyValuePair<String, String>> queryParameters = null,
String mediaType = c_jsonMediaType) String mediaType = c_jsonMediaType)
{ {
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 4");
CheckForDisposed(); CheckForDisposed();
// Negotiate the request version to send // Negotiate the request version to send
ApiResourceVersion requestVersion = NegotiateRequestVersion(location, version); ApiResourceVersion requestVersion = NegotiateRequestVersion(location, version);
@@ -758,14 +749,12 @@ namespace GitHub.Services.WebApi
//from deadlocking... //from deadlocking...
using (HttpResponseMessage response = await this.SendAsync(message, userState, cancellationToken).ConfigureAwait(false)) using (HttpResponseMessage response = await this.SendAsync(message, userState, cancellationToken).ConfigureAwait(false))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 6");
return await ReadContentAsAsync<T>(response, cancellationToken).ConfigureAwait(false); return await ReadContentAsAsync<T>(response, cancellationToken).ConfigureAwait(false);
} }
} }
protected async Task<T> ReadContentAsAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken)) protected async Task<T> ReadContentAsAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine($"VssHttpClientBase.ReadContentAsAsync {response.Headers}");
CheckForDisposed(); CheckForDisposed();
Boolean isJson = IsJsonResponse(response); Boolean isJson = IsJsonResponse(response);
bool mismatchContentType = false; bool mismatchContentType = false;
@@ -777,20 +766,17 @@ namespace GitHub.Services.WebApi
!typeof(Byte[]).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) && !typeof(Byte[]).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) &&
!typeof(JObject).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())) !typeof(JObject).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()))
{ {
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: isJson 1");
// expect it to come back wrapped, if it isn't it is a bug! // expect it to come back wrapped, if it isn't it is a bug!
var wrapper = await ReadJsonContentAsync<VssJsonCollectionWrapper<T>>(response, cancellationToken).ConfigureAwait(false); var wrapper = await ReadJsonContentAsync<VssJsonCollectionWrapper<T>>(response, cancellationToken).ConfigureAwait(false);
return wrapper.Value; return wrapper.Value;
} }
else if (isJson) else if (isJson)
{ {
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: isJson 2");
return await ReadJsonContentAsync<T>(response, cancellationToken).ConfigureAwait(false); return await ReadJsonContentAsync<T>(response, cancellationToken).ConfigureAwait(false);
} }
} }
catch (JsonReaderException) catch (JsonReaderException)
{ {
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: mismatchContentType");
// We thought the content was JSON but failed to parse. // We thought the content was JSON but failed to parse.
// In this case, do nothing and utilize the HandleUnknownContentType call below // In this case, do nothing and utilize the HandleUnknownContentType call below
mismatchContentType = true; mismatchContentType = true;
@@ -816,7 +802,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 7");
// the default in httpClient for HttpCompletionOption is ResponseContentRead so that is what we do here // the default in httpClient for HttpCompletionOption is ResponseContentRead so that is what we do here
return this.SendAsync( return this.SendAsync(
message, message,
@@ -831,7 +816,6 @@ namespace GitHub.Services.WebApi
Object userState = null, Object userState = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
// System.Console.WriteLine("VssHttpClientBase.SendAsync 8");
CheckForDisposed(); CheckForDisposed();
if (message.Headers.UserAgent != null) if (message.Headers.UserAgent != null)
{ {
@@ -867,7 +851,6 @@ namespace GitHub.Services.WebApi
//ConfigureAwait(false) enables the continuation to be run outside //ConfigureAwait(false) enables the continuation to be run outside
//any captured SyncronizationContext (such as ASP.NET's) which keeps things //any captured SyncronizationContext (such as ASP.NET's) which keeps things
//from deadlocking... //from deadlocking...
// System.Console.WriteLine($"VssHttpClientBase.SendAsync 8: Calling Client.SendAsync {message}");
HttpResponseMessage response = await Client.SendAsync(message, completionOption, cancellationToken).ConfigureAwait(false); HttpResponseMessage response = await Client.SendAsync(message, completionOption, cancellationToken).ConfigureAwait(false);
// Inject delay or failure for testing // Inject delay or failure for testing
@@ -885,7 +868,6 @@ namespace GitHub.Services.WebApi
[Obsolete("Use VssHttpClientBase.HandleResponseAsync instead")] [Obsolete("Use VssHttpClientBase.HandleResponseAsync instead")]
protected virtual void HandleResponse(HttpResponseMessage response) protected virtual void HandleResponse(HttpResponseMessage response)
{ {
// System.Console.WriteLine("VssHttpClientBase.HandleResponse 1");
} }
@@ -893,7 +875,6 @@ namespace GitHub.Services.WebApi
HttpResponseMessage response, HttpResponseMessage response,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// System.Console.WriteLine($"VssHttpClientBase.HandleResponse 2 status code {response.StatusCode} headers {response.Headers}");
response.Trace(); response.Trace();
VssHttpEventSource.Log.HttpRequestStop(VssTraceActivity.Current, response); VssHttpEventSource.Log.HttpRequestStop(VssTraceActivity.Current, response);
@@ -905,7 +886,6 @@ namespace GitHub.Services.WebApi
} }
else if (ShouldThrowError(response)) else if (ShouldThrowError(response))
{ {
// System.Console.WriteLine("VssHttpClientBase.HandleResponse: Should throw error");
Exception exToThrow = null; Exception exToThrow = null;
if (IsJsonResponse(response)) if (IsJsonResponse(response))
{ {
@@ -929,7 +909,6 @@ namespace GitHub.Services.WebApi
{ {
message = response.ReasonPhrase; message = response.ReasonPhrase;
} }
// System.Console.WriteLine($"VssHttpClientBase.HandleResponse: Exception message {message}");
exToThrow = new VssServiceResponseException(response.StatusCode, message, exToThrow); exToThrow = new VssServiceResponseException(response.StatusCode, message, exToThrow);
} }

View File

@@ -19,7 +19,8 @@ namespace GitHub.Runner.Common.Tests
"linux-x64", "linux-x64",
"linux-arm", "linux-arm",
"linux-arm64", "linux-arm64",
"osx-x64" "osx-x64",
"osx-arm64"
}; };
Assert.True(BuildConstants.Source.CommitHash.Length == 40, $"CommitHash should be SHA-1 hash {BuildConstants.Source.CommitHash}"); Assert.True(BuildConstants.Source.CommitHash.Length == 40, $"CommitHash should be SHA-1 hash {BuildConstants.Source.CommitHash}");

View File

@@ -708,33 +708,85 @@ namespace GitHub.Runner.Common.Tests
} }
} }
[Fact] [Theory]
[InlineData("configure", "once")]
[InlineData("remove", "disableupdate")]
[InlineData("remove", "ephemeral")]
[InlineData("remove", "once")]
[InlineData("remove", "replace")]
[InlineData("remove", "runasservice")]
[InlineData("remove", "unattended")]
[InlineData("run", "disableupdate")]
[InlineData("run", "ephemeral")]
[InlineData("run", "replace")]
[InlineData("run", "runasservice")]
[InlineData("run", "unattended")]
[InlineData("warmup", "disableupdate")]
[InlineData("warmup", "ephemeral")]
[InlineData("warmup", "once")]
[InlineData("warmup", "replace")]
[InlineData("warmup", "runasservice")]
[InlineData("warmup", "unattended")]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", nameof(CommandSettings))] [Trait("Category", nameof(CommandSettings))]
public void ValidateFlags() public void ValidateInvalidFlagCommandCombination(string validCommand, string flag)
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext hc = CreateTestContext())
{ {
// Arrange. // Arrange.
var command = new CommandSettings(hc, args: new string[] { "--badflag" }); var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{flag}" });
// Assert. // Assert.
Assert.Contains("badflag", command.Validate()); Assert.Contains(flag, command.Validate());
} }
} }
[Fact] [Theory]
[InlineData("remove", "auth", "bar arg value")]
[InlineData("remove", "labels", "bar arg value")]
[InlineData("remove", "monitorsocketaddress", "bar arg value")]
[InlineData("remove", "name", "bar arg value")]
[InlineData("remove", "runnergroup", "bar arg value")]
[InlineData("remove", "url", "bar arg value")]
[InlineData("remove", "username", "bar arg value")]
[InlineData("remove", "windowslogonaccount", "bar arg value")]
[InlineData("remove", "windowslogonpassword", "bar arg value")]
[InlineData("remove", "work", "bar arg value")]
[InlineData("run", "auth", "bad arg value")]
[InlineData("run", "labels", "bad arg value")]
[InlineData("run", "monitorsocketaddress", "bad arg value")]
[InlineData("run", "name", "bad arg value")]
[InlineData("run", "pat", "bad arg value")]
[InlineData("run", "runnergroup", "bad arg value")]
[InlineData("run", "token", "bad arg value")]
[InlineData("run", "url", "bad arg value")]
[InlineData("run", "username", "bad arg value")]
[InlineData("run", "windowslogonaccount", "bad arg value")]
[InlineData("run", "windowslogonpassword", "bad arg value")]
[InlineData("run", "work", "bad arg value")]
[InlineData("warmup", "auth", "bad arg value")]
[InlineData("warmup", "labels", "bad arg value")]
[InlineData("warmup", "monitorsocketaddress", "bad arg value")]
[InlineData("warmup", "name", "bad arg value")]
[InlineData("warmup", "pat", "bad arg value")]
[InlineData("warmup", "runnergroup", "bad arg value")]
[InlineData("warmup", "token", "bad arg value")]
[InlineData("warmup", "url", "bad arg value")]
[InlineData("warmup", "username", "bad arg value")]
[InlineData("warmup", "windowslogonaccount", "bad arg value")]
[InlineData("warmup", "windowslogonpassword", "bad arg value")]
[InlineData("warmup", "work", "bad arg value")]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", nameof(CommandSettings))] [Trait("Category", nameof(CommandSettings))]
public void ValidateArgs() public void ValidateInvalidArgCommandCombination(string validCommand, string arg, string argValue)
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext hc = CreateTestContext())
{ {
// Arrange. // Arrange.
var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" }); var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{arg}", argValue });
// Assert. // Assert.
Assert.Contains("badargname", command.Validate()); Assert.Contains(arg, command.Validate());
} }
} }
@@ -758,6 +810,73 @@ namespace GitHub.Runner.Common.Tests
} }
} }
[Theory]
[InlineData("configure", "help")]
[InlineData("configure", "version")]
[InlineData("configure", "commit")]
[InlineData("configure", "check")]
[InlineData("configure", "disableupdate")]
[InlineData("configure", "ephemeral")]
[InlineData("configure", "replace")]
[InlineData("configure", "runasservice")]
[InlineData("configure", "unattended")]
[InlineData("remove", "help")]
[InlineData("remove", "version")]
[InlineData("remove", "commit")]
[InlineData("remove", "check")]
[InlineData("run", "help")]
[InlineData("run", "version")]
[InlineData("run", "commit")]
[InlineData("run", "check")]
[InlineData("run", "once")]
[InlineData("warmup", "help")]
[InlineData("warmup", "version")]
[InlineData("warmup", "commit")]
[InlineData("warmup", "check")]
[Trait("Level", "L0")]
[Trait("Category", nameof(CommandSettings))]
public void ValidateGoodFlagCommandCombination(string validCommand, string flag)
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange.
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{flag}" });
// Assert.
Assert.True(command.Validate().Count == 0);
}
}
[Theory]
[InlineData("configure", "auth", "good arg value")]
[InlineData("configure", "labels", "good arg value")]
[InlineData("configure", "monitorsocketaddress", "good arg value")]
[InlineData("configure", "name", "good arg value")]
[InlineData("configure", "pat", "good arg value")]
[InlineData("configure", "runnergroup", "good arg value")]
[InlineData("configure", "token", "good arg value")]
[InlineData("configure", "url", "good arg value")]
[InlineData("configure", "username", "good arg value")]
[InlineData("configure", "windowslogonaccount", "good arg value")]
[InlineData("configure", "windowslogonpassword", "good arg value")]
[InlineData("configure", "work", "good arg value")]
[InlineData("remove", "token", "good arg value")]
[InlineData("remove", "pat", "good arg value")]
[InlineData("run", "startuptype", "good arg value")]
[Trait("Level", "L0")]
[Trait("Category", nameof(CommandSettings))]
public void ValidateGoodArgCommandCombination(string validCommand, string arg, string argValue)
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange.
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{arg}", argValue });
// Assert.
Assert.True(command.Validate().Count == 0);
}
}
private TestHostContext CreateTestContext([CallerMemberName] string testName = "") private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
{ {
TestHostContext hc = new TestHostContext(this, testName); TestHostContext hc = new TestHostContext(this, testName);

View File

@@ -1,4 +1,5 @@
using System; #if !(OS_OSX && ARM64)
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -50,9 +51,9 @@ namespace GitHub.Runner.Common.Tests.Listener
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://github.com/actions/runner/releases/latest")); var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://github.com/actions/runner/releases/latest"));
if (response.StatusCode == System.Net.HttpStatusCode.Redirect) if (response.StatusCode == System.Net.HttpStatusCode.Redirect)
{ {
var redirect = await response.Content.ReadAsStringAsync(); var redirectUrl = response.Headers.Location.ToString();
Regex regex = new Regex(@"/runner/releases/tag/v(?<version>\d+\.\d+\.\d+)"); Regex regex = new Regex(@"/runner/releases/tag/v(?<version>\d+\.\d+\.\d+)");
var match = regex.Match(redirect); var match = regex.Match(redirectUrl);
if (match.Success) if (match.Success)
{ {
latestVersion = match.Groups["version"].Value; latestVersion = match.Groups["version"].Value;
@@ -63,6 +64,10 @@ namespace GitHub.Runner.Common.Tests.Listener
_packageUrl = $"https://github.com/actions/runner/releases/download/v{latestVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{latestVersion}.zip"; _packageUrl = $"https://github.com/actions/runner/releases/download/v{latestVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{latestVersion}.zip";
#endif #endif
} }
else
{
throw new Exception("The latest runner version could not be determined so a download URL could not be generated for it. Please check the location header of the redirect response of 'https://github.com/actions/runner/releases/latest'");
}
} }
} }
@@ -791,3 +796,4 @@ namespace GitHub.Runner.Common.Tests.Listener
} }
} }
} }
#endif

View File

@@ -166,9 +166,9 @@ namespace GitHub.Runner.Common.Tests
string binDir = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin"); string binDir = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin");
#if OS_WINDOWS #if OS_WINDOWS
string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node12\bin\node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node16\bin\node");
#else #else
string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node12/bin/node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node16/bin/node");
#endif #endif
string hashFilesScript = Path.Combine(binDir, "hashFiles"); string hashFilesScript = Path.Combine(binDir, "hashFiles");
var hashResult = string.Empty; var hashResult = string.Empty;
@@ -228,9 +228,9 @@ namespace GitHub.Runner.Common.Tests
string binDir = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin"); string binDir = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin");
#if OS_WINDOWS #if OS_WINDOWS
string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node12\bin\node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node16\bin\node");
#else #else
string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node12/bin/node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node16/bin/node");
#endif #endif
string hashFilesScript = Path.Combine(binDir, "hashFiles"); string hashFilesScript = Path.Combine(binDir, "hashFiles");
var hashResult = string.Empty; var hashResult = string.Empty;

View File

@@ -27,9 +27,9 @@ namespace GitHub.Runner.Common.Tests
try try
{ {
#if OS_WINDOWS #if OS_WINDOWS
string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node12\bin\node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"..\_layout\externals\node16\bin\node");
#else #else
string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node12/bin/node"); string node = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/externals/node16/bin/node");
hc.EnqueueInstance<IProcessInvoker>(new ProcessInvokerWrapper()); hc.EnqueueInstance<IProcessInvoker>(new ProcessInvokerWrapper());
#endif #endif
var startInfo = new ProcessStartInfo(node, "-e \"setTimeout(function(){{}}, 15 * 1000);\""); var startInfo = new ProcessStartInfo(node, "-e \"setTimeout(function(){{}}, 15 * 1000);\"");

View File

@@ -25,23 +25,6 @@ namespace GitHub.Runner.Common.Tests.Worker
private CreateStepSummaryCommand _createStepCommand; private CreateStepSummaryCommand _createStepCommand;
private ITraceWriter _trace; private ITraceWriter _trace;
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void CreateStepSummaryCommand_FeatureDisabled()
{
using (var hostContext = Setup(featureFlagState: "false"))
{
var stepSummaryFile = Path.Combine(_rootDirectory, "feature-off");
_createStepCommand.ProcessCommand(_executionContext.Object, stepSummaryFile, null);
_jobExecutionContext.Complete();
_jobServerQueue.Verify(x => x.QueueFileUpload(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()), Times.Never());
Assert.Equal(0, _issues.Count);
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
@@ -117,7 +100,7 @@ namespace GitHub.Runner.Common.Tests.Worker
using (var hostContext = Setup()) using (var hostContext = Setup())
{ {
var stepSummaryFile = Path.Combine(_rootDirectory, "empty-file"); var stepSummaryFile = Path.Combine(_rootDirectory, "empty-file");
File.WriteAllBytes(stepSummaryFile, new byte[128 * 1024 + 1]); File.WriteAllBytes(stepSummaryFile, new byte[CreateStepSummaryCommand.AttachmentSizeLimit + 1]);
_createStepCommand.ProcessCommand(_executionContext.Object, stepSummaryFile, null); _createStepCommand.ProcessCommand(_executionContext.Object, stepSummaryFile, null);
_jobExecutionContext.Complete(); _jobExecutionContext.Complete();
@@ -199,7 +182,7 @@ namespace GitHub.Runner.Common.Tests.Worker
File.WriteAllText(path, contentStr, encoding); File.WriteAllText(path, contentStr, encoding);
} }
private TestHostContext Setup([CallerMemberName] string name = "", string featureFlagState = "true") private TestHostContext Setup([CallerMemberName] string name = "")
{ {
var hostContext = new TestHostContext(this, name); var hostContext = new TestHostContext(this, name);
@@ -241,7 +224,6 @@ namespace GitHub.Runner.Common.Tests.Worker
_variables = new Variables(hostContext, new Dictionary<string, VariableValue> _variables = new Variables(hostContext, new Dictionary<string, VariableValue>
{ {
{ "MySecretName", new VariableValue("My secret value", true) }, { "MySecretName", new VariableValue("My secret value", true) },
{ "DistributedTask.UploadStepSummary", featureFlagState },
}); });
// Directory for test data // Directory for test data

View File

@@ -6,6 +6,8 @@ using System.Threading;
using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.Pipelines.ContextData;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Worker; using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Container;
using GitHub.Runner.Worker.Handlers;
using Moq; using Moq;
using Xunit; using Xunit;
using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.ObjectTemplating.Tokens;
@@ -724,5 +726,149 @@ namespace GitHub.Runner.Common.Tests.Worker
return hc; return hc;
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void GetExpressionValues_ContainerStepHost()
{
using (TestHostContext hc = CreateTestContext())
{
const string source = "/home/username/Projects/work/runner/_layout";
var containerInfo = new ContainerInfo();
containerInfo.ContainerId = "test";
containerInfo.AddPathTranslateMapping($"{source}/_work", "/__w");
containerInfo.AddPathTranslateMapping($"{source}/_temp", "/__t");
containerInfo.AddPathTranslateMapping($"{source}/externals", "/__e");
containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_home", "/github/home");
containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_workflow", "/github/workflow");
foreach (var v in new List<string>() {
$"{source}/_work",
$"{source}/externals",
$"{source}/_work/_temp",
$"{source}/_work/_actions",
$"{source}/_work/_tool",
})
{
containerInfo.MountVolumes.Add(new MountVolume(v, containerInfo.TranslateToContainerPath(v)));
};
var stepHost = new ContainerStepHost();
stepHost.Container = containerInfo;
var ec = new Runner.Worker.ExecutionContext();
ec.Initialize(hc);
var inputGithubContext = new GitHubContext();
var inputeRunnerContext = new RunnerContext();
// string context data
inputGithubContext["action_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_actions/owner/composite/main");
inputGithubContext["action"] = new StringContextData("__owner_composite");
inputGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
inputGithubContext["env"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
inputGithubContext["path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
inputGithubContext["event_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_github_workflow/event.json");
inputGithubContext["repository"] = new StringContextData("owner/repo-name");
inputGithubContext["run_id"] = new StringContextData("2033211332");
inputGithubContext["workflow"] = new StringContextData("Name of Workflow");
inputGithubContext["workspace"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/step-order/step-order");
inputeRunnerContext["temp"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp");
inputeRunnerContext["tool_cache"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_tool");
// dictionary context data
var githubEvent = new DictionaryContextData();
githubEvent["inputs"] = null;
githubEvent["ref"] = new StringContextData("refs/heads/main");
githubEvent["repository"] = new DictionaryContextData();
githubEvent["sender"] = new DictionaryContextData();
githubEvent["workflow"] = new StringContextData(".github/workflows/composite_step_host_translate.yaml");
inputGithubContext["event"] = githubEvent;
ec.ExpressionValues["github"] = inputGithubContext;
ec.ExpressionValues["runner"] = inputeRunnerContext;
var ecExpect = new Runner.Worker.ExecutionContext();
ecExpect.Initialize(hc);
var expectedGithubEvent = new DictionaryContextData();
expectedGithubEvent["inputs"] = null;
expectedGithubEvent["ref"] = new StringContextData("refs/heads/main");
expectedGithubEvent["repository"] = new DictionaryContextData();
expectedGithubEvent["sender"] = new DictionaryContextData();
expectedGithubEvent["workflow"] = new StringContextData(".github/workflows/composite_step_host_translate.yaml");
var expectedGithubContext = new GitHubContext();
var expectedRunnerContext = new RunnerContext();
expectedGithubContext["action_path"] = new StringContextData("/__w/_actions/owner/composite/main");
expectedGithubContext["action"] = new StringContextData("__owner_composite");
expectedGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
expectedGithubContext["env"] = new StringContextData("/__w/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
expectedGithubContext["path"] = new StringContextData("/__w/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
expectedGithubContext["event_path"] = new StringContextData("/github/workflow/event.json");
expectedGithubContext["repository"] = new StringContextData("owner/repo-name");
expectedGithubContext["run_id"] = new StringContextData("2033211332");
expectedGithubContext["workflow"] = new StringContextData("Name of Workflow");
expectedGithubContext["workspace"] = new StringContextData("/__w/step-order/step-order");
expectedGithubContext["event"] = expectedGithubEvent;
expectedRunnerContext["temp"] = new StringContextData("/__w/_temp");
expectedRunnerContext["tool_cache"] = new StringContextData("/__w/_tool");
ecExpect.ExpressionValues["github"] = expectedGithubContext;
ecExpect.ExpressionValues["runner"] = expectedRunnerContext;
var translatedExpressionValues = ec.GetExpressionValues(stepHost);
foreach (var contextName in new string[] { "github", "runner" })
{
var dict = translatedExpressionValues[contextName].AssertDictionary($"expected context github to be a dictionary");
var expectedExpressionValues = ecExpect.ExpressionValues[contextName].AssertDictionary("expect dict");
foreach (var key in dict.Keys.ToList())
{
if (dict[key] is StringContextData)
{
var expect = dict[key].AssertString("expect string");
var outcome = expectedExpressionValues[key].AssertString("expect string");
Assert.Equal(expect.Value, outcome.Value);
}
else if (dict[key] is DictionaryContextData || dict[key] is CaseSensitiveDictionaryContextData)
{
var expectDict = dict[key].AssertDictionary("expect dict");
var actualDict = expectedExpressionValues[key].AssertDictionary("expect dict");
Assert.True(ExpressionValuesAssertEqual(expectDict, actualDict));
}
}
}
}
}
private bool ExpressionValuesAssertEqual(DictionaryContextData expect, DictionaryContextData actual)
{
foreach (var key in expect.Keys.ToList())
{
if (expect[key] is StringContextData)
{
var expectValue = expect[key].AssertString("expect string");
var actualValue = actual[key].AssertString("expect string");
if (expectValue.Equals(actualValue))
{
return false;
}
}
else if (expect[key] is DictionaryContextData || expect[key] is CaseSensitiveDictionaryContextData)
{
var expectDict = expect[key].AssertDictionary("expect dict");
var actualDict = actual[key].AssertDictionary("expect dict");
if (!ExpressionValuesAssertEqual(expectDict, actualDict))
{
return false;
}
}
}
return true;
}
} }
} }

View File

@@ -211,6 +211,24 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async Task JobExtensionBuildFailsWithoutContainerIfRequired()
{
Environment.SetEnvironmentVariable(Constants.Variables.Actions.RequireJobContainer, "true");
using (TestHostContext hc = CreateTestContext())
{
var jobExtension = new JobExtension();
jobExtension.Initialize(hc);
_actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny<IExecutionContext>(), It.IsAny<IEnumerable<Pipelines.JobStep>>(), It.IsAny<Guid>()))
.Returns(Task.FromResult(new PrepareResult(new List<JobExtensionRunner>() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }, new Dictionary<Guid, IActionRunner>())));
await Assert.ThrowsAsync<ArgumentException>(() => jobExtension.InitializeJob(_jobEc, _message));
}
}
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]

View File

@@ -3,9 +3,9 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Runner.Worker; using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
@@ -937,6 +937,19 @@ namespace GitHub.Runner.Common.Tests.Worker
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void CaptureTelemetryForGitUnsafeRepository()
{
using (Setup())
using (_outputManager)
{
Process("fatal: unsafe repository ('/github/workspace' is owned by someone else)");
Assert.Contains("fatal: unsafe repository ('/github/workspace' is owned by someone else)", _executionContext.Object.StepTelemetry.ErrorMessages);
}
}
private TestHostContext Setup( private TestHostContext Setup(
[CallerMemberName] string name = "", [CallerMemberName] string name = "",
IssueMatchersConfig matchers = null, IssueMatchersConfig matchers = null,
@@ -962,6 +975,8 @@ namespace GitHub.Runner.Common.Tests.Worker
Variables = _variables, Variables = _variables,
WriteDebug = true, WriteDebug = true,
}); });
_executionContext.Setup(x => x.StepTelemetry)
.Returns(new DTWebApi.ActionsStepTelemetry());
_executionContext.Setup(x => x.GetMatchers()) _executionContext.Setup(x => x.GetMatchers())
.Returns(matchers?.Matchers ?? new List<IssueMatcherConfig>()); .Returns(matchers?.Matchers ?? new List<IssueMatcherConfig>());
_executionContext.Setup(x => x.Add(It.IsAny<OnMatcherChanged>())) _executionContext.Setup(x => x.Add(It.IsAny<OnMatcherChanged>()))

View File

@@ -7,6 +7,9 @@ using Xunit;
using GitHub.Runner.Worker; using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Handlers; using GitHub.Runner.Worker.Handlers;
using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Container;
using GitHub.DistributedTask.Pipelines.ContextData;
using System.Linq;
using GitHub.DistributedTask.Pipelines;
namespace GitHub.Runner.Common.Tests.Worker namespace GitHub.Runner.Common.Tests.Worker
{ {
@@ -29,6 +32,7 @@ namespace GitHub.Runner.Common.Tests.Worker
return hc; return hc;
} }
#if OS_LINUX
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
@@ -105,5 +109,6 @@ namespace GitHub.Runner.Common.Tests.Worker
Assert.Equal("node16", nodeVersion); Assert.Equal("node16", nodeVersion);
} }
} }
#endif
} }
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn> <NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
</PropertyGroup> </PropertyGroup>

View File

@@ -2,7 +2,7 @@
############################################################################### ###############################################################################
# #
# ./dev.sh build/layout/test/package [Debug/Release] [linux-x64|linux-x86|linux-arm64|linux-arm|osx-x64|win-x64|win-x86] [use-broker] # ./dev.sh build/layout/test/package [Debug/Release]
# #
############################################################################### ###############################################################################
@@ -11,7 +11,6 @@ set -e
DEV_CMD=$1 DEV_CMD=$1
DEV_CONFIG=$2 DEV_CONFIG=$2
DEV_TARGET_RUNTIME=$3 DEV_TARGET_RUNTIME=$3
DEV_USE_BROKER=$4
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LAYOUT_DIR="$SCRIPT_DIR/../_layout" LAYOUT_DIR="$SCRIPT_DIR/../_layout"
@@ -23,7 +22,7 @@ DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
PACKAGE_DIR="$SCRIPT_DIR/../_package" PACKAGE_DIR="$SCRIPT_DIR/../_package"
PACKAGE_TRIMS_DIR="$SCRIPT_DIR/../_package_trims" PACKAGE_TRIMS_DIR="$SCRIPT_DIR/../_package_trims"
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk" DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
DOTNETSDK_VERSION="6.0.100" DOTNETSDK_VERSION="6.0.300"
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION" DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
RUNNER_VERSION=$(cat runnerversion) RUNNER_VERSION=$(cat runnerversion)
@@ -55,6 +54,12 @@ elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
fi fi
elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
RUNTIME_ID='osx-x64' RUNTIME_ID='osx-x64'
if command -v uname > /dev/null; then
CPU_NAME=$(uname -m)
case $CPU_NAME in
arm64) RUNTIME_ID="osx-arm64";;
esac
fi
fi fi
if [[ -n "$DEV_TARGET_RUNTIME" ]]; then if [[ -n "$DEV_TARGET_RUNTIME" ]]; then
@@ -64,7 +69,7 @@ fi
# Make sure current platform support publish the dotnet runtime # Make sure current platform support publish the dotnet runtime
# Windows can publish win-x86/x64 # Windows can publish win-x86/x64
# Linux can publish linux-x64/arm/arm64 # Linux can publish linux-x64/arm/arm64
# OSX can publish osx-x64 # OSX can publish osx-x64/arm64
if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') ]]; then if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') ]]; then
echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2 echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
@@ -76,19 +81,12 @@ elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
exit 1 exit 1
fi fi
elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
if [[ ("$RUNTIME_ID" != 'osx-x64') ]]; then if [[ ("$RUNTIME_ID" != 'osx-x64') && ("$RUNTIME_ID" != 'osx-arm64') ]]; then
echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2 echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
exit 1 exit 1
fi fi
fi fi
if [ -n "$DEV_USE_BROKER" ]; then
USE_BROKER='-p:USE_BROKER="true"'
else
USE_BROKER=''
fi
function failed() function failed()
{ {
local error=${1:-Undefined error} local error=${1:-Undefined error}
@@ -122,13 +120,13 @@ function heading()
function build () function build ()
{ {
heading "Building ..." heading "Building ..."
dotnet msbuild -t:Build -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" $USE_BROKER ./dir.proj || failed build dotnet msbuild -t:Build -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" ./dir.proj || failed build
} }
function layout () function layout ()
{ {
heading "Create layout ..." heading "Create layout ..."
dotnet msbuild -t:layout -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" $USE_BROKER ./dir.proj || failed build dotnet msbuild -t:layout -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" ./dir.proj || failed build
#change execution flag to allow running with sudo #change execution flag to allow running with sudo
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then

View File

@@ -48,7 +48,7 @@
<Target Name="Test" DependsOnTargets="GenerateConstant"> <Target Name="Test" DependsOnTargets="GenerateConstant">
<Exec Command="dotnet build Test/Test.csproj -c $(BUILDCONFIG) /p:PackageRuntime=$(PackageRuntime)" ConsoleToMSBuild="true" /> <Exec Command="dotnet build Test/Test.csproj -c $(BUILDCONFIG) /p:PackageRuntime=$(PackageRuntime)" ConsoleToMSBuild="true" />
<Exec Command="dotnet test Test/Test.csproj --no-build --logger:trx" ConsoleToMSBuild="true" /> <Exec Command="dotnet test Test/Test.csproj -c $(BUILDCONFIG) --no-build --logger:trx" ConsoleToMSBuild="true" />
</Target> </Target>
<Target Name="Layout" DependsOnTargets="Clean;Build"> <Target Name="Layout" DependsOnTargets="Clean;Build">

View File

@@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version": "6.0.100" "version": "6.0.300"
} }
} }

View File

@@ -1 +1 @@
2.289.2 2.292.0