mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
59 Commits
v2.283.4
...
users/eric
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa07c78c0c | ||
|
|
8eacbdc79f | ||
|
|
6b4a95cdb1 | ||
|
|
c95d5eae30 | ||
|
|
ea67ff9647 | ||
|
|
d7d38e173e | ||
|
|
ac31fd10b2 | ||
|
|
d8251bf912 | ||
|
|
715bb7cca8 | ||
|
|
47dfebdf48 | ||
|
|
7cb198a554 | ||
|
|
7616e9b7aa | ||
|
|
3b8475de3e | ||
|
|
ba9766d544 | ||
|
|
29da60a538 | ||
|
|
f2e210e5f3 | ||
|
|
fa32fcf2a1 | ||
|
|
46da23edb1 | ||
|
|
9bfbc48f45 | ||
|
|
ead1826afb | ||
|
|
9de17f197c | ||
|
|
45decac397 | ||
|
|
55ed60b9fc | ||
|
|
698d3a2e66 | ||
|
|
d0ab54ce45 | ||
|
|
3e65909b81 | ||
|
|
3ec20e989d | ||
|
|
231fdcb19d | ||
|
|
bef164a12f | ||
|
|
a519f96a41 | ||
|
|
b1ecffd707 | ||
|
|
801a02ec89 | ||
|
|
6332f9a42f | ||
|
|
5b8ff174c6 | ||
|
|
e3e977fd84 | ||
|
|
4dc8a09db3 | ||
|
|
dcc5d34ad1 | ||
|
|
3e34fb10c1 | ||
|
|
23a693aa2c | ||
|
|
eb36db8ff9 | ||
|
|
85e1927754 | ||
|
|
b6dbf42746 | ||
|
|
67ba8a7d42 | ||
|
|
e4f9e6ae26 | ||
|
|
854d5e3bf3 | ||
|
|
57dec28f68 | ||
|
|
55a861f089 | ||
|
|
51b2031cbf | ||
|
|
400b2d879c | ||
|
|
c4b6d288d4 | ||
|
|
0699597876 | ||
|
|
a592b14ae3 | ||
|
|
04269f7b1b | ||
|
|
e89d2e84bd | ||
|
|
afe7066e39 | ||
|
|
da79ef4acb | ||
|
|
5afb52b272 | ||
|
|
cf87c55557 | ||
|
|
43fa351980 |
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,12 +1,18 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: 🛑 Report a bug in the runner application
|
||||||
about: Create a report to help us improve
|
about: If you have issues with GitHub Actions, please follow the "support for GitHub Actions" link, below.
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
👋 You're opening a bug report against the GitHub Actions **runner application**.
|
||||||
|
|
||||||
|
🛑 Please stop if you're not certain that the bug you're seeing is in the runner application - if you have general problems with actions, workflows, or runners, please see the [GitHub Community Support Forum](https://github.community/c/code-to-cloud/52) which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃
|
||||||
|
-->
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: ✅ Support for GitHub Actions
|
||||||
|
url: https://github.community/c/code-to-cloud/52
|
||||||
|
about: If you have questions about GitHub Actions or need support writing workflows, please ask in the GitHub Community Support forum.
|
||||||
|
- name: ✅ Feedback and suggestions for GitHub Actions
|
||||||
|
url: https://github.com/github/feedback/discussions/categories/actions-and-packages-feedback
|
||||||
|
about: If you have feedback or suggestions about GitHub Actions, please open a discussion (or add to an existing one) in the GitHub Actions Feedback. GitHub Actions Product Managers and Engineers monitor the feedback forum.
|
||||||
|
- name: ‼️ GitHub Security Bug Bounty
|
||||||
|
url: https://bounty.github.com/
|
||||||
|
about: Please report security vulnerabilities here.
|
||||||
13
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
13
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
@@ -1,19 +1,24 @@
|
|||||||
---
|
---
|
||||||
name: Feature Request
|
name: 🛑 Request a feature in the runner application
|
||||||
about: Create a request to help us improve
|
about: If you have feature requests for GitHub Actions, please use the "feedback and suggestions for GitHub Actions" link below.
|
||||||
title: ''
|
title: ''
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Thank you 🙇♀ for wanting to create a feature in this repository. Before you do, please ensure you are filing the issue in the right place. Issues should only be opened on if the issue **relates to code in this repository**.
|
<!--
|
||||||
|
👋 You're opening a request for an enhancement in the GitHub Actions **runner application**.
|
||||||
|
|
||||||
|
🛑 Please stop if you're not certain that the feature you want is in the runner application - if you have a suggestion for improving GitHub Actions, please see the [GitHub Actions Feedback](https://github.com/github/feedback/discussions/categories/actions-and-packages-feedback) discussion forum which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃
|
||||||
|
|
||||||
|
Some additional useful links:
|
||||||
* If you have found a security issue [please submit it here](https://hackerone.com/github)
|
* If you have found a security issue [please submit it here](https://hackerone.com/github)
|
||||||
* If you have questions or issues with the service, writing workflows or actions, then please [visit the GitHub Community Forum's Actions Board](https://github.community/t5/GitHub-Actions/bd-p/actions)
|
* If you have questions or issues with the service, writing workflows or actions, then please [visit the GitHub Community Forum's Actions Board](https://github.community/t5/GitHub-Actions/bd-p/actions)
|
||||||
* If you are having an issue or question about GitHub Actions then please [contact customer support](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-github-actions#contacting-support)
|
* If you are having an issue or have a question about GitHub Actions then please [contact customer support](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-github-actions#contacting-support)
|
||||||
|
|
||||||
If you have a feature request that is relevant to this repository, the runner, then please include the information below:
|
If you have a feature request that is relevant to this repository, the runner, then please include the information below:
|
||||||
|
-->
|
||||||
|
|
||||||
**Describe the enhancement**
|
**Describe the enhancement**
|
||||||
A clear and concise description of what the features or enhancement you need.
|
A clear and concise description of what the features or enhancement you need.
|
||||||
|
|||||||
35
.github/workflows/build.yml
vendored
35
.github/workflows/build.yml
vendored
@@ -37,12 +37,12 @@ jobs:
|
|||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
|
||||||
- runtime: win-x64
|
- runtime: win-x64
|
||||||
os: windows-latest
|
os: windows-2019
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
@@ -57,6 +57,29 @@ jobs:
|
|||||||
working-directory: src
|
working-directory: src
|
||||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||||
|
|
||||||
|
# Check runtime/externals hash
|
||||||
|
- name: Compute/Compare runtime and externals Hash
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Current dotnet runtime hash result: $DOTNET_RUNTIME_HASH"
|
||||||
|
echo "Current Externals hash result: $EXTERNALS_HASH"
|
||||||
|
|
||||||
|
NeedUpdate=0
|
||||||
|
if [ "$EXTERNALS_HASH" != "$(cat ./src/Misc/contentHash/externals/${{ matrix.runtime }})" ] ;then
|
||||||
|
echo Hash mismatch, Update ./src/Misc/contentHash/externals/${{ matrix.runtime }} to $EXTERNALS_HASH
|
||||||
|
NeedUpdate=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DOTNET_RUNTIME_HASH" != "$(cat ./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }})" ] ;then
|
||||||
|
echo Hash mismatch, Update ./src/Misc/contentHash/dotnetRuntime/${{ matrix.runtime }} to $DOTNET_RUNTIME_HASH
|
||||||
|
NeedUpdate=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $NeedUpdate
|
||||||
|
env:
|
||||||
|
DOTNET_RUNTIME_HASH: ${{hashFiles('**/_layout_trims/runtime/**/*')}}
|
||||||
|
EXTERNALS_HASH: ${{hashFiles('**/_layout_trims/externals/**/*')}}
|
||||||
|
|
||||||
# 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'
|
||||||
@@ -67,7 +90,11 @@ jobs:
|
|||||||
# Upload runner package tar.gz/zip as artifact
|
# Upload runner package tar.gz/zip as artifact
|
||||||
- name: Publish Artifact
|
- name: Publish Artifact
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: runner-package-${{ matrix.runtime }}
|
name: runner-package-${{ matrix.runtime }}
|
||||||
path: _package
|
path: |
|
||||||
|
_package
|
||||||
|
_package_trims/trim_externals
|
||||||
|
_package_trims/trim_runtime
|
||||||
|
_package_trims/trim_runtime_externals
|
||||||
|
|||||||
5
.github/workflows/codeql.yml
vendored
5
.github/workflows/codeql.yml
vendored
@@ -1,7 +1,12 @@
|
|||||||
name: "Code Scanning - Action"
|
name: "Code Scanning - Action"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
|
|||||||
343
.github/workflows/release.yml
vendored
343
.github/workflows/release.yml
vendored
@@ -51,6 +51,21 @@ 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 }}
|
||||||
|
linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }}
|
||||||
|
linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }}
|
||||||
|
linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }}
|
||||||
|
win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }}
|
||||||
|
osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-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-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }}
|
||||||
|
win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }}
|
||||||
|
osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-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-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 }}
|
||||||
|
osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-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 ]
|
||||||
@@ -72,12 +87,12 @@ jobs:
|
|||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
|
||||||
- runtime: win-x64
|
- runtime: win-x64
|
||||||
os: windows-latest
|
os: windows-2019
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
@@ -99,14 +114,6 @@ jobs:
|
|||||||
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact.
|
|
||||||
# Since each package name is unique, so we don't need to put ${{matrix}} info into artifact name
|
|
||||||
- name: Publish Artifact
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: actions/upload-artifact@v1
|
|
||||||
with:
|
|
||||||
name: runner-packages
|
|
||||||
path: _package
|
|
||||||
# compute shas and set as job outputs to use in release notes
|
# compute shas and set as job outputs to use in release notes
|
||||||
- run: brew install coreutils #needed for shasum util
|
- run: brew install coreutils #needed for shasum util
|
||||||
if: ${{ matrix.os == 'macOS-latest' }}
|
if: ${{ matrix.os == 'macOS-latest' }}
|
||||||
@@ -120,6 +127,91 @@ jobs:
|
|||||||
id: sha
|
id: sha
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
working-directory: _package
|
working-directory: _package
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noexternals
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_externals
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noruntime
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_runtime
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noruntime_noexternals
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_runtime_externals
|
||||||
|
|
||||||
|
- name: Create trimmedpackages.json for ${{ matrix.runtime }}
|
||||||
|
if: matrix.runtime == 'win-x64'
|
||||||
|
uses: actions/github-script@0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
|
const fs = require('fs');
|
||||||
|
const runnerVersion = fs.readFileSync('src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
|
var trimmedPackages = fs.readFileSync('src/Misc/trimmedpackages_zip.json', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion).replace(/<RUNNER_PLATFORM>/g, '${{ matrix.runtime }}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<RUNTIME_HASH>/g, '${{hashFiles('**/_layout_trims/runtime/**/*')}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<EXTERNALS_HASH>/g, '${{hashFiles('**/_layout_trims/externals/**/*')}}')
|
||||||
|
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_EXTERNALS_HASH>/g, '${{steps.sha_noruntime_noexternals.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_HASH>/g, '${{steps.sha_noruntime.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_EXTERNALS_HASH>/g, '${{steps.sha_noexternals.outputs.sha256}}')
|
||||||
|
|
||||||
|
console.log(trimmedPackages)
|
||||||
|
fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages)
|
||||||
|
|
||||||
|
- name: Create trimmedpackages.json for ${{ matrix.runtime }}
|
||||||
|
if: matrix.runtime != 'win-x64'
|
||||||
|
uses: actions/github-script@0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
|
const fs = require('fs');
|
||||||
|
const runnerVersion = fs.readFileSync('src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
|
var trimmedPackages = fs.readFileSync('src/Misc/trimmedpackages_targz.json', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion).replace(/<RUNNER_PLATFORM>/g, '${{ matrix.runtime }}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<RUNTIME_HASH>/g, '${{hashFiles('**/_layout_trims/runtime/**/*')}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<EXTERNALS_HASH>/g, '${{hashFiles('**/_layout_trims/externals/**/*')}}')
|
||||||
|
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_EXTERNALS_HASH>/g, '${{steps.sha_noruntime_noexternals.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_HASH>/g, '${{steps.sha_noruntime.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_EXTERNALS_HASH>/g, '${{steps.sha_noexternals.outputs.sha256}}')
|
||||||
|
|
||||||
|
console.log(trimmedPackages)
|
||||||
|
fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages)
|
||||||
|
|
||||||
|
# Upload runner package tar.gz/zip as artifact.
|
||||||
|
# Since each package name is unique, so we don't need to put ${{matrix}} info into artifact name
|
||||||
|
- name: Publish Artifact
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: runner-packages
|
||||||
|
path: |
|
||||||
|
_package
|
||||||
|
_package_trims/trim_externals
|
||||||
|
_package_trims/trim_runtime
|
||||||
|
_package_trims/trim_runtime_externals
|
||||||
|
${{ matrix.runtime }}-trimmedpackages.json
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -150,6 +242,21 @@ jobs:
|
|||||||
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(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-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_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(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-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_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(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-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_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime-noexternals}}')
|
||||||
console.log(releaseNote)
|
console.log(releaseNote)
|
||||||
core.setOutput('version', runnerVersion);
|
core.setOutput('version', runnerVersion);
|
||||||
core.setOutput('note', releaseNote);
|
core.setOutput('note', releaseNote);
|
||||||
@@ -165,14 +272,14 @@ jobs:
|
|||||||
body: |
|
body: |
|
||||||
${{ steps.releaseNote.outputs.note }}
|
${{ steps.releaseNote.outputs.note }}
|
||||||
|
|
||||||
# Upload release assets
|
# Upload release assets (full runner packages)
|
||||||
- name: Upload Release Asset (win-x64)
|
- name: Upload Release Asset (win-x64)
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
asset_path: ${{ github.workspace }}/_package/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
||||||
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -182,7 +289,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -192,7 +299,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
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
|
||||||
|
|
||||||
@@ -202,7 +309,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -212,6 +319,210 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# Upload release assets (trim externals)
|
||||||
|
- name: Upload Release Asset (win-x64-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-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
|
||||||
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-x64-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-linux-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (osx-x64-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-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
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-arm-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-linux-arm-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-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-linux-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# Upload release assets (trim runtime)
|
||||||
|
- name: Upload Release Asset (win-x64-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-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
|
||||||
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-x64-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-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (osx-x64-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-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
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-arm-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-linux-arm-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-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-linux-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# Upload release assets (trim runtime and externals)
|
||||||
|
- name: Upload Release Asset (win-x64-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-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
|
||||||
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-x64-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-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (osx-x64-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-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
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-arm-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-linux-arm-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-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-linux-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# Upload release assets (trimmedpackages.json)
|
||||||
|
- name: Upload Release Asset (win-x64-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 }}/win-x64-trimmedpackages.json
|
||||||
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-x64-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 }}/linux-x64-trimmedpackages.json
|
||||||
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (osx-x64-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-x64-trimmedpackages.json
|
||||||
|
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-arm-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 }}/linux-arm-trimmedpackages.json
|
||||||
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-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 }}/linux-arm64-trimmedpackages.json
|
||||||
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,7 +19,9 @@
|
|||||||
node_modules
|
node_modules
|
||||||
_downloads
|
_downloads
|
||||||
_layout
|
_layout
|
||||||
|
_layout_trims
|
||||||
_package
|
_package
|
||||||
|
_package_trims
|
||||||
_dotnetsdk
|
_dotnetsdk
|
||||||
TestResults
|
TestResults
|
||||||
TestLogs
|
TestLogs
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
# GitHub Actions Runner
|
# GitHub Actions Runner
|
||||||
|
|
||||||
[](https://github.com/actions/runner/actions)
|
[](https://github.com/actions/runner/actions)
|
||||||
[](https://github.com/actions/runner/actions)
|
|
||||||
|
|
||||||
The runner is the application that runs a job from a GitHub Actions workflow. It is used by GitHub Actions in the [hosted virtual environments](https://github.com/actions/virtual-environments), or you can [self-host the runner](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners) in your own environment.
|
The runner is the application that runs a job from a GitHub Actions workflow. It is used by GitHub Actions in the [hosted virtual environments](https://github.com/actions/virtual-environments), or you can [self-host the runner](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners) in your own environment.
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Compilation failures during a CI build should surface good error messages.
|
|||||||
|
|
||||||
For example, the actual compile errors from the typescript compiler should bubble as issues in the UI. And not simply "tsc exited with exit code 1".
|
For example, the actual compile errors from the typescript compiler should bubble as issues in the UI. And not simply "tsc exited with exit code 1".
|
||||||
|
|
||||||
VSCode has an extensible model for solving this type of problem. VSCode allows users to configure which problems matchers to use, when scanning output. For example, a user can apply the `tsc` problem matcher to receive a rich error output experience in VSCode, when compiling their typescript project.
|
VSCode has an extensible model for solving this type of problem. VSCode allows users to configure which [problems matchers](https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher) to use, when scanning output. For example, a user can apply the `tsc` problem matcher to receive a rich error output experience in VSCode, when compiling their typescript project.
|
||||||
|
|
||||||
The problem-matcher concept fits well with "setup" actions. For example, the `setup-nodejs` action will download node.js, add it to the PATH, and register the `tsc` problem matcher. For the duration of the job, the `tsc` problem matcher will be applied against the output.
|
The problem-matcher concept fits well with "setup" actions. For example, the `setup-nodejs` action will download node.js, add it to the PATH, and register the `tsc` problem matcher. For the duration of the job, the `tsc` problem matcher will be applied against the output.
|
||||||
|
|
||||||
@@ -18,21 +18,23 @@ The problem-matcher concept fits well with "setup" actions. For example, the `se
|
|||||||
|
|
||||||
### Registration
|
### Registration
|
||||||
|
|
||||||
#### Using `##` command
|
#### Using `::` command
|
||||||
|
|
||||||
`##[add-matcher]path-to-problem-matcher-config.json`
|
`::add-matcher::path-to-problem-matcher-config.json`
|
||||||
|
|
||||||
Using a `##` command allows for flexibility:
|
Using a `::` command allows for flexibility:
|
||||||
- Ad hoc scripts can register problem matchers
|
- Ad hoc scripts can register problem matchers
|
||||||
- Allows problem matchers to be conditionally registered
|
- Allows problem matchers to be conditionally registered
|
||||||
|
|
||||||
Note, if a matcher with the same name is registered a second time, it will clobber the first instance.
|
Note, if a matcher with the same name is registered a second time, it will clobber the first instance.
|
||||||
|
|
||||||
#### Unregister using `##` command
|
Note, at some point the syntax changed from `##` to `::`.
|
||||||
|
|
||||||
|
#### Unregister using `::` command
|
||||||
|
|
||||||
A way out for rare cases where scoping is a problem.
|
A way out for rare cases where scoping is a problem.
|
||||||
|
|
||||||
`##[remove-matcher]owner`
|
`::remove-matcher::owner`
|
||||||
|
|
||||||
For this to be usable, the `owner` needs to be discoverable. Therefore, debug print the owner on registration.
|
For this to be usable, the `owner` needs to be discoverable. Therefore, debug print the owner on registration.
|
||||||
|
|
||||||
@@ -104,7 +106,7 @@ message: ; expected
|
|||||||
fromPath: C:\myrepo\myproject\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj
|
fromPath: C:\myrepo\myproject\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj
|
||||||
```
|
```
|
||||||
|
|
||||||
Additionally the line will appear red in the web UI (prefix with `##[error]`).
|
Additionally the line will appear red in the web UI (prefix with `::error`).
|
||||||
|
|
||||||
Note, an error does not imply task failure. Exit codes communicate failure.
|
Note, an error does not imply task failure. Exit codes communicate failure.
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ The runner will look for a file `.setup_info` under the runner's root directory,
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
The runner will use `##[group]` and `##[endgroup]` to fold all detail info into an expandable group.
|
The runner will use `::group` and `::endgroup` to fold all detail info into an expandable group.
|
||||||
|
|
||||||
Both [virtual-environments](https://github.com/actions/virtual-environments) and self-hosted runners can use this mechanism to add extra logging info to the `Set up job` step's log.
|
Both [virtual-environments](https://github.com/actions/virtual-environments) and self-hosted runners can use this mechanism to add extra logging info to the `Set up job` step's log.
|
||||||
|
|
||||||
|
|||||||
71
docs/adrs/1438-conditional-composite.md
Normal file
71
docs/adrs/1438-conditional-composite.md
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# ADR 1438: Support Conditionals In Composite Actions
|
||||||
|
|
||||||
|
**Date**: 2021-10-13
|
||||||
|
|
||||||
|
**Status**: Accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
We recently shipped composite actions, which allows you to reuse individual steps inside an action.
|
||||||
|
However, one of the [most requested features](https://github.com/actions/runner/issues/834) has been a way to support the `if` keyword.
|
||||||
|
|
||||||
|
### Goals
|
||||||
|
- We want to keep consistent with current behavior
|
||||||
|
- We want to support conditionals via the `if` keyword
|
||||||
|
- Our built in functions like `success` should be implementable without calling them, for example you can do `job.status == success` rather then `success()` currently.
|
||||||
|
|
||||||
|
### How does composite currently work?
|
||||||
|
|
||||||
|
Currently, we have limited conditional support in composite actions for `pre` and `post` steps.
|
||||||
|
These are based on the `job status`, and support keywords like `always()`, `failed()`, `success()` and `cancelled()`.
|
||||||
|
However, generic or main steps do **not** support conditionals.
|
||||||
|
|
||||||
|
By default, in a regular workflow, a step runs on the `success()` condition. Which looks at the **job** **status**, sees if it is successful and runs.
|
||||||
|
|
||||||
|
By default, in a composite action, main steps run until a single step fails in that composite action, then the composite action is halted early. It does **not** care about the job status.
|
||||||
|
Pre, and post steps in composite actions use the job status to determine if they should run.
|
||||||
|
|
||||||
|
### How do we go forward?
|
||||||
|
|
||||||
|
Well, if we think about what composite actions are currently doing when invoking main steps, they are checking if the current composite action is successful.
|
||||||
|
Lets formalize that concept into a "real" idea.
|
||||||
|
|
||||||
|
- We will add an `action_status` field to the github context to mimic the [job's context status](https://docs.github.com/en/actions/learn-github-actions/contexts#job-context).
|
||||||
|
- We have an existing concept that does this `action_path` which is only set for composite actions on the github context.
|
||||||
|
- In a composite action during a main step, the `success()` function will check if `action_status == success`, rather then `job_status == success`. Failure will work the same way.
|
||||||
|
- Pre and post steps in composite actions will not change, they will continue to check the job status.
|
||||||
|
|
||||||
|
|
||||||
|
### Nested Scenario
|
||||||
|
For nested composite actions, we will follow the existing behavior, you only care about your current composite action, not any parents.
|
||||||
|
For example, lets imagine a scenario with a simple nested composite action
|
||||||
|
|
||||||
|
```
|
||||||
|
- Job
|
||||||
|
- Regular Step
|
||||||
|
- Composite Action
|
||||||
|
- runs: exit 1
|
||||||
|
- if: always()
|
||||||
|
uses: A child composite action
|
||||||
|
- if: success()
|
||||||
|
runs: echo "this should print"
|
||||||
|
- runs: echo "this should also print"
|
||||||
|
- if: success()
|
||||||
|
runs: echo "this will not print as the current composite action has failed already"
|
||||||
|
|
||||||
|
```
|
||||||
|
The child composite actions steps should run in this example, the child composite action has not yet failed, so it should run all steps until a step fails. This is consistent with how a composite action currently works in production if the main job fails but a composite action is invoked with `if:always()` or `if: failure()`
|
||||||
|
|
||||||
|
### Other options explored
|
||||||
|
We could add the `current_step_status` to the job context rather then `__status` to the steps context, however this comes with two major downsides:
|
||||||
|
- We need to support the field for every type of step, because its non trivial to remove a field from the job context once it has been added (its readonly)
|
||||||
|
- For all actions besides composite it would only every be `success`
|
||||||
|
- Its weird to have a `current_step` value on the job context
|
||||||
|
- We also explored a `__status` on the steps context.
|
||||||
|
- The `__` is required to prevent us from colliding with a step with id: status
|
||||||
|
- This felt wrong because the naming was not smooth, and did not fit into current conventions.
|
||||||
|
|
||||||
|
### Consequences
|
||||||
|
- github context has a new field for the status of the current composite action.
|
||||||
|
- We support conditional's in composite actions
|
||||||
|
- We keep the existing behavior for all users, but allow them to expand that functionality.
|
||||||
@@ -23,6 +23,10 @@ An ADR is an Architectural Decision Record. This allows consensus on the direct
|
|||||||
|
|
||||||
  Git for Windows and Linux [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
  Git for Windows and Linux [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
||||||
|
|
||||||
|
 cURL [Install here](https://curl.se/download.html) (needed for external sh script)
|
||||||
|
|
||||||
|
 Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev sh script)
|
||||||
|
|
||||||
## Quickstart: Run a job from a real repository
|
## Quickstart: Run a job from a real repository
|
||||||
|
|
||||||
If you just want to get from building the sourcecode to using it to execute an action, you will need:
|
If you just want to get from building the sourcecode to using it to execute an action, you will need:
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 138 KiB |
@@ -23,8 +23,8 @@ You might see something like this which indicate a dependency's missing.
|
|||||||
./config.sh
|
./config.sh
|
||||||
libunwind.so.8 => not found
|
libunwind.so.8 => not found
|
||||||
libunwind-x86_64.so.8 => not found
|
libunwind-x86_64.so.8 => not found
|
||||||
Dependencies is missing for Dotnet Core 3.0
|
Dependencies is missing for Dotnet Core 6.0
|
||||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.
|
||||||
```
|
```
|
||||||
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
||||||
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Collect more telemetry
|
- Bump runtime to dotnet 6 (#1471)
|
||||||
- Make `runner.name` available as a runner context variable
|
- Show service container logs on teardown (#1563)
|
||||||
- Add attempt number (`run_attempt`) to GitHub context
|
|
||||||
- When using the `--ephemeral` flag, ensure that the runner cleans up local `.runner` and `.credentials` files after completion (#1337)
|
## Bugs
|
||||||
|
|
||||||
|
- Add masks for multiline secrets from ::add-mask:: (#1521)
|
||||||
|
- fix Log size and retention settings not work (#1507)
|
||||||
|
- Refactor SelfUpdater adding L0 tests. (#1564)
|
||||||
|
- Fix test failure: /bin/sleep on Macos 11 (Monterey) does not accept the suffix s. (#1472)
|
||||||
|
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
- Improved network troubleshooting docs
|
- Update dependency check for dotnet 6. (#1551)
|
||||||
|
- Produce trimmed down runner packages. (#1556)
|
||||||
|
- Deleted extra background in github-praph.png, which is displayed in README.md (#1432)
|
||||||
|
|
||||||
|
|
||||||
## 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.
|
||||||
@@ -79,3 +88,21 @@ The SHA-256 checksums for the packages included in this build are shown below:
|
|||||||
- 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-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-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-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-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-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-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-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-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-arm-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noruntime_noexternals --><LINUX_ARM_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-arm_noruntime_noexternals -->
|
||||||
|
|||||||
1
src/Misc/contentHash/dotnetRuntime/linux-arm
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-arm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
de62d296708908cfd1236e58869aebbc2bae8a8c3d629276968542626c508e37
|
||||||
1
src/Misc/contentHash/dotnetRuntime/linux-arm64
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-arm64
Normal file
@@ -0,0 +1 @@
|
|||||||
|
44fcd0422dd98ed17d2c8e9057ff2260c50165f20674236a4ae7d2645a07df25
|
||||||
1
src/Misc/contentHash/dotnetRuntime/linux-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-x64
Normal file
@@ -0,0 +1 @@
|
|||||||
|
e57652cf322ee16ce3af4f9e58f80858746b9e1e60279e991a3b3d9a6baf8d79
|
||||||
1
src/Misc/contentHash/dotnetRuntime/osx-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/osx-x64
Normal file
@@ -0,0 +1 @@
|
|||||||
|
bdd247b2ff3f51095524412e2ac588e7a87af805e114d6caf2368366ee7be1ea
|
||||||
1
src/Misc/contentHash/dotnetRuntime/win-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/win-x64
Normal file
@@ -0,0 +1 @@
|
|||||||
|
d23a0cb9f20c0aa1cddb7a39567cd097020cdeb06a1e952940601d1a405c53b8
|
||||||
1
src/Misc/contentHash/externals/linux-arm
vendored
Normal file
1
src/Misc/contentHash/externals/linux-arm
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
6ca4a0e1c50b7079ead05321dcf5835c1c25f23dc632add8c1c4667d416d103e
|
||||||
1
src/Misc/contentHash/externals/linux-arm64
vendored
Normal file
1
src/Misc/contentHash/externals/linux-arm64
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
b5951dc607d782d9c7571a7224e940eb0975bb23c54ff25c7afdbf959a417081
|
||||||
1
src/Misc/contentHash/externals/linux-x64
vendored
Normal file
1
src/Misc/contentHash/externals/linux-x64
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
af819e92011cc9cbca90e8299f9f7651f2cf6bf45b42920f9a4ca22795486147
|
||||||
1
src/Misc/contentHash/externals/osx-x64
vendored
Normal file
1
src/Misc/contentHash/externals/osx-x64
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
aa0e6bf4bfaabf48c962ea3b262dca042629ab332005f73d282faec908847036
|
||||||
1
src/Misc/contentHash/externals/win-x64
vendored
Normal file
1
src/Misc/contentHash/externals/win-x64
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
40328cff2b8229f9b578f32739183bd8f6aab481c21dadc052b09f1c7e8e4665
|
||||||
@@ -4,6 +4,7 @@ PRECACHE=$2
|
|||||||
|
|
||||||
NODE_URL=https://nodejs.org/dist
|
NODE_URL=https://nodejs.org/dist
|
||||||
NODE12_VERSION="12.13.1"
|
NODE12_VERSION="12.13.1"
|
||||||
|
NODE16_VERSION="16.13.0"
|
||||||
|
|
||||||
get_abs_path() {
|
get_abs_path() {
|
||||||
# exploits the fact that pwd will print abs path when no args
|
# exploits the fact that pwd will print abs path when no args
|
||||||
@@ -126,6 +127,8 @@ function acquireExternalTool() {
|
|||||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -134,18 +137,23 @@ fi
|
|||||||
# Download the external tools only for OSX.
|
# Download the external tools only for OSX.
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
||||||
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ var gracefulShutdown = function (code) {
|
|||||||
listener.kill('SIGINT');
|
listener.kill('SIGINT');
|
||||||
|
|
||||||
console.log('Sending SIGKILL to runner listener');
|
console.log('Sending SIGKILL to runner listener');
|
||||||
setTimeout(() => listener.kill('SIGKILL'), 30000);
|
setTimeout(() => listener.kill('SIGKILL'), 30000).unref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>ProcessType</key>
|
<key>ProcessType</key>
|
||||||
<string>Interactive</string>
|
<string>Interactive</string>
|
||||||
|
<key>SessionCreate</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ downloadrunnerversion=_DOWNLOAD_RUNNER_VERSION_
|
|||||||
logfile="_UPDATE_LOG_"
|
logfile="_UPDATE_LOG_"
|
||||||
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
||||||
|
|
||||||
|
telemetryfile="$rootfolder/_diag/.telemetry"
|
||||||
|
|
||||||
# log user who run the script
|
# log user who run the script
|
||||||
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
||||||
whoami >> "$logfile" 2>&1
|
whoami >> "$logfile" 2>&1
|
||||||
@@ -118,40 +120,55 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# fix upgrade issue with macOS
|
# fix upgrade issue with macOS when running as a service
|
||||||
|
attemptedtargetedfix=0
|
||||||
currentplatform=$(uname | awk '{print tolower($0)}')
|
currentplatform=$(uname | awk '{print tolower($0)}')
|
||||||
if [[ "$currentplatform" == 'darwin' ]]; then
|
if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
||||||
# need a short-term fix for https://github.com/actions/runner/issues/743
|
# We needed a fix for https://github.com/actions/runner/issues/743
|
||||||
# we will recreate all the ./externals/node12/bin/node of the past 5 versions
|
# We will recreate the ./externals/node12/bin/node of the past runner version that launched the runnerlistener service
|
||||||
# v2.280.3 v2.280.2 v2.280.1 v2.279.0 v2.278.0
|
# Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.3/node12/bin/node" ]]
|
|
||||||
then
|
|
||||||
mkdir -p "$rootfolder/externals.2.280.3/node12/bin"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.3/node12/bin/node"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.2/node12/bin/node" ]]
|
# We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid
|
||||||
|
# assumption here is only one process is invoking rootfolder/runsvc.sh
|
||||||
|
procgroup=$(ps x -o pgid,command | grep "$rootfolder/runsvc.sh" | grep -v grep | awk '{print $1}')
|
||||||
|
if [[ $? -eq 0 && -n "$procgroup" ]]
|
||||||
then
|
then
|
||||||
mkdir -p "$rootfolder/externals.2.280.2/node12/bin"
|
# inspect the open file handles to find the node process
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.2/node12/bin/node"
|
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks
|
||||||
fi
|
path=$(lsof -a -g "$procgroup" -F n | grep node12/bin/node | grep externals | tail -1 | cut -c2-)
|
||||||
|
if [[ $? -eq 0 && -n "$path" ]]
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.1/node12/bin/node" ]]
|
then
|
||||||
then
|
# trim the last 5 characters of the path '/node'
|
||||||
mkdir -p "$rootfolder/externals.2.280.1/node12/bin"
|
trimmedpath=$(dirname "$path")
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.1/node12/bin/node"
|
if [[ $? -eq 0 && -n "$trimmedpath" ]]
|
||||||
fi
|
then
|
||||||
|
attemptedtargetedfix=1
|
||||||
if [[ ! -e "$rootfolder/externals.2.279.0/node12/bin/node" ]]
|
# Create the path if it does not exist
|
||||||
then
|
if [[ ! -e "$path" ]]
|
||||||
mkdir -p "$rootfolder/externals.2.279.0/node12/bin"
|
then
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.279.0/node12/bin/node"
|
date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1
|
||||||
fi
|
mkdir -p "$trimmedpath"
|
||||||
|
cp "$rootfolder/externals/node12/bin/node" "$path"
|
||||||
if [[ ! -e "$rootfolder/externals.2.278.0/node12/bin/node" ]]
|
else
|
||||||
then
|
date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1
|
||||||
mkdir -p "$rootfolder/externals.2.278.0/node12/bin"
|
fi
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.278.0/node12/bin/node"
|
else
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
runproc=$(ps x -o pgid,command | grep "run.sh" | grep -v grep | awk '{print $1}')
|
||||||
|
if [[ $? -eq 0 && -n "$runproc" ]]
|
||||||
|
then
|
||||||
|
date "+[%F %T-%4N] Running as ephemeral using run.sh, no need to recreate node folder" >> "$logfile" 2>&1
|
||||||
|
else
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
||||||
|
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check dotnet core 3.0 dependencies for Linux
|
# Check dotnet Core 6.0 dependencies for Linux
|
||||||
if [[ (`uname` == "Linux") ]]
|
if [[ (`uname` == "Linux") ]]
|
||||||
then
|
then
|
||||||
command -v ldd > /dev/null
|
command -v ldd > /dev/null
|
||||||
@@ -18,25 +18,25 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
message="Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
message="Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies."
|
||||||
|
|
||||||
ldd ./bin/libcoreclr.so | grep 'not found'
|
ldd ./bin/libcoreclr.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||||
echo $message
|
echo $message
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/System.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
ldd ./bin/libSystem.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||||
echo $message
|
echo $message
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/System.IO.Compression.Native.so | grep 'not found'
|
ldd ./bin/libSystem.IO.Compression.Native.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||||
echo $message
|
echo $message
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -54,7 +54,7 @@ then
|
|||||||
libpath=${LD_LIBRARY_PATH:-}
|
libpath=${LD_LIBRARY_PATH:-}
|
||||||
$LDCONFIG_COMMAND -NXv ${libpath//:/ } 2>&1 | grep libicu >/dev/null 2>&1
|
$LDCONFIG_COMMAND -NXv ${libpath//:/ } 2>&1 | grep libicu >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Libicu's dependencies is missing for Dotnet Core 3.0"
|
echo "Libicu's dependencies is missing for Dotnet Core 6.0"
|
||||||
echo $message
|
echo $message
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
39
src/Misc/layoutroot/run-helper.cmd.template
Normal file
39
src/Misc/layoutroot/run-helper.cmd.template
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
"%~dp0\bin\Runner.Listener.exe" run %*
|
||||||
|
|
||||||
|
rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
|
||||||
|
rem `if ERRORLEVEL N` means: error level is N or MORE
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 0 (
|
||||||
|
echo "Runner listener exit with 0 return code, stop the service, no retry needed."
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 1 (
|
||||||
|
echo "Runner listener exit with terminated error, stop the service, no retry needed."
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 2 (
|
||||||
|
echo "Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
||||||
|
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 3 (
|
||||||
|
rem Sleep 5 seconds to wait for the runner update process finish
|
||||||
|
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
||||||
|
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 4 (
|
||||||
|
rem Sleep 5 seconds to wait for the ephemeral runner update process finish
|
||||||
|
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
||||||
|
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Exiting after unknown error code: %ERRORLEVEL%"
|
||||||
|
exit /b 0
|
||||||
54
src/Misc/layoutroot/run-helper.sh.template
Executable file
54
src/Misc/layoutroot/run-helper.sh.template
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Validate not sudo
|
||||||
|
user_id=`id -u`
|
||||||
|
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
||||||
|
echo "Must not run interactively with sudo"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run
|
||||||
|
shopt -s nocasematch
|
||||||
|
|
||||||
|
safe_sleep() {
|
||||||
|
if [ ! -x "$(command -v sleep)" ]; then
|
||||||
|
if [ ! -x "$(command -v ping)" ]; then
|
||||||
|
COUNT="0"
|
||||||
|
while [[ $COUNT != 5000 ]]; do
|
||||||
|
echo "SLEEP" > /dev/null
|
||||||
|
COUNT=$[$COUNT+1]
|
||||||
|
done
|
||||||
|
else
|
||||||
|
ping -c 5 127.0.0.1 > /dev/null
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
bin/Runner.Listener run $*
|
||||||
|
returnCode=$?
|
||||||
|
if [[ $returnCode == 0 ]]; then
|
||||||
|
echo "Runner listener exit with 0 return code, stop the service, no retry needed."
|
||||||
|
exit 0
|
||||||
|
elif [[ $returnCode == 1 ]]; then
|
||||||
|
echo "Runner listener exit with terminated error, stop the service, no retry needed."
|
||||||
|
exit 0
|
||||||
|
elif [[ $returnCode == 2 ]]; then
|
||||||
|
echo "Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
||||||
|
safe_sleep
|
||||||
|
exit 1
|
||||||
|
elif [[ $returnCode == 3 ]]; then
|
||||||
|
# Sleep 5 seconds to wait for the runner update process finish
|
||||||
|
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
||||||
|
safe_sleep
|
||||||
|
exit 1
|
||||||
|
elif [[ $returnCode == 4 ]]; then
|
||||||
|
# Sleep 5 seconds to wait for the ephemeral runner update process finish
|
||||||
|
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
||||||
|
safe_sleep
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Exiting with unknown error code: ${returnCode}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
@@ -13,21 +13,19 @@ if defined VERBOSE_ARG (
|
|||||||
rem Unblock files in the root of the layout folder. E.g. .cmd files.
|
rem Unblock files in the root of the layout folder. E.g. .cmd files.
|
||||||
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"
|
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"
|
||||||
|
|
||||||
if /i "%~1" equ "localRun" (
|
|
||||||
rem ********************************************************************************
|
|
||||||
rem Local run.
|
|
||||||
rem ********************************************************************************
|
|
||||||
"%~dp0bin\Runner.Listener.exe" %*
|
|
||||||
) else (
|
|
||||||
rem ********************************************************************************
|
|
||||||
rem Run.
|
|
||||||
rem ********************************************************************************
|
|
||||||
"%~dp0bin\Runner.Listener.exe" run %*
|
|
||||||
|
|
||||||
rem Return code 4 means the run once runner received an update message.
|
rem ********************************************************************************
|
||||||
rem Sleep 5 seconds to wait for the update process finish and run the runner again.
|
rem Run.
|
||||||
if ERRORLEVEL 4 (
|
rem ********************************************************************************
|
||||||
timeout /t 5 /nobreak > NUL
|
|
||||||
"%~dp0bin\Runner.Listener.exe" run %*
|
:launch_helper
|
||||||
)
|
copy run-helper.cmd.template run-helper.cmd /Y
|
||||||
|
call "%~dp0run-helper.cmd" %*
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 1 (
|
||||||
|
echo "Restarting runner..."
|
||||||
|
goto :launch_helper
|
||||||
|
) else (
|
||||||
|
echo "Exiting runner..."
|
||||||
|
exit 0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,49 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Validate not sudo
|
|
||||||
user_id=`id -u`
|
|
||||||
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
|
||||||
echo "Must not run interactively with sudo"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Change directory to the script root directory
|
# Change directory to the script root directory
|
||||||
# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within
|
# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within
|
||||||
SOURCE="${BASH_SOURCE[0]}"
|
SOURCE="${BASH_SOURCE[0]}"
|
||||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
SOURCE="$(readlink "$SOURCE")"
|
SOURCE="$(readlink "$SOURCE")"
|
||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
cp -f run-helper.sh.template run-helper.sh
|
||||||
# Do not "cd $DIR". For localRun, the current directory is expected to be the repo location on disk.
|
# run the helper process which keep the listener alive
|
||||||
|
while :;
|
||||||
# Run
|
do
|
||||||
shopt -s nocasematch
|
"$DIR"/run-helper.sh $*
|
||||||
if [[ "$1" == "localRun" ]]; then
|
|
||||||
"$DIR"/bin/Runner.Listener $*
|
|
||||||
else
|
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
|
||||||
|
|
||||||
# Return code 3 means the run once runner received an update message.
|
|
||||||
# Sleep 5 seconds to wait for the update process finish
|
|
||||||
returnCode=$?
|
returnCode=$?
|
||||||
if [[ $returnCode == 3 ]]; then
|
if [[ $returnCode == 1 ]]; then
|
||||||
if [ ! -x "$(command -v sleep)" ]; then
|
echo "Restarting runner..."
|
||||||
if [ ! -x "$(command -v ping)" ]; then
|
|
||||||
COUNT="0"
|
|
||||||
while [[ $COUNT != 5000 ]]; do
|
|
||||||
echo "SLEEP" > /dev/null
|
|
||||||
COUNT=$[$COUNT+1]
|
|
||||||
done
|
|
||||||
else
|
|
||||||
ping -c 5 127.0.0.1 > /dev/null
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sleep 5
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
exit $returnCode
|
echo "Exiting runner..."
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
|
|||||||
57
src/Misc/runnercoreassets
Normal file
57
src/Misc/runnercoreassets
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
actions.runner.plist.template
|
||||||
|
actions.runner.service.template
|
||||||
|
checkScripts/downloadCert.js
|
||||||
|
checkScripts/makeWebRequest.js
|
||||||
|
darwin.svc.sh.template
|
||||||
|
hashFiles/index.js
|
||||||
|
installdependencies.sh
|
||||||
|
macos-run-invoker.js
|
||||||
|
Microsoft.IdentityModel.Logging.dll
|
||||||
|
Microsoft.IdentityModel.Tokens.dll
|
||||||
|
Minimatch.dll
|
||||||
|
Newtonsoft.Json.Bson.dll
|
||||||
|
Newtonsoft.Json.dll
|
||||||
|
Runner.Common.deps.json
|
||||||
|
Runner.Common.dll
|
||||||
|
Runner.Common.pdb
|
||||||
|
Runner.Listener
|
||||||
|
Runner.Listener.deps.json
|
||||||
|
Runner.Listener.dll
|
||||||
|
Runner.Listener.exe
|
||||||
|
Runner.Listener.pdb
|
||||||
|
Runner.Listener.runtimeconfig.json
|
||||||
|
Runner.PluginHost
|
||||||
|
Runner.PluginHost.deps.json
|
||||||
|
Runner.PluginHost.dll
|
||||||
|
Runner.PluginHost.exe
|
||||||
|
Runner.PluginHost.pdb
|
||||||
|
Runner.PluginHost.runtimeconfig.json
|
||||||
|
Runner.Plugins.deps.json
|
||||||
|
Runner.Plugins.dll
|
||||||
|
Runner.Plugins.pdb
|
||||||
|
Runner.Sdk.deps.json
|
||||||
|
Runner.Sdk.dll
|
||||||
|
Runner.Sdk.pdb
|
||||||
|
Runner.Worker
|
||||||
|
Runner.Worker.deps.json
|
||||||
|
Runner.Worker.dll
|
||||||
|
Runner.Worker.exe
|
||||||
|
Runner.Worker.pdb
|
||||||
|
Runner.Worker.runtimeconfig.json
|
||||||
|
RunnerService.exe
|
||||||
|
RunnerService.exe.config
|
||||||
|
RunnerService.js
|
||||||
|
RunnerService.pdb
|
||||||
|
runsvc.sh
|
||||||
|
Sdk.deps.json
|
||||||
|
Sdk.dll
|
||||||
|
Sdk.pdb
|
||||||
|
System.IdentityModel.Tokens.Jwt.dll
|
||||||
|
System.Net.Http.Formatting.dll
|
||||||
|
System.Security.Cryptography.Pkcs.dll
|
||||||
|
System.Security.Cryptography.ProtectedData.dll
|
||||||
|
System.ServiceProcess.ServiceController.dll
|
||||||
|
systemd.svc.sh.template
|
||||||
|
update.cmd.template
|
||||||
|
update.sh.template
|
||||||
|
YamlDotNet.dll
|
||||||
263
src/Misc/runnerdotnetruntimeassets
Normal file
263
src/Misc/runnerdotnetruntimeassets
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
api-ms-win-core-console-l1-1-0.dll
|
||||||
|
api-ms-win-core-console-l1-2-0.dll
|
||||||
|
api-ms-win-core-datetime-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-file-l1-1-0.dll
|
||||||
|
api-ms-win-core-file-l1-2-0.dll
|
||||||
|
api-ms-win-core-file-l2-1-0.dll
|
||||||
|
api-ms-win-core-handle-l1-1-0.dll
|
||||||
|
api-ms-win-core-heap-l1-1-0.dll
|
||||||
|
api-ms-win-core-interlocked-l1-1-0.dll
|
||||||
|
api-ms-win-core-libraryloader-l1-1-0.dll
|
||||||
|
api-ms-win-core-localization-l1-2-0.dll
|
||||||
|
api-ms-win-core-memory-l1-1-0.dll
|
||||||
|
api-ms-win-core-namedpipe-l1-1-0.dll
|
||||||
|
api-ms-win-core-processenvironment-l1-1-0.dll
|
||||||
|
api-ms-win-core-processthreads-l1-1-0.dll
|
||||||
|
api-ms-win-core-processthreads-l1-1-1.dll
|
||||||
|
api-ms-win-core-profile-l1-1-0.dll
|
||||||
|
api-ms-win-core-rtlsupport-l1-1-0.dll
|
||||||
|
api-ms-win-core-string-l1-1-0.dll
|
||||||
|
api-ms-win-core-synch-l1-1-0.dll
|
||||||
|
api-ms-win-core-synch-l1-2-0.dll
|
||||||
|
api-ms-win-core-sysinfo-l1-1-0.dll
|
||||||
|
api-ms-win-core-timezone-l1-1-0.dll
|
||||||
|
api-ms-win-core-util-l1-1-0.dll
|
||||||
|
api-ms-win-crt-conio-l1-1-0.dll
|
||||||
|
api-ms-win-crt-convert-l1-1-0.dll
|
||||||
|
api-ms-win-crt-environment-l1-1-0.dll
|
||||||
|
api-ms-win-crt-filesystem-l1-1-0.dll
|
||||||
|
api-ms-win-crt-heap-l1-1-0.dll
|
||||||
|
api-ms-win-crt-locale-l1-1-0.dll
|
||||||
|
api-ms-win-crt-math-l1-1-0.dll
|
||||||
|
api-ms-win-crt-multibyte-l1-1-0.dll
|
||||||
|
api-ms-win-crt-private-l1-1-0.dll
|
||||||
|
api-ms-win-crt-process-l1-1-0.dll
|
||||||
|
api-ms-win-crt-runtime-l1-1-0.dll
|
||||||
|
api-ms-win-crt-stdio-l1-1-0.dll
|
||||||
|
api-ms-win-crt-string-l1-1-0.dll
|
||||||
|
api-ms-win-crt-time-l1-1-0.dll
|
||||||
|
api-ms-win-crt-utility-l1-1-0.dll
|
||||||
|
clrcompression.dll
|
||||||
|
clretwrc.dll
|
||||||
|
clrjit.dll
|
||||||
|
coreclr.dll
|
||||||
|
createdump
|
||||||
|
createdump.exe
|
||||||
|
dbgshim.dll
|
||||||
|
hostfxr.dll
|
||||||
|
hostpolicy.dll
|
||||||
|
libclrjit.dylib
|
||||||
|
libclrjit.so
|
||||||
|
libcoreclr.dylib
|
||||||
|
libcoreclr.so
|
||||||
|
libcoreclrtraceptprovider.so
|
||||||
|
libdbgshim.dylib
|
||||||
|
libdbgshim.so
|
||||||
|
libhostfxr.dylib
|
||||||
|
libhostfxr.so
|
||||||
|
libhostpolicy.dylib
|
||||||
|
libhostpolicy.so
|
||||||
|
libmscordaccore.dylib
|
||||||
|
libmscordaccore.so
|
||||||
|
libmscordbi.dylib
|
||||||
|
libmscordbi.so
|
||||||
|
Microsoft.CSharp.dll
|
||||||
|
Microsoft.DiaSymReader.Native.amd64.dll
|
||||||
|
Microsoft.VisualBasic.Core.dll
|
||||||
|
Microsoft.VisualBasic.dll
|
||||||
|
Microsoft.Win32.Primitives.dll
|
||||||
|
Microsoft.Win32.Registry.dll
|
||||||
|
mscordaccore.dll
|
||||||
|
mscordaccore_amd64_amd64_6.0.21.52210.dll
|
||||||
|
mscordbi.dll
|
||||||
|
mscorlib.dll
|
||||||
|
mscorrc.debug.dll
|
||||||
|
mscorrc.dll
|
||||||
|
msquic.dll
|
||||||
|
netstandard.dll
|
||||||
|
SOS_README.md
|
||||||
|
System.AppContext.dll
|
||||||
|
System.Buffers.dll
|
||||||
|
System.Collections.Concurrent.dll
|
||||||
|
System.Collections.dll
|
||||||
|
System.Collections.Immutable.dll
|
||||||
|
System.Collections.NonGeneric.dll
|
||||||
|
System.Collections.Specialized.dll
|
||||||
|
System.ComponentModel.Annotations.dll
|
||||||
|
System.ComponentModel.DataAnnotations.dll
|
||||||
|
System.ComponentModel.dll
|
||||||
|
System.ComponentModel.EventBasedAsync.dll
|
||||||
|
System.ComponentModel.Primitives.dll
|
||||||
|
System.ComponentModel.TypeConverter.dll
|
||||||
|
System.Configuration.dll
|
||||||
|
System.Console.dll
|
||||||
|
System.Core.dll
|
||||||
|
System.Data.Common.dll
|
||||||
|
System.Data.DataSetExtensions.dll
|
||||||
|
System.Data.dll
|
||||||
|
System.Diagnostics.Contracts.dll
|
||||||
|
System.Diagnostics.Debug.dll
|
||||||
|
System.Diagnostics.DiagnosticSource.dll
|
||||||
|
System.Diagnostics.FileVersionInfo.dll
|
||||||
|
System.Diagnostics.Process.dll
|
||||||
|
System.Diagnostics.StackTrace.dll
|
||||||
|
System.Diagnostics.TextWriterTraceListener.dll
|
||||||
|
System.Diagnostics.Tools.dll
|
||||||
|
System.Diagnostics.TraceSource.dll
|
||||||
|
System.Diagnostics.Tracing.dll
|
||||||
|
System.dll
|
||||||
|
System.Drawing.dll
|
||||||
|
System.Drawing.Primitives.dll
|
||||||
|
System.Dynamic.Runtime.dll
|
||||||
|
System.Formats.Asn1.dll
|
||||||
|
System.Globalization.Calendars.dll
|
||||||
|
System.Globalization.dll
|
||||||
|
System.Globalization.Extensions.dll
|
||||||
|
System.Globalization.Native.dylib
|
||||||
|
System.Globalization.Native.so
|
||||||
|
System.IO.Compression.Brotli.dll
|
||||||
|
System.IO.Compression.dll
|
||||||
|
System.IO.Compression.FileSystem.dll
|
||||||
|
System.IO.Compression.Native.a
|
||||||
|
System.IO.Compression.Native.dll
|
||||||
|
System.IO.Compression.Native.dylib
|
||||||
|
System.IO.Compression.Native.so
|
||||||
|
System.IO.Compression.ZipFile.dll
|
||||||
|
System.IO.dll
|
||||||
|
System.IO.FileSystem.AccessControl.dll
|
||||||
|
System.IO.FileSystem.dll
|
||||||
|
System.IO.FileSystem.DriveInfo.dll
|
||||||
|
System.IO.FileSystem.Primitives.dll
|
||||||
|
System.IO.FileSystem.Watcher.dll
|
||||||
|
System.IO.IsolatedStorage.dll
|
||||||
|
System.IO.MemoryMappedFiles.dll
|
||||||
|
System.IO.Pipes.AccessControl.dll
|
||||||
|
System.IO.Pipes.dll
|
||||||
|
System.IO.UnmanagedMemoryStream.dll
|
||||||
|
System.Linq.dll
|
||||||
|
System.Linq.Expressions.dll
|
||||||
|
System.Linq.Parallel.dll
|
||||||
|
System.Linq.Queryable.dll
|
||||||
|
System.Memory.dll
|
||||||
|
System.Native.a
|
||||||
|
System.Native.dylib
|
||||||
|
System.Native.so
|
||||||
|
System.Net.dll
|
||||||
|
System.Net.Http.dll
|
||||||
|
System.Net.Http.Json.dll
|
||||||
|
System.Net.Http.Native.a
|
||||||
|
System.Net.Http.Native.dylib
|
||||||
|
System.Net.Http.Native.so
|
||||||
|
System.Net.HttpListener.dll
|
||||||
|
System.Net.Mail.dll
|
||||||
|
System.Net.NameResolution.dll
|
||||||
|
System.Net.NetworkInformation.dll
|
||||||
|
System.Net.Ping.dll
|
||||||
|
System.Net.Primitives.dll
|
||||||
|
System.Net.Quic.dll
|
||||||
|
System.Net.Requests.dll
|
||||||
|
System.Net.Security.dll
|
||||||
|
System.Net.Security.Native.a
|
||||||
|
System.Net.Security.Native.dylib
|
||||||
|
System.Net.Security.Native.so
|
||||||
|
System.Net.ServicePoint.dll
|
||||||
|
System.Net.Sockets.dll
|
||||||
|
System.Net.WebClient.dll
|
||||||
|
System.Net.WebHeaderCollection.dll
|
||||||
|
System.Net.WebProxy.dll
|
||||||
|
System.Net.WebSockets.Client.dll
|
||||||
|
System.Net.WebSockets.dll
|
||||||
|
System.Numerics.dll
|
||||||
|
System.Numerics.Vectors.dll
|
||||||
|
System.ObjectModel.dll
|
||||||
|
System.Private.CoreLib.dll
|
||||||
|
System.Private.DataContractSerialization.dll
|
||||||
|
System.Private.Uri.dll
|
||||||
|
System.Private.Xml.dll
|
||||||
|
System.Private.Xml.Linq.dll
|
||||||
|
System.Reflection.DispatchProxy.dll
|
||||||
|
System.Reflection.dll
|
||||||
|
System.Reflection.Emit.dll
|
||||||
|
System.Reflection.Emit.ILGeneration.dll
|
||||||
|
System.Reflection.Emit.Lightweight.dll
|
||||||
|
System.Reflection.Extensions.dll
|
||||||
|
System.Reflection.Metadata.dll
|
||||||
|
System.Reflection.Primitives.dll
|
||||||
|
System.Reflection.TypeExtensions.dll
|
||||||
|
System.Resources.Reader.dll
|
||||||
|
System.Resources.ResourceManager.dll
|
||||||
|
System.Resources.Writer.dll
|
||||||
|
System.Runtime.CompilerServices.Unsafe.dll
|
||||||
|
System.Runtime.CompilerServices.VisualC.dll
|
||||||
|
System.Runtime.dll
|
||||||
|
System.Runtime.Extensions.dll
|
||||||
|
System.Runtime.Handles.dll
|
||||||
|
System.Runtime.InteropServices.dll
|
||||||
|
System.Runtime.InteropServices.RuntimeInformation.dll
|
||||||
|
System.Runtime.InteropServices.WindowsRuntime.dll
|
||||||
|
System.Runtime.Intrinsics.dll
|
||||||
|
System.Runtime.Loader.dll
|
||||||
|
System.Runtime.Numerics.dll
|
||||||
|
System.Runtime.Serialization.dll
|
||||||
|
System.Runtime.Serialization.Formatters.dll
|
||||||
|
System.Runtime.Serialization.Json.dll
|
||||||
|
System.Runtime.Serialization.Primitives.dll
|
||||||
|
System.Runtime.Serialization.Xml.dll
|
||||||
|
System.Runtime.WindowsRuntime.dll
|
||||||
|
System.Runtime.WindowsRuntime.UI.Xaml.dll
|
||||||
|
System.Security.AccessControl.dll
|
||||||
|
System.Security.Claims.dll
|
||||||
|
System.Security.Cryptography.Algorithms.dll
|
||||||
|
System.Security.Cryptography.Cng.dll
|
||||||
|
System.Security.Cryptography.Csp.dll
|
||||||
|
System.Security.Cryptography.Encoding.dll
|
||||||
|
System.Security.Cryptography.Native.Apple.a
|
||||||
|
System.Security.Cryptography.Native.Apple.dylib
|
||||||
|
System.Security.Cryptography.Native.OpenSsl.a
|
||||||
|
System.Security.Cryptography.Native.OpenSsl.dylib
|
||||||
|
System.Security.Cryptography.Native.OpenSsl.so
|
||||||
|
System.Security.Cryptography.OpenSsl.dll
|
||||||
|
System.Security.Cryptography.Primitives.dll
|
||||||
|
System.Security.Cryptography.X509Certificates.dll
|
||||||
|
System.Security.Cryptography.XCertificates.dll
|
||||||
|
System.Security.dll
|
||||||
|
System.Security.Principal.dll
|
||||||
|
System.Security.Principal.Windows.dll
|
||||||
|
System.Security.SecureString.dll
|
||||||
|
System.ServiceModel.Web.dll
|
||||||
|
System.ServiceProcess.dll
|
||||||
|
System.Text.Encoding.CodePages.dll
|
||||||
|
System.Text.Encoding.dll
|
||||||
|
System.Text.Encoding.Extensions.dll
|
||||||
|
System.Text.Encodings.Web.dll
|
||||||
|
System.Text.Json.dll
|
||||||
|
System.Text.RegularExpressions.dll
|
||||||
|
System.Threading.Channels.dll
|
||||||
|
System.Threading.dll
|
||||||
|
System.Threading.Overlapped.dll
|
||||||
|
System.Threading.Tasks.Dataflow.dll
|
||||||
|
System.Threading.Tasks.dll
|
||||||
|
System.Threading.Tasks.Extensions.dll
|
||||||
|
System.Threading.Tasks.Parallel.dll
|
||||||
|
System.Threading.Thread.dll
|
||||||
|
System.Threading.ThreadPool.dll
|
||||||
|
System.Threading.Timer.dll
|
||||||
|
System.Transactions.dll
|
||||||
|
System.Transactions.Local.dll
|
||||||
|
System.ValueTuple.dll
|
||||||
|
System.Web.dll
|
||||||
|
System.Web.HttpUtility.dll
|
||||||
|
System.Windows.dll
|
||||||
|
System.Xml.dll
|
||||||
|
System.Xml.Linq.dll
|
||||||
|
System.Xml.ReaderWriter.dll
|
||||||
|
System.Xml.Serialization.dll
|
||||||
|
System.Xml.XDocument.dll
|
||||||
|
System.Xml.XmlDocument.dll
|
||||||
|
System.Xml.XmlSerializer.dll
|
||||||
|
System.Xml.XPath.dll
|
||||||
|
System.Xml.XPath.XDocument.dll
|
||||||
|
ucrtbase.dll
|
||||||
|
WindowsBase.dll
|
||||||
24
src/Misc/trimmedpackages_targz.json
Normal file
24
src/Misc/trimmedpackages_targz.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_RUNTIME_EXTERNALS_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noruntime-noexternals.tar.gz",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"dotnetRuntime": "<RUNTIME_HASH>",
|
||||||
|
"externals": "<EXTERNALS_HASH>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_RUNTIME_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noruntime.tar.gz",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"dotnetRuntime": "<RUNTIME_HASH>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_EXTERNALS_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noexternals.tar.gz",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"externals": "<EXTERNALS_HASH>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
24
src/Misc/trimmedpackages_zip.json
Normal file
24
src/Misc/trimmedpackages_zip.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_RUNTIME_EXTERNALS_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noruntime-noexternals.zip",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"dotnetRuntime": "<RUNTIME_HASH>",
|
||||||
|
"externals": "<EXTERNALS_HASH>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_RUNTIME_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noruntime.zip",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"dotnetRuntime": "<RUNTIME_HASH>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HashValue": "<NO_EXTERNALS_HASH>",
|
||||||
|
"DownloadUrl": "https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-<RUNNER_PLATFORM>-<RUNNER_VERSION>-noexternals.zip",
|
||||||
|
"TrimmedContents": {
|
||||||
|
"externals": "<EXTERNALS_HASH>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -33,6 +33,9 @@ namespace GitHub.Runner.Common
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string PoolName { get; set; }
|
public string PoolName { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public bool DisableUpdate { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public bool Ephemeral { get; set; }
|
public bool Ephemeral { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace GitHub.Runner.Common
|
|||||||
Certificates,
|
Certificates,
|
||||||
Options,
|
Options,
|
||||||
SetupInfo,
|
SetupInfo,
|
||||||
|
Telemetry
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Constants
|
public static class Constants
|
||||||
@@ -128,7 +129,8 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string Ephemeral = "ephemeral";
|
public static readonly string Ephemeral = "ephemeral";
|
||||||
public static readonly string Help = "help";
|
public static readonly string Help = "help";
|
||||||
public static readonly string Replace = "replace";
|
public static readonly string Replace = "replace";
|
||||||
public static readonly string Once = "once"; // TODO: Remove in 10/2021
|
public static readonly string DisableUpdate = "disableupdate";
|
||||||
|
public static readonly string Once = "once"; // Keep this around since customers still relies on it
|
||||||
public static readonly string RunAsService = "runasservice";
|
public static readonly string RunAsService = "runasservice";
|
||||||
public static readonly string Unattended = "unattended";
|
public static readonly string Unattended = "unattended";
|
||||||
public static readonly string Version = "version";
|
public static readonly string Version = "version";
|
||||||
@@ -154,6 +156,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
||||||
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
||||||
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
|
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
|
||||||
|
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RunnerEvent
|
public static class RunnerEvent
|
||||||
@@ -213,6 +216,7 @@ namespace GitHub.Runner.Common
|
|||||||
// Keep alphabetical
|
// Keep alphabetical
|
||||||
//
|
//
|
||||||
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 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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ namespace GitHub.Runner.Common
|
|||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscape);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift1);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift1);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift2);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift2);
|
||||||
|
this.SecretMasker.AddValueEncoder(ValueEncoders.BashComparand);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.CommandLineArgumentEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.CommandLineArgumentEscape);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.ExpressionStringEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.ExpressionStringEscape);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.JsonStringEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.JsonStringEscape);
|
||||||
@@ -98,14 +99,14 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
int logPageSize;
|
int logPageSize;
|
||||||
string logSizeEnv = Environment.GetEnvironmentVariable($"{hostType.ToUpperInvariant()}_LOGSIZE");
|
string logSizeEnv = Environment.GetEnvironmentVariable($"{hostType.ToUpperInvariant()}_LOGSIZE");
|
||||||
if (!string.IsNullOrEmpty(logSizeEnv) || !int.TryParse(logSizeEnv, out logPageSize))
|
if (string.IsNullOrEmpty(logSizeEnv) || !int.TryParse(logSizeEnv, out logPageSize))
|
||||||
{
|
{
|
||||||
logPageSize = _defaultLogPageSize;
|
logPageSize = _defaultLogPageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int logRetentionDays;
|
int logRetentionDays;
|
||||||
string logRetentionDaysEnv = Environment.GetEnvironmentVariable($"{hostType.ToUpperInvariant()}_LOGRETENTION");
|
string logRetentionDaysEnv = Environment.GetEnvironmentVariable($"{hostType.ToUpperInvariant()}_LOGRETENTION");
|
||||||
if (!string.IsNullOrEmpty(logRetentionDaysEnv) || !int.TryParse(logRetentionDaysEnv, out logRetentionDays))
|
if (string.IsNullOrEmpty(logRetentionDaysEnv) || !int.TryParse(logRetentionDaysEnv, out logRetentionDays))
|
||||||
{
|
{
|
||||||
logRetentionDays = _defaultLogRetentionDays;
|
logRetentionDays = _defaultLogRetentionDays;
|
||||||
}
|
}
|
||||||
@@ -193,6 +194,11 @@ namespace GitHub.Runner.Common
|
|||||||
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
||||||
|
{
|
||||||
|
_trace.Warning($"Runner is running under insecure mode: HTTPS server certifcate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable.");
|
||||||
|
}
|
||||||
|
|
||||||
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
||||||
if (File.Exists(credFile))
|
if (File.Exists(credFile))
|
||||||
{
|
{
|
||||||
@@ -200,9 +206,17 @@ namespace GitHub.Runner.Common
|
|||||||
if (credData != null &&
|
if (credData != null &&
|
||||||
credData.Data.TryGetValue("clientId", out var clientId))
|
credData.Data.TryGetValue("clientId", out var clientId))
|
||||||
{
|
{
|
||||||
_userAgents.Add(new ProductInfoHeaderValue($"RunnerId", clientId));
|
_userAgents.Add(new ProductInfoHeaderValue("ClientId", clientId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var runnerFile = GetConfigFile(WellKnownConfigFile.Runner);
|
||||||
|
if (File.Exists(runnerFile))
|
||||||
|
{
|
||||||
|
var runnerSettings = IOUtil.LoadObject<RunnerSettings>(runnerFile);
|
||||||
|
_userAgents.Add(new ProductInfoHeaderValue("RunnerId", runnerSettings.AgentId.ToString(CultureInfo.InvariantCulture)));
|
||||||
|
_userAgents.Add(new ProductInfoHeaderValue("GroupId", runnerSettings.PoolId.ToString(CultureInfo.InvariantCulture)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDirectory(WellKnownDirectory directory)
|
public string GetDirectory(WellKnownDirectory directory)
|
||||||
@@ -343,6 +357,12 @@ namespace GitHub.Runner.Common
|
|||||||
".setup_info");
|
".setup_info");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WellKnownConfigFile.Telemetry:
|
||||||
|
path = Path.Combine(
|
||||||
|
GetDirectory(WellKnownDirectory.Diag),
|
||||||
|
".telemetry");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Unexpected well known config file: '{configFile}'");
|
throw new NotSupportedException($"Unexpected well known config file: '{configFile}'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
@@ -13,7 +14,14 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
public HttpClientHandler CreateClientHandler(RunnerWebProxy webProxy)
|
public HttpClientHandler CreateClientHandler(RunnerWebProxy webProxy)
|
||||||
{
|
{
|
||||||
return new HttpClientHandler() { Proxy = webProxy };
|
var client = new HttpClientHandler() { Proxy = webProxy };
|
||||||
|
|
||||||
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
||||||
|
{
|
||||||
|
client.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Services.Common;
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
@@ -35,7 +38,11 @@ namespace GitHub.Runner.Common
|
|||||||
public async Task ConnectAsync(VssConnection jobConnection)
|
public async Task ConnectAsync(VssConnection jobConnection)
|
||||||
{
|
{
|
||||||
_connection = jobConnection;
|
_connection = jobConnection;
|
||||||
int attemptCount = 5;
|
int totalAttempts = 5;
|
||||||
|
int attemptCount = totalAttempts;
|
||||||
|
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||||
|
var runnerSettings = configurationStore.GetSettings();
|
||||||
|
|
||||||
while (!_connection.HasAuthenticated && attemptCount-- > 0)
|
while (!_connection.HasAuthenticated && attemptCount-- > 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -45,17 +52,71 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
catch (Exception ex) when (attemptCount > 0)
|
catch (Exception ex) when (attemptCount > 0)
|
||||||
{
|
{
|
||||||
Trace.Info($"Catch exception during connect. {attemptCount} attemp left.");
|
Trace.Info($"Catch exception during connect. {attemptCount} attempts left.");
|
||||||
Trace.Error(ex);
|
Trace.Error(ex);
|
||||||
|
|
||||||
|
if (runnerSettings.IsHostedServer)
|
||||||
|
{
|
||||||
|
await CheckNetworkEndpointsAsync(attemptCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(100);
|
int attempt = totalAttempts - attemptCount;
|
||||||
|
TimeSpan backoff = BackoffTimerHelper.GetExponentialBackoff(attempt, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(3.2), TimeSpan.FromMilliseconds(100));
|
||||||
|
|
||||||
|
await Task.Delay(backoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
_taskClient = _connection.GetClient<TaskHttpClient>();
|
_taskClient = _connection.GetClient<TaskHttpClient>();
|
||||||
_hasConnection = true;
|
_hasConnection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CheckNetworkEndpointsAsync(int attemptsLeft)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trace.Info("Requesting Actions Service health endpoint status");
|
||||||
|
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||||
|
using (var actionsClient = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
var baseUri = new Uri(_connection.Uri.GetLeftPart(UriPartial.Authority));
|
||||||
|
|
||||||
|
actionsClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
|
|
||||||
|
// Call the _apis/health endpoint, and include how many attempts are left as a URL query for easy tracking
|
||||||
|
var response = await actionsClient.GetAsync(new Uri(baseUri, $"_apis/health?_internalRunnerAttemptsLeft={attemptsLeft}"));
|
||||||
|
Trace.Info($"Actions health status code: {response.StatusCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log error, but continue as this call is best-effort
|
||||||
|
Trace.Info($"Actions Service health endpoint failed due to {ex.GetType().Name}");
|
||||||
|
Trace.Error(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trace.Info("Requesting Github API endpoint status");
|
||||||
|
// This is a dotcom public API... just call it directly
|
||||||
|
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||||
|
using (var gitHubClient = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
gitHubClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
|
|
||||||
|
// Call the api.github.com endpoint, and include how many attempts are left as a URL query for easy tracking
|
||||||
|
var response = await gitHubClient.GetAsync($"https://api.github.com?_internalRunnerAttemptsLeft={attemptsLeft}");
|
||||||
|
Trace.Info($"api.github.com status code: {response.StatusCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log error, but continue as this call is best-effort
|
||||||
|
Trace.Info($"Github API endpoint failed due to {ex.GetType().Name}");
|
||||||
|
Trace.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void CheckConnection()
|
private void CheckConnection()
|
||||||
{
|
{
|
||||||
if (!_hasConnection)
|
if (!_hasConnection)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Runner.Common.Util;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -76,6 +75,7 @@ namespace GitHub.Runner.Common
|
|||||||
// at the same time we can cut the load to server after the build run for more than 60s
|
// at the same time we can cut the load to server after the build run for more than 60s
|
||||||
private int _webConsoleLineAggressiveDequeueCount = 0;
|
private int _webConsoleLineAggressiveDequeueCount = 0;
|
||||||
private const int _webConsoleLineAggressiveDequeueLimit = 4 * 60;
|
private const int _webConsoleLineAggressiveDequeueLimit = 4 * 60;
|
||||||
|
private const int _webConsoleLineQueueSizeLimit = 1024;
|
||||||
private bool _webConsoleLineAggressiveDequeue = true;
|
private bool _webConsoleLineAggressiveDequeue = true;
|
||||||
private bool _firstConsoleOutputs = true;
|
private bool _firstConsoleOutputs = true;
|
||||||
|
|
||||||
@@ -161,8 +161,20 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
|
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
|
||||||
{
|
{
|
||||||
Trace.Verbose("Enqueue web console line queue: {0}", line);
|
// We only process 500 lines of the queue everytime.
|
||||||
_webConsoleLineQueue.Enqueue(new ConsoleLineInfo(stepRecordId, line, lineNumber));
|
// If the queue is backing up due to slow Http request or flood of output from step,
|
||||||
|
// we will drop the output to avoid extra memory consumption from the runner since the live console feed is best effort.
|
||||||
|
if (!string.IsNullOrEmpty(line) && _webConsoleLineQueue.Count < _webConsoleLineQueueSizeLimit)
|
||||||
|
{
|
||||||
|
Trace.Verbose("Enqueue web console line queue: {0}", line);
|
||||||
|
if (line.Length > 1024)
|
||||||
|
{
|
||||||
|
Trace.Verbose("Web console line is more than 1024 chars, truncate to first 1024 chars");
|
||||||
|
line = $"{line.Substring(0, 1024)}...";
|
||||||
|
}
|
||||||
|
|
||||||
|
_webConsoleLineQueue.Enqueue(new ConsoleLineInfo(stepRecordId, line, lineNumber));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource)
|
public void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource)
|
||||||
@@ -230,12 +242,6 @@ namespace GitHub.Runner.Common
|
|||||||
stepRecordIds.Add(lineInfo.StepRecordId);
|
stepRecordIds.Add(lineInfo.StepRecordId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(lineInfo.Line) && lineInfo.Line.Length > 1024)
|
|
||||||
{
|
|
||||||
Trace.Verbose("Web console line is more than 1024 chars, truncate to first 1024 chars");
|
|
||||||
lineInfo.Line = $"{lineInfo.Line.Substring(0, 1024)}...";
|
|
||||||
}
|
|
||||||
|
|
||||||
stepsConsoleLines[lineInfo.StepRecordId].Add(new TimelineRecordLogLine(lineInfo.Line, lineInfo.LineNumber));
|
stepsConsoleLines[lineInfo.StepRecordId].Add(new TimelineRecordLogLine(lineInfo.Line, lineInfo.LineNumber));
|
||||||
linesCounter++;
|
linesCounter++;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ namespace GitHub.Runner.Common
|
|||||||
// Configuration
|
// Configuration
|
||||||
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
||||||
Task DeleteAgentAsync(int agentPoolId, int agentId);
|
Task DeleteAgentAsync(int agentPoolId, int agentId);
|
||||||
|
Task DeleteAgentAsync(int agentId);
|
||||||
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
||||||
|
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
||||||
Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent);
|
Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent);
|
||||||
|
|
||||||
// messagequeue
|
// messagequeue
|
||||||
@@ -49,7 +51,7 @@ namespace GitHub.Runner.Common
|
|||||||
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent update
|
// agent update
|
||||||
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState);
|
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RunnerServer : RunnerService, IRunnerServer
|
public sealed class RunnerServer : RunnerService, IRunnerServer
|
||||||
@@ -252,6 +254,11 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
|
||||||
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
@@ -264,6 +271,11 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task DeleteAgentAsync(int agentId)
|
||||||
|
{
|
||||||
|
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// MessageQueue
|
// MessageQueue
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
@@ -329,25 +341,10 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState)
|
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState);
|
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// Runner Auth Url
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
public Task<string> GetRunnerAuthUrlAsync(int runnerPoolId, int runnerId)
|
|
||||||
{
|
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
|
||||||
return _messageTaskAgentClient.GetAgentAuthUrlAsync(runnerPoolId, runnerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ReportRunnerAuthUrlErrorAsync(int runnerPoolId, int runnerId, string error)
|
|
||||||
{
|
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
|
||||||
return _messageTaskAgentClient.ReportAgentAuthUrlMigrationErrorAsync(runnerPoolId, runnerId, error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
Constants.Runner.CommandLine.Flags.Check,
|
Constants.Runner.CommandLine.Flags.Check,
|
||||||
Constants.Runner.CommandLine.Flags.Commit,
|
Constants.Runner.CommandLine.Flags.Commit,
|
||||||
|
Constants.Runner.CommandLine.Flags.DisableUpdate,
|
||||||
Constants.Runner.CommandLine.Flags.Ephemeral,
|
Constants.Runner.CommandLine.Flags.Ephemeral,
|
||||||
Constants.Runner.CommandLine.Flags.Help,
|
Constants.Runner.CommandLine.Flags.Help,
|
||||||
|
Constants.Runner.CommandLine.Flags.Once,
|
||||||
Constants.Runner.CommandLine.Flags.Replace,
|
Constants.Runner.CommandLine.Flags.Replace,
|
||||||
Constants.Runner.CommandLine.Flags.RunAsService,
|
Constants.Runner.CommandLine.Flags.RunAsService,
|
||||||
Constants.Runner.CommandLine.Flags.Unattended,
|
Constants.Runner.CommandLine.Flags.Unattended,
|
||||||
@@ -67,8 +69,9 @@ namespace GitHub.Runner.Listener
|
|||||||
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
|
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
|
||||||
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
|
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
|
||||||
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
|
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
|
||||||
|
public bool DisableUpdate => TestFlag(Constants.Runner.CommandLine.Flags.DisableUpdate);
|
||||||
|
|
||||||
// TODO: Remove in 10/2021
|
// Keep this around since customers still relies on it
|
||||||
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
|
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
@@ -242,6 +245,7 @@ namespace GitHub.Runner.Listener
|
|||||||
validator: Validators.ServerUrlValidator);
|
validator: Validators.ServerUrlValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg)
|
public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg)
|
||||||
{
|
{
|
||||||
return GetArgOrPrompt(
|
return GetArgOrPrompt(
|
||||||
@@ -259,7 +263,7 @@ namespace GitHub.Runner.Listener
|
|||||||
defaultValue: string.Empty,
|
defaultValue: string.Empty,
|
||||||
validator: Validators.NonEmptyValidator);
|
validator: Validators.NonEmptyValidator);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
public string GetWork()
|
public string GetWork()
|
||||||
{
|
{
|
||||||
return GetArgOrPrompt(
|
return GetArgOrPrompt(
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
Trace.Info(nameof(LoadSettings));
|
Trace.Info(nameof(LoadSettings));
|
||||||
if (!IsConfigured())
|
if (!IsConfigured())
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Not configured. Run config.(sh/cmd) to configure the runner.");
|
throw new NonRetryableException("Not configured. Run config.(sh/cmd) to configure the runner.");
|
||||||
}
|
}
|
||||||
|
|
||||||
RunnerSettings settings = _store.GetSettings();
|
RunnerSettings settings = _store.GetSettings();
|
||||||
@@ -196,6 +196,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
TaskAgent agent;
|
TaskAgent agent;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
runnerSettings.DisableUpdate = command.DisableUpdate;
|
||||||
runnerSettings.Ephemeral = command.Ephemeral;
|
runnerSettings.Ephemeral = command.Ephemeral;
|
||||||
runnerSettings.AgentName = command.GetRunnerName();
|
runnerSettings.AgentName = command.GetRunnerName();
|
||||||
|
|
||||||
@@ -213,11 +214,22 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
if (command.GetReplace())
|
if (command.GetReplace())
|
||||||
{
|
{
|
||||||
// Update existing agent with new PublicKey, agent version.
|
// Update existing agent with new PublicKey, agent version.
|
||||||
agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral);
|
agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
agent = await _runnerServer.ReplaceAgentAsync(runnerSettings.PoolId, agent);
|
agent = await _runnerServer.ReplaceAgentAsync(runnerSettings.PoolId, agent);
|
||||||
|
if (command.DisableUpdate &&
|
||||||
|
command.DisableUpdate != agent.DisableUpdate)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("The GitHub server does not support configuring a self-hosted runner with 'DisableUpdate' flag.");
|
||||||
|
}
|
||||||
|
if (command.Ephemeral &&
|
||||||
|
command.Ephemeral != agent.Ephemeral)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("The GitHub server does not support configuring a self-hosted runner with 'Ephemeral' flag.");
|
||||||
|
}
|
||||||
|
|
||||||
_term.WriteSuccessMessage("Successfully replaced the runner");
|
_term.WriteSuccessMessage("Successfully replaced the runner");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -236,11 +248,22 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new agent.
|
// Create a new agent.
|
||||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral);
|
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
agent = await _runnerServer.AddAgentAsync(runnerSettings.PoolId, agent);
|
agent = await _runnerServer.AddAgentAsync(runnerSettings.PoolId, agent);
|
||||||
|
if (command.DisableUpdate &&
|
||||||
|
command.DisableUpdate != agent.DisableUpdate)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("The GitHub server does not support configuring a self-hosted runner with 'DisableUpdate' flag.");
|
||||||
|
}
|
||||||
|
if (command.Ephemeral &&
|
||||||
|
command.Ephemeral != agent.Ephemeral)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("The GitHub server does not support configuring a self-hosted runner with 'Ephemeral' flag.");
|
||||||
|
}
|
||||||
|
|
||||||
_term.WriteSuccessMessage("Runner successfully added");
|
_term.WriteSuccessMessage("Runner successfully added");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -415,7 +438,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// Determine the service deployment type based on connection data. (Hosted/OnPremises)
|
// Determine the service deployment type based on connection data. (Hosted/OnPremises)
|
||||||
await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
|
await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
|
||||||
|
|
||||||
var agents = await _runnerServer.GetAgentsAsync(settings.PoolId, settings.AgentName);
|
var agents = await _runnerServer.GetAgentsAsync(settings.AgentName);
|
||||||
Trace.Verbose("Returns {0} agents", agents.Count);
|
Trace.Verbose("Returns {0} agents", agents.Count);
|
||||||
TaskAgent agent = agents.FirstOrDefault();
|
TaskAgent agent = agents.FirstOrDefault();
|
||||||
if (agent == null)
|
if (agent == null)
|
||||||
@@ -424,7 +447,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _runnerServer.DeleteAgentAsync(settings.PoolId, settings.AgentId);
|
await _runnerServer.DeleteAgentAsync(settings.AgentId);
|
||||||
|
|
||||||
_term.WriteLine();
|
_term.WriteLine();
|
||||||
_term.WriteSuccessMessage("Runner removed successfully");
|
_term.WriteSuccessMessage("Runner removed successfully");
|
||||||
@@ -466,7 +489,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral)
|
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNull(agent, nameof(agent));
|
ArgUtil.NotNull(agent, nameof(agent));
|
||||||
agent.Authorization = new TaskAgentAuthorization
|
agent.Authorization = new TaskAgentAuthorization
|
||||||
@@ -478,6 +501,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
agent.Version = BuildConstants.RunnerPackage.Version;
|
agent.Version = BuildConstants.RunnerPackage.Version;
|
||||||
agent.OSDescription = RuntimeInformation.OSDescription;
|
agent.OSDescription = RuntimeInformation.OSDescription;
|
||||||
agent.Ephemeral = ephemeral;
|
agent.Ephemeral = ephemeral;
|
||||||
|
agent.DisableUpdate = disableUpdate;
|
||||||
agent.MaxParallelism = 1;
|
agent.MaxParallelism = 1;
|
||||||
|
|
||||||
agent.Labels.Clear();
|
agent.Labels.Clear();
|
||||||
@@ -494,7 +518,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral)
|
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
|
||||||
{
|
{
|
||||||
TaskAgent agent = new TaskAgent(agentName)
|
TaskAgent agent = new TaskAgent(agentName)
|
||||||
{
|
{
|
||||||
@@ -506,6 +530,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
Version = BuildConstants.RunnerPackage.Version,
|
Version = BuildConstants.RunnerPackage.Version,
|
||||||
OSDescription = RuntimeInformation.OSDescription,
|
OSDescription = RuntimeInformation.OSDescription,
|
||||||
Ephemeral = ephemeral,
|
Ephemeral = ephemeral,
|
||||||
|
DisableUpdate = disableUpdate
|
||||||
};
|
};
|
||||||
|
|
||||||
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
|
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -141,7 +142,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
LocalGroupInfo groupInfo = new LocalGroupInfo();
|
LocalGroupInfo groupInfo = new LocalGroupInfo();
|
||||||
groupInfo.Name = groupName;
|
groupInfo.Name = groupName;
|
||||||
groupInfo.Comment = StringUtil.Format("Built-in group used by Team Foundation Server.");
|
groupInfo.Comment = StringUtil.Format("Built-in group used by GitHub Actions Runner.");
|
||||||
|
|
||||||
int returnCode = NetLocalGroupAdd(null, // computer name
|
int returnCode = NetLocalGroupAdd(null, // computer name
|
||||||
1, // 1 means include comment
|
1, // 1 means include comment
|
||||||
@@ -1327,4 +1328,5 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
public IntPtr hProfile;
|
public IntPtr hProfile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
return !string.IsNullOrEmpty(value);
|
return !string.IsNullOrEmpty(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
public static bool NTAccountValidator(string arg)
|
public static bool NTAccountValidator(string arg)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\')))
|
if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\')))
|
||||||
@@ -87,5 +89,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -169,4 +170,5 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common.Util;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
using System.Linq;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
using GitHub.Services.WebApi.Jwt;
|
using GitHub.Services.WebApi.Jwt;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Listener
|
namespace GitHub.Runner.Listener
|
||||||
{
|
{
|
||||||
@@ -34,6 +36,7 @@ namespace GitHub.Runner.Listener
|
|||||||
// and the server will not send another job while this one is still running.
|
// and the server will not send another job while this one is still running.
|
||||||
public sealed class JobDispatcher : RunnerService, IJobDispatcher
|
public sealed class JobDispatcher : RunnerService, IJobDispatcher
|
||||||
{
|
{
|
||||||
|
private static Regex _invalidJsonRegex = new Regex(@"invalid\ Json\ at\ position\ '(\d+)':", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>();
|
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>();
|
||||||
private int _poolId;
|
private int _poolId;
|
||||||
|
|
||||||
@@ -964,6 +967,30 @@ namespace GitHub.Runner.Listener
|
|||||||
TimelineRecord jobRecord = timeline.Records.FirstOrDefault(x => x.Id == message.JobId && x.RecordType == "Job");
|
TimelineRecord jobRecord = timeline.Records.FirstOrDefault(x => x.Id == message.JobId && x.RecordType == "Job");
|
||||||
ArgUtil.NotNull(jobRecord, nameof(jobRecord));
|
ArgUtil.NotNull(jobRecord, nameof(jobRecord));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(errorMessage) &&
|
||||||
|
message.Variables.TryGetValue("DistributedTask.EnableRunnerIPCDebug", out var enableRunnerIPCDebug) &&
|
||||||
|
StringUtil.ConvertToBoolean(enableRunnerIPCDebug.Value))
|
||||||
|
{
|
||||||
|
// the trace should be best effort and not affect any job result
|
||||||
|
var match = _invalidJsonRegex.Match(errorMessage);
|
||||||
|
if (match.Success &&
|
||||||
|
match.Groups.Count == 2)
|
||||||
|
{
|
||||||
|
var jsonPosition = int.Parse(match.Groups[1].Value);
|
||||||
|
var serializedJobMessage = JsonUtility.ToString(message);
|
||||||
|
var originalJson = serializedJobMessage.Substring(jsonPosition - 10, 20);
|
||||||
|
errorMessage = $"Runner sent Json at position '{jsonPosition}': {originalJson} ({Convert.ToBase64String(Encoding.UTF8.GetBytes(originalJson))})\n{errorMessage}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.Error(ex);
|
||||||
|
errorMessage = $"Fail to check json IPC error: {ex.Message}\n{errorMessage}";
|
||||||
|
}
|
||||||
|
|
||||||
var unhandledExceptionIssue = new Issue() { Type = IssueType.Error, Message = errorMessage };
|
var unhandledExceptionIssue = new Issue() { Type = IssueType.Error, Message = errorMessage };
|
||||||
unhandledExceptionIssue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.WorkerCrash;
|
unhandledExceptionIssue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.WorkerCrash;
|
||||||
jobRecord.ErrorCount++;
|
jobRecord.ErrorCount++;
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
<PredefinedCulturesOnly>false</PredefinedCulturesOnly>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -26,6 +25,12 @@
|
|||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" />
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="..\Misc\runnercoreassets">
|
||||||
|
<LogicalName>GitHub.Runner.Listener.runnercoreassets</LogicalName>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -233,8 +233,14 @@ namespace GitHub.Runner.Listener
|
|||||||
Trace.Info($"Set runner startup type - {startType}");
|
Trace.Info($"Set runner startup type - {startType}");
|
||||||
HostContext.StartupType = startType;
|
HostContext.StartupType = startType;
|
||||||
|
|
||||||
|
if (command.RunOnce)
|
||||||
|
{
|
||||||
|
_term.WriteLine("Warning: '--once' is going to be deprecated in the future, please consider using '--ephemeral' during runner registration.", ConsoleColor.Yellow);
|
||||||
|
_term.WriteLine("https://docs.github.com/en/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#using-ephemeral-runners-for-autoscaling", ConsoleColor.Yellow);
|
||||||
|
}
|
||||||
|
|
||||||
// Run the runner interactively or as service
|
// Run the runner interactively or as service
|
||||||
return await RunAsync(settings, command.RunOnce || settings.Ephemeral); // TODO: Remove RunOnce later.
|
return await RunAsync(settings, command.RunOnce || settings.Ephemeral);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -306,10 +312,15 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
HostContext.WritePerfCounter("SessionCreated");
|
HostContext.WritePerfCounter("SessionCreated");
|
||||||
|
|
||||||
|
_term.WriteLine($"Current runner version: '{BuildConstants.RunnerPackage.Version}'");
|
||||||
_term.WriteLine($"{DateTime.UtcNow:u}: Listening for Jobs");
|
_term.WriteLine($"{DateTime.UtcNow:u}: Listening for Jobs");
|
||||||
|
|
||||||
IJobDispatcher jobDispatcher = null;
|
IJobDispatcher jobDispatcher = null;
|
||||||
CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken);
|
CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken);
|
||||||
|
|
||||||
|
// Should we try to cleanup ephemeral runners
|
||||||
|
bool runOnceJobCompleted = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var notification = HostContext.GetService<IJobNotification>();
|
var notification = HostContext.GetService<IJobNotification>();
|
||||||
@@ -371,6 +382,7 @@ namespace GitHub.Runner.Listener
|
|||||||
Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task);
|
Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task);
|
||||||
if (completeTask == jobDispatcher.RunOnceJobCompleted.Task)
|
if (completeTask == jobDispatcher.RunOnceJobCompleted.Task)
|
||||||
{
|
{
|
||||||
|
runOnceJobCompleted = true;
|
||||||
Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode.");
|
Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode.");
|
||||||
Trace.Info("Stop message queue looping.");
|
Trace.Info("Stop message queue looping.");
|
||||||
messageQueueLoopTokenSource.Cancel();
|
messageQueueLoopTokenSource.Cancel();
|
||||||
@@ -396,7 +408,7 @@ namespace GitHub.Runner.Listener
|
|||||||
autoUpdateInProgress = true;
|
autoUpdateInProgress = true;
|
||||||
var runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body);
|
var runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body);
|
||||||
var selfUpdater = HostContext.GetService<ISelfUpdater>();
|
var selfUpdater = HostContext.GetService<ISelfUpdater>();
|
||||||
selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, !runOnce && HostContext.StartupType != StartupType.Service, HostContext.RunnerShutdownToken);
|
selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, false, HostContext.RunnerShutdownToken);
|
||||||
Trace.Info("Refresh message received, kick-off selfupdate background process.");
|
Trace.Info("Refresh message received, kick-off selfupdate background process.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -413,6 +425,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
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(jobMessage, runOnce);
|
jobDispatcher.Run(jobMessage, runOnce);
|
||||||
if (runOnce)
|
if (runOnce)
|
||||||
@@ -479,7 +492,7 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
messageQueueLoopTokenSource.Dispose();
|
messageQueueLoopTokenSource.Dispose();
|
||||||
|
|
||||||
if (settings.Ephemeral)
|
if (settings.Ephemeral && runOnceJobCompleted)
|
||||||
{
|
{
|
||||||
var configManager = HostContext.GetService<IConfigurationManager>();
|
var configManager = HostContext.GetService<IConfigurationManager>();
|
||||||
configManager.DeleteLocalRunnerConfig();
|
configManager.DeleteLocalRunnerConfig();
|
||||||
@@ -527,6 +540,7 @@ Config Options:
|
|||||||
--work string Relative runner work directory (default {Constants.Path.WorkDirectory})
|
--work string Relative runner work directory (default {Constants.Path.WorkDirectory})
|
||||||
--replace Replace any existing runner with the same name (default false)
|
--replace Replace any existing runner with the same name (default false)
|
||||||
--pat GitHub personal access token used for checking network connectivity when executing `.{separator}run.{ext} --check`
|
--pat GitHub personal access token used for checking network connectivity when executing `.{separator}run.{ext} --check`
|
||||||
|
--disableupdate Disable self-hosted runner automatic update to the latest released version`
|
||||||
--ephemeral Configure the runner to only take one job and then let the service un-configure the runner after the job finishes (default false)");
|
--ephemeral Configure the runner to only take one job and then let the service un-configure the runner after the job finishes (default false)");
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
@@ -534,7 +548,7 @@ Config Options:
|
|||||||
_term.WriteLine($@" --windowslogonaccount string Account to run the service as. Requires runasservice");
|
_term.WriteLine($@" --windowslogonaccount string Account to run the service as. Requires runasservice");
|
||||||
_term.WriteLine($@" --windowslogonpassword string Password for the service account. Requires runasservice");
|
_term.WriteLine($@" --windowslogonpassword string Password for the service account. Requires runasservice");
|
||||||
#endif
|
#endif
|
||||||
_term.WriteLine($@"
|
_term.WriteLine($@"
|
||||||
Examples:
|
Examples:
|
||||||
Check GitHub server network connectivity:
|
Check GitHub server network connectivity:
|
||||||
.{separator}run.{ext} --check --url <url> --pat <pat>
|
.{separator}run.{ext} --check --url <url> --pat <pat>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
<PredefinedCulturesOnly>false</PredefinedCulturesOnly>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
{
|
{
|
||||||
// We should never
|
// We should never
|
||||||
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
|
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
|
||||||
throw ex;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
uploadTimer.Restart();
|
uploadTimer.Restart();
|
||||||
using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024))
|
using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token))
|
||||||
{
|
{
|
||||||
if (response == null || response.StatusCode != HttpStatusCode.Created)
|
if (response == null || response.StatusCode != HttpStatusCode.Created)
|
||||||
{
|
{
|
||||||
@@ -528,7 +528,7 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
|
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
|
||||||
throw ex;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
VssClientHttpRequestSettings.Default.UserAgent = headerValues;
|
||||||
VssHttpMessageHandler.DefaultWebProxy = proxy;
|
VssHttpMessageHandler.DefaultWebProxy = proxy;
|
||||||
|
|
||||||
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
||||||
|
{
|
||||||
|
VssClientHttpRequestSettings.Default.ServerCertificateValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -108,20 +108,18 @@ namespace GitHub.Runner.Worker
|
|||||||
// Stop command
|
// Stop command
|
||||||
if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
context.Output(input);
|
ValidateStopToken(context, actionCommand.Data);
|
||||||
context.Debug("Paused processing commands until '##[{actionCommand.Data}]' is received");
|
|
||||||
_stopToken = actionCommand.Data;
|
_stopToken = actionCommand.Data;
|
||||||
if (_registeredCommands.Contains(actionCommand.Data) || string.IsNullOrEmpty(actionCommand.Data))
|
|
||||||
{
|
|
||||||
var telemetry = new JobTelemetry
|
|
||||||
{
|
|
||||||
Message = $"Invoked ::stopCommand:: with token: [{actionCommand.Data}]",
|
|
||||||
Type = JobTelemetryType.ActionCommand
|
|
||||||
};
|
|
||||||
context.JobTelemetry.Add(telemetry);
|
|
||||||
}
|
|
||||||
_stopProcessCommand = true;
|
_stopProcessCommand = true;
|
||||||
_registeredCommands.Add(_stopToken);
|
_registeredCommands.Add(_stopToken);
|
||||||
|
if (_stopToken.Length > 6)
|
||||||
|
{
|
||||||
|
HostContext.SecretMasker.AddValue(_stopToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Output(input);
|
||||||
|
context.Debug("Paused processing commands until the token you called ::stopCommands:: with is received");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Found command
|
// Found command
|
||||||
@@ -155,7 +153,42 @@ namespace GitHub.Runner.Worker
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool EnhancedAnnotationsEnabled(IExecutionContext context) {
|
private void ValidateStopToken(IExecutionContext context, string stopToken)
|
||||||
|
{
|
||||||
|
#if OS_WINDOWS
|
||||||
|
var envContext = context.ExpressionValues["env"] as DictionaryContextData;
|
||||||
|
#else
|
||||||
|
var envContext = context.ExpressionValues["env"] as CaseSensitiveDictionaryContextData;
|
||||||
|
#endif
|
||||||
|
var allowUnsecureStopCommandTokens = false;
|
||||||
|
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens));
|
||||||
|
if (!allowUnsecureStopCommandTokens && envContext.ContainsKey(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens))
|
||||||
|
{
|
||||||
|
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(envContext[Constants.Variables.Actions.AllowUnsupportedStopCommandTokens].ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTokenInvalid = _registeredCommands.Contains(stopToken)
|
||||||
|
|| string.IsNullOrEmpty(stopToken)
|
||||||
|
|| string.Equals(stopToken, "pause-logging", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (isTokenInvalid)
|
||||||
|
{
|
||||||
|
var telemetry = new JobTelemetry
|
||||||
|
{
|
||||||
|
Message = $"Invoked ::stopCommand:: with token: [{stopToken}]",
|
||||||
|
Type = JobTelemetryType.ActionCommand
|
||||||
|
};
|
||||||
|
context.JobTelemetry.Add(telemetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTokenInvalid && !allowUnsecureStopCommandTokens)
|
||||||
|
{
|
||||||
|
throw new Exception(Constants.Runner.UnsupportedStopCommandTokenDisabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool EnhancedAnnotationsEnabled(IExecutionContext context)
|
||||||
|
{
|
||||||
return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false;
|
return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,7 +292,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public const String Name = "name";
|
public const String Name = "name";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] _setEnvBlockList =
|
private string[] _setEnvBlockList =
|
||||||
{
|
{
|
||||||
"NODE_OPTIONS"
|
"NODE_OPTIONS"
|
||||||
};
|
};
|
||||||
@@ -348,6 +381,13 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
HostContext.SecretMasker.AddValue(command.Data);
|
HostContext.SecretMasker.AddValue(command.Data);
|
||||||
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
||||||
|
|
||||||
|
// Also add each individual line. Typically individual lines are processed from STDOUT of child processes.
|
||||||
|
var split = command.Data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
foreach (var item in split)
|
||||||
|
{
|
||||||
|
HostContext.SecretMasker.AddValue(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,7 +400,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
|
||||||
{
|
{
|
||||||
var allowUnsecureCommands = false;
|
var allowUnsecureCommands = false;
|
||||||
bool.TryParse(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedCommands), out allowUnsecureCommands);
|
bool.TryParse(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedCommands), out allowUnsecureCommands);
|
||||||
|
|
||||||
@@ -549,11 +589,11 @@ namespace GitHub.Runner.Worker
|
|||||||
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|
||||||
if (!ActionCommandManager.EnhancedAnnotationsEnabled(context))
|
if (!ActionCommandManager.EnhancedAnnotationsEnabled(context))
|
||||||
{
|
{
|
||||||
context.Debug("Enhanced Annotations not enabled on the server. The 'title', 'end_line', and 'end_column' fields are unsupported.");
|
context.Debug("Enhanced Annotations not enabled on the server. The 'title', 'end_line', and 'end_column' fields are unsupported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Issue issue = new Issue()
|
Issue issue = new Issue()
|
||||||
{
|
{
|
||||||
Category = "General",
|
Category = "General",
|
||||||
@@ -605,7 +645,7 @@ namespace GitHub.Runner.Worker
|
|||||||
context.AddIssue(issue);
|
context.AddIssue(issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context)
|
public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context)
|
||||||
{
|
{
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.EndLine, out string endLine);
|
command.Properties.TryGetValue(IssueCommandProperties.EndLine, out string endLine);
|
||||||
@@ -634,28 +674,28 @@ namespace GitHub.Runner.Worker
|
|||||||
column = endColumn;
|
column = endColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasStartLine && hasColumn)
|
if (!hasStartLine && hasColumn)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' can only be set if '{IssueCommandProperties.Line}' value is provided.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' can only be set if '{IssueCommandProperties.Line}' value is provided.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasEndLine && line != endLine && hasColumn)
|
if (hasEndLine && line != endLine && hasColumn)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' cannot be set if '{IssueCommandProperties.Line}' and '{IssueCommandProperties.EndLine}' are different values.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' cannot be set if '{IssueCommandProperties.Line}' and '{IssueCommandProperties.EndLine}' are different values.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasStartLine && hasEndLine && endLineNumber < lineNumber)
|
if (hasStartLine && hasEndLine && endLineNumber < lineNumber)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndLine}' cannot be less than '{IssueCommandProperties.Line}'.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndLine}' cannot be less than '{IssueCommandProperties.Line}'.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Line);
|
command.Properties.Remove(IssueCommandProperties.Line);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndLine);
|
command.Properties.Remove(IssueCommandProperties.EndLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasStartColumn && hasEndColumn && endColumnNumber < columnNumber)
|
if (hasStartColumn && hasEndColumn && endColumnNumber < columnNumber)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndColumn}' cannot be less than '{IssueCommandProperties.Column}'.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndColumn}' cannot be less than '{IssueCommandProperties.Column}'.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
|
|||||||
@@ -267,6 +267,19 @@ namespace GitHub.Runner.Worker
|
|||||||
_cachedEmbeddedPostSteps[parentStepId].Push(clonedAction);
|
_cachedEmbeddedPostSteps[parentStepId].Push(clonedAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (depth > 0)
|
||||||
|
{
|
||||||
|
// if we're in a composite action and haven't loaded the local action yet
|
||||||
|
// we assume it has a post step
|
||||||
|
if (!_cachedEmbeddedPostSteps.ContainsKey(parentStepId))
|
||||||
|
{
|
||||||
|
// If we haven't done so already, add the parent to the post steps
|
||||||
|
_cachedEmbeddedPostSteps[parentStepId] = new Stack<Pipelines.ActionStep>();
|
||||||
|
}
|
||||||
|
// Clone action so we can modify the condition without affecting the original
|
||||||
|
var clonedAction = action.Clone() as Pipelines.ActionStep;
|
||||||
|
_cachedEmbeddedPostSteps[parentStepId].Push(clonedAction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +443,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
for (var i = 0; i < compositeAction.Steps.Count; i++)
|
for (var i = 0; i < compositeAction.Steps.Count; i++)
|
||||||
{
|
{
|
||||||
// Store Id's for later load actions
|
// Load stored Ids for later load actions
|
||||||
compositeAction.Steps[i].Id = _cachedEmbeddedStepIds[action.Id][i];
|
compositeAction.Steps[i].Id = _cachedEmbeddedStepIds[action.Id][i];
|
||||||
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && compositeAction.Steps[i].Reference.Type != Pipelines.ActionSourceType.Script)
|
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && compositeAction.Steps[i].Reference.Type != Pipelines.ActionSourceType.Script)
|
||||||
{
|
{
|
||||||
@@ -438,6 +451,16 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_cachedEmbeddedStepIds[action.Id] = new List<Guid>();
|
||||||
|
foreach (var compositeStep in compositeAction.Steps)
|
||||||
|
{
|
||||||
|
var guid = Guid.NewGuid();
|
||||||
|
compositeStep.Id = guid;
|
||||||
|
_cachedEmbeddedStepIds[action.Id].Add(guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -633,7 +656,12 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled.
|
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled.
|
||||||
{
|
{
|
||||||
if (attempt < 3)
|
// UnresolvableActionDownloadInfoException is a 422 client error, don't retry
|
||||||
|
// Some possible cases are:
|
||||||
|
// * Repo is rate limited
|
||||||
|
// * Repo or tag doesn't exist, or isn't public
|
||||||
|
// * Policy validation failed
|
||||||
|
if (attempt < 3 && !(ex is WebApi.UnresolvableActionDownloadInfoException))
|
||||||
{
|
{
|
||||||
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
|
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
|
||||||
executionContext.Debug(ex.ToString());
|
executionContext.Debug(ex.ToString());
|
||||||
@@ -649,6 +677,7 @@ namespace GitHub.Runner.Worker
|
|||||||
// Some possible cases are:
|
// Some possible cases are:
|
||||||
// * Repo is rate limited
|
// * Repo is rate limited
|
||||||
// * Repo or tag doesn't exist, or isn't public
|
// * Repo or tag doesn't exist, or isn't public
|
||||||
|
// * Policy validation failed
|
||||||
if (ex is WebApi.UnresolvableActionDownloadInfoException)
|
if (ex is WebApi.UnresolvableActionDownloadInfoException)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
@@ -1028,7 +1057,6 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove once we remove the DistributedTask.EnableCompositeActions FF
|
|
||||||
foreach (var step in compositeAction.Steps)
|
foreach (var step in compositeAction.Steps)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && step.Reference.Type != Pipelines.ActionSourceType.Script)
|
if (string.IsNullOrEmpty(executionContext.Global.Variables.Get("DistributedTask.EnableCompositeActions")) && step.Reference.Type != Pipelines.ActionSourceType.Script)
|
||||||
@@ -1171,6 +1199,8 @@ namespace GitHub.Runner.Worker
|
|||||||
public string Pre { get; set; }
|
public string Pre { get; set; }
|
||||||
|
|
||||||
public string Post { get; set; }
|
public string Post { get; set; }
|
||||||
|
|
||||||
|
public string NodeVersion { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PluginActionExecutionData : ActionExecutionData
|
public sealed class PluginActionExecutionData : ActionExecutionData
|
||||||
|
|||||||
@@ -451,7 +451,8 @@ namespace GitHub.Runner.Worker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase)||
|
||||||
|
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(mainToken?.Value))
|
if (string.IsNullOrEmpty(mainToken?.Value))
|
||||||
{
|
{
|
||||||
@@ -461,6 +462,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
return new NodeJSActionExecutionData()
|
return new NodeJSActionExecutionData()
|
||||||
{
|
{
|
||||||
|
NodeVersion = usingToken.Value,
|
||||||
Script = mainToken.Value,
|
Script = mainToken.Value,
|
||||||
Pre = preToken?.Value,
|
Pre = preToken?.Value,
|
||||||
InitCondition = preIfToken?.Value ?? "always()",
|
InitCondition = preIfToken?.Value ?? "always()",
|
||||||
@@ -490,7 +492,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker' or 'node12' instead.");
|
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12' or 'node16' instead.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pluginToken != null)
|
else if (pluginToken != null)
|
||||||
|
|||||||
@@ -55,12 +55,14 @@ namespace GitHub.Runner.Worker
|
|||||||
// Our container feature requires to map working directory from host to the container.
|
// Our container feature requires to map working directory from host to the container.
|
||||||
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
// service CExecSvc is Container Execution Agent.
|
// service CExecSvc is Container Execution Agent.
|
||||||
ServiceController[] scServices = ServiceController.GetServices();
|
ServiceController[] scServices = ServiceController.GetServices();
|
||||||
if (scServices.Any(x => String.Equals(x.ServiceName, "cexecsvc", StringComparison.OrdinalIgnoreCase) && x.Status == ServiceControllerStatus.Running))
|
if (scServices.Any(x => String.Equals(x.ServiceName, "cexecsvc", StringComparison.OrdinalIgnoreCase) && x.Status == ServiceControllerStatus.Running))
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
#else
|
#else
|
||||||
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
||||||
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||||
@@ -70,6 +72,7 @@ namespace GitHub.Runner.Worker
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
// Check OS version (Windows server 1803 is required)
|
// Check OS version (Windows server 1803 is required)
|
||||||
object windowsInstallationType = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType", defaultValue: null);
|
object windowsInstallationType = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType", defaultValue: null);
|
||||||
ArgUtil.NotNull(windowsInstallationType, nameof(windowsInstallationType));
|
ArgUtil.NotNull(windowsInstallationType, nameof(windowsInstallationType));
|
||||||
@@ -88,6 +91,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId");
|
throw new ArgumentOutOfRangeException(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId");
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check docker client/server version
|
// Check docker client/server version
|
||||||
@@ -334,6 +338,18 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(container.ContainerId))
|
if (!string.IsNullOrEmpty(container.ContainerId))
|
||||||
{
|
{
|
||||||
|
if(!container.IsJobContainer)
|
||||||
|
{
|
||||||
|
// Print logs for service container jobs (not the "action" job itself b/c that's already logged).
|
||||||
|
executionContext.Output($"Print service container logs: {container.ContainerDisplayName}");
|
||||||
|
|
||||||
|
int logsExitCode = await _dockerManager.DockerLogs(executionContext, container.ContainerId);
|
||||||
|
if (logsExitCode != 0)
|
||||||
|
{
|
||||||
|
executionContext.Warning($"Docker logs fail with exit code {logsExitCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
executionContext.Output($"Stop and remove container: {container.ContainerDisplayName}");
|
executionContext.Output($"Stop and remove container: {container.ContainerDisplayName}");
|
||||||
|
|
||||||
int rmExitCode = await _dockerManager.DockerRemove(executionContext, container.ContainerId);
|
int rmExitCode = await _dockerManager.DockerRemove(executionContext, container.ContainerId);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace GitHub.Runner.Worker
|
|||||||
string ScopeName { get; }
|
string ScopeName { get; }
|
||||||
string SiblingScopeName { get; }
|
string SiblingScopeName { get; }
|
||||||
string ContextName { get; }
|
string ContextName { get; }
|
||||||
|
ActionRunStage Stage { get; }
|
||||||
Task ForceCompleted { get; }
|
Task ForceCompleted { get; }
|
||||||
TaskResult? Result { get; set; }
|
TaskResult? Result { get; set; }
|
||||||
TaskResult? Outcome { get; set; }
|
TaskResult? Outcome { get; set; }
|
||||||
@@ -62,7 +63,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
Stack<IStep> PostJobSteps { get; }
|
Stack<IStep> PostJobSteps { get; }
|
||||||
HashSet<Guid> EmbeddedStepsWithPostRegistered{ get; }
|
Dictionary<Guid, string> EmbeddedStepsWithPostRegistered { get; }
|
||||||
|
|
||||||
// Keep track of embedded steps states
|
// Keep track of embedded steps states
|
||||||
Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; }
|
Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; }
|
||||||
@@ -76,8 +77,8 @@ namespace GitHub.Runner.Worker
|
|||||||
// Initialize
|
// Initialize
|
||||||
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
void InitializeJob(Pipelines.AgentJobRequestMessage message, CancellationToken token);
|
||||||
void CancelToken();
|
void CancelToken();
|
||||||
IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null);
|
IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null);
|
||||||
IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
|
IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null);
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
long Write(string tag, string message);
|
long Write(string tag, string message);
|
||||||
@@ -144,6 +145,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public string ScopeName { get; private set; }
|
public string ScopeName { get; private set; }
|
||||||
public string SiblingScopeName { get; private set; }
|
public string SiblingScopeName { get; private set; }
|
||||||
public string ContextName { get; private set; }
|
public string ContextName { get; private set; }
|
||||||
|
public ActionRunStage Stage { get; private set; }
|
||||||
public Task ForceCompleted => _forceCompleted.Task;
|
public Task ForceCompleted => _forceCompleted.Task;
|
||||||
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
||||||
public Dictionary<string, string> IntraActionState { get; private set; }
|
public Dictionary<string, string> IntraActionState { get; private set; }
|
||||||
@@ -168,7 +170,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public HashSet<Guid> StepsWithPostRegistered { get; private set; }
|
public HashSet<Guid> StepsWithPostRegistered { get; private set; }
|
||||||
|
|
||||||
// Only job level ExecutionContext has EmbeddedStepsWithPostRegistered
|
// Only job level ExecutionContext has EmbeddedStepsWithPostRegistered
|
||||||
public HashSet<Guid> EmbeddedStepsWithPostRegistered { get; private set; }
|
public Dictionary<Guid, string> EmbeddedStepsWithPostRegistered { get; private set; }
|
||||||
|
|
||||||
public Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; private set; }
|
public Dictionary<Guid, Dictionary<string, string>> EmbeddedIntraActionState { get; private set; }
|
||||||
|
|
||||||
@@ -265,12 +267,19 @@ namespace GitHub.Runner.Worker
|
|||||||
string siblingScopeName = null;
|
string siblingScopeName = null;
|
||||||
if (this.IsEmbedded)
|
if (this.IsEmbedded)
|
||||||
{
|
{
|
||||||
if (step is IActionRunner actionRunner && !Root.EmbeddedStepsWithPostRegistered.Add(actionRunner.Action.Id))
|
if (step is IActionRunner actionRunner)
|
||||||
{
|
{
|
||||||
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to child post step stack.");
|
if (Root.EmbeddedStepsWithPostRegistered.ContainsKey(actionRunner.Action.Id))
|
||||||
|
{
|
||||||
|
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to child post step stack.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Root.EmbeddedStepsWithPostRegistered[actionRunner.Action.Id] = actionRunner.Condition;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
else if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id))
|
else if (step is IActionRunner actionRunner && !Root.StepsWithPostRegistered.Add(actionRunner.Action.Id))
|
||||||
{
|
{
|
||||||
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to post step stack.");
|
Trace.Info($"'post' of '{actionRunner.DisplayName}' already push to post step stack.");
|
||||||
@@ -285,7 +294,7 @@ namespace GitHub.Runner.Worker
|
|||||||
Root.PostJobSteps.Push(step);
|
Root.PostJobSteps.Push(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null)
|
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, ActionRunStage stage, Dictionary<string, string> intraActionState = null, int? recordOrder = null, IPagingLogger logger = null, bool isEmbedded = false, CancellationTokenSource cancellationTokenSource = null, Guid embeddedId = default(Guid), string siblingScopeName = null)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
|
|
||||||
@@ -294,6 +303,7 @@ namespace GitHub.Runner.Worker
|
|||||||
child.Global = Global;
|
child.Global = Global;
|
||||||
child.ScopeName = scopeName;
|
child.ScopeName = scopeName;
|
||||||
child.ContextName = contextName;
|
child.ContextName = contextName;
|
||||||
|
child.Stage = stage;
|
||||||
child.EmbeddedId = embeddedId;
|
child.EmbeddedId = embeddedId;
|
||||||
child.SiblingScopeName = siblingScopeName;
|
child.SiblingScopeName = siblingScopeName;
|
||||||
child.JobTelemetry = JobTelemetry;
|
child.JobTelemetry = JobTelemetry;
|
||||||
@@ -344,9 +354,9 @@ namespace GitHub.Runner.Worker
|
|||||||
/// An embedded execution context shares the same record ID, record name, logger,
|
/// An embedded execution context shares the same record ID, record name, logger,
|
||||||
/// and a linked cancellation token.
|
/// and a linked cancellation token.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, Dictionary<string, string> intraActionState = null, string siblingScopeName = null)
|
public IExecutionContext CreateEmbeddedChild(string scopeName, string contextName, Guid embeddedId, ActionRunStage stage, Dictionary<string, string> intraActionState = null, string siblingScopeName = null)
|
||||||
{
|
{
|
||||||
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName);
|
return Root.CreateChild(_record.Id, _record.Name, _record.Id.ToString("N"), scopeName, contextName, stage, logger: _logger, isEmbedded: true, cancellationTokenSource: CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token), intraActionState: intraActionState, embeddedId: embeddedId, siblingScopeName: siblingScopeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(string currentOperation = null)
|
public void Start(string currentOperation = null)
|
||||||
@@ -543,8 +553,8 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
_record.WarningCount++;
|
_record.WarningCount++;
|
||||||
}
|
}
|
||||||
else if (issue.Type == IssueType.Notice)
|
else if (issue.Type == IssueType.Notice)
|
||||||
{
|
{
|
||||||
|
|
||||||
// tracking line number for each issue in log file
|
// tracking line number for each issue in log file
|
||||||
@@ -716,10 +726,10 @@ namespace GitHub.Runner.Worker
|
|||||||
StepsWithPostRegistered = new HashSet<Guid>();
|
StepsWithPostRegistered = new HashSet<Guid>();
|
||||||
|
|
||||||
// EmbeddedStepsWithPostRegistered for job ExecutionContext
|
// EmbeddedStepsWithPostRegistered for job ExecutionContext
|
||||||
EmbeddedStepsWithPostRegistered = new HashSet<Guid>();
|
EmbeddedStepsWithPostRegistered = new Dictionary<Guid, string>();
|
||||||
|
|
||||||
// EmbeddedIntraActionState for job ExecutionContext
|
// EmbeddedIntraActionState for job ExecutionContext
|
||||||
EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string,string>>();
|
EmbeddedIntraActionState = new Dictionary<Guid, Dictionary<string, string>>();
|
||||||
|
|
||||||
// Job timeline record.
|
// Job timeline record.
|
||||||
InitializeTimelineRecord(
|
InitializeTimelineRecord(
|
||||||
@@ -937,7 +947,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newGuid = Guid.NewGuid();
|
var newGuid = Guid.NewGuid();
|
||||||
return CreateChild(newGuid, displayName, newGuid.ToString("N"), null, null, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count, siblingScopeName: siblingScopeName);
|
return CreateChild(newGuid, displayName, newGuid.ToString("N"), null, null, ActionRunStage.Post, intraActionState, _childTimelineRecordOrder - Root.PostJobSteps.Count, siblingScopeName: siblingScopeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -970,7 +980,7 @@ namespace GitHub.Runner.Worker
|
|||||||
// Do not add a format string overload. See comment on ExecutionContext.Write().
|
// Do not add a format string overload. See comment on ExecutionContext.Write().
|
||||||
public static void InfrastructureError(this IExecutionContext context, string message)
|
public static void InfrastructureError(this IExecutionContext context, string message)
|
||||||
{
|
{
|
||||||
context.AddIssue(new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true});
|
context.AddIssue(new Issue() { Type = IssueType.Error, Message = message, IsInfrastructureIssue = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not add a format string overload. See comment on ExecutionContext.Write().
|
// Do not add a format string overload. See comment on ExecutionContext.Write().
|
||||||
|
|||||||
@@ -24,8 +24,19 @@ namespace GitHub.Runner.Worker.Expressions
|
|||||||
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
||||||
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
|
||||||
return jobStatus == ActionResult.Failure;
|
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps
|
||||||
|
var isCompositeMainStep = executionContext.IsEmbedded && executionContext.Stage == ActionRunStage.Main;
|
||||||
|
if (isCompositeMainStep)
|
||||||
|
{
|
||||||
|
ActionResult actionStatus = EnumUtil.TryParse<ActionResult>(executionContext.GetGitHubContext("action_status")) ?? ActionResult.Success;
|
||||||
|
return actionStatus == ActionResult.Failure;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
||||||
|
return jobStatus == ActionResult.Failure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,19 @@ namespace GitHub.Runner.Worker.Expressions
|
|||||||
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
ArgUtil.NotNull(templateContext, nameof(templateContext));
|
||||||
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
|
||||||
return jobStatus == ActionResult.Success;
|
// Decide based on 'action_status' for composite MAIN steps and 'job.status' for pre, post and job-level steps
|
||||||
|
var isCompositeMainStep = executionContext.IsEmbedded && executionContext.Stage == ActionRunStage.Main;
|
||||||
|
if (isCompositeMainStep)
|
||||||
|
{
|
||||||
|
ActionResult actionStatus = EnumUtil.TryParse<ActionResult>(executionContext.GetGitHubContext("action_status")) ?? ActionResult.Success;
|
||||||
|
return actionStatus == ActionResult.Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ActionResult jobStatus = executionContext.JobContext.Status ?? ActionResult.Success;
|
||||||
|
return jobStatus == ActionResult.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ namespace GitHub.Runner.Worker
|
|||||||
"job",
|
"job",
|
||||||
"path",
|
"path",
|
||||||
"ref",
|
"ref",
|
||||||
|
"ref_name",
|
||||||
|
"ref_protected",
|
||||||
|
"ref_type",
|
||||||
"repository",
|
"repository",
|
||||||
"repository_owner",
|
"repository_owner",
|
||||||
"retention_days",
|
"retention_days",
|
||||||
@@ -39,9 +42,16 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
foreach (var data in this)
|
foreach (var data in this)
|
||||||
{
|
{
|
||||||
if (_contextEnvAllowlist.Contains(data.Key) && data.Value is StringContextData value)
|
if (_contextEnvAllowlist.Contains(data.Key))
|
||||||
{
|
{
|
||||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
|
if (data.Value is StringContextData value)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
|
||||||
|
}
|
||||||
|
else if (data.Value is BooleanContextData booleanValue)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", booleanValue.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,9 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Only register post steps for steps that actually ran
|
// Only register post steps for steps that actually ran
|
||||||
foreach (var step in Data.PostSteps.ToList())
|
foreach (var step in Data.PostSteps.ToList())
|
||||||
{
|
{
|
||||||
if (ExecutionContext.Root.EmbeddedStepsWithPostRegistered.Contains(step.Id))
|
if (ExecutionContext.Root.EmbeddedStepsWithPostRegistered.ContainsKey(step.Id))
|
||||||
{
|
{
|
||||||
|
step.Condition = ExecutionContext.Root.EmbeddedStepsWithPostRegistered[step.Id];
|
||||||
steps.Add(step);
|
steps.Add(step);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -124,7 +125,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
{
|
{
|
||||||
ArgUtil.NotNull(step, step.DisplayName);
|
ArgUtil.NotNull(step, step.DisplayName);
|
||||||
var stepId = $"__{Guid.NewGuid()}";
|
var stepId = $"__{Guid.NewGuid()}";
|
||||||
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid());
|
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepId, Guid.NewGuid(), stage);
|
||||||
embeddedSteps.Add(step);
|
embeddedSteps.Add(step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,7 +144,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
step.Stage = stage;
|
step.Stage = stage;
|
||||||
step.Condition = stepData.Condition;
|
step.Condition = stepData.Condition;
|
||||||
ExecutionContext.Root.EmbeddedIntraActionState.TryGetValue(step.Action.Id, out var intraActionState);
|
ExecutionContext.Root.EmbeddedIntraActionState.TryGetValue(step.Action.Id, out var intraActionState);
|
||||||
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepData.ContextName, step.Action.Id, intraActionState: intraActionState, siblingScopeName: siblingScopeName);
|
step.ExecutionContext = ExecutionContext.CreateEmbeddedChild(childScopeName, stepData.ContextName, step.Action.Id, stage, intraActionState: intraActionState, siblingScopeName: siblingScopeName);
|
||||||
step.ExecutionContext.ExpressionValues["inputs"] = inputsData;
|
step.ExecutionContext.ExpressionValues["inputs"] = inputsData;
|
||||||
if (!String.IsNullOrEmpty(ExecutionContext.SiblingScopeName))
|
if (!String.IsNullOrEmpty(ExecutionContext.SiblingScopeName))
|
||||||
{
|
{
|
||||||
@@ -241,6 +242,10 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<FailureFunction>(PipelineTemplateConstants.Failure, 0, 0));
|
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<FailureFunction>(PipelineTemplateConstants.Failure, 0, 0));
|
||||||
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<SuccessFunction>(PipelineTemplateConstants.Success, 0, 0));
|
step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo<SuccessFunction>(PipelineTemplateConstants.Success, 0, 0));
|
||||||
|
|
||||||
|
// Set action_status to the success of the current composite action
|
||||||
|
var actionResult = ExecutionContext.Result?.ToActionResult() ?? ActionResult.Success;
|
||||||
|
step.ExecutionContext.SetGitHubContext("action_status", actionResult.ToString());
|
||||||
|
|
||||||
// Initialize env context
|
// Initialize env context
|
||||||
Trace.Info("Initialize Env context for embedded step");
|
Trace.Info("Initialize Env context for embedded step");
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
@@ -295,108 +300,100 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
CancellationTokenRegistration? jobCancelRegister = null;
|
CancellationTokenRegistration? jobCancelRegister = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// For main steps just run the action
|
// Register job cancellation call back only if job cancellation token not been fire before each step run
|
||||||
if (stage == ActionRunStage.Main)
|
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
// Test the condition again. The job was canceled after the condition was originally evaluated.
|
||||||
|
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
|
||||||
|
{
|
||||||
|
// Mark job as cancelled
|
||||||
|
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||||
|
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||||
|
|
||||||
|
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
||||||
|
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
||||||
|
var conditionReTestResult = false;
|
||||||
|
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
|
||||||
|
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||||
|
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Cancel the step since we get exception while re-evaluate step condition
|
||||||
|
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
|
||||||
|
step.ExecutionContext.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conditionReTestResult)
|
||||||
|
{
|
||||||
|
// Cancel the step
|
||||||
|
Trace.Info("Cancel current running step.");
|
||||||
|
step.ExecutionContext.CancelToken();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ExecutionContext.Root.Result != TaskResult.Canceled)
|
||||||
|
{
|
||||||
|
// Mark job as cancelled
|
||||||
|
ExecutionContext.Root.Result = TaskResult.Canceled;
|
||||||
|
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Evaluate condition
|
||||||
|
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
|
||||||
|
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
|
||||||
|
var conditionResult = false;
|
||||||
|
var conditionEvaluateError = default(Exception);
|
||||||
|
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
|
||||||
|
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
||||||
|
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.Info("Caught exception from expression.");
|
||||||
|
Trace.Error(ex);
|
||||||
|
conditionEvaluateError = ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!conditionResult && conditionEvaluateError == null)
|
||||||
|
{
|
||||||
|
// Condition is false
|
||||||
|
Trace.Info("Skipping step due to condition evaluation.");
|
||||||
|
SetStepConclusion(step, TaskResult.Skipped);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (conditionEvaluateError != null)
|
||||||
|
{
|
||||||
|
// Condition error
|
||||||
|
step.ExecutionContext.Error(conditionEvaluateError);
|
||||||
|
SetStepConclusion(step, TaskResult.Failed);
|
||||||
|
ExecutionContext.Result = TaskResult.Failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
await RunStepAsync(step);
|
await RunStepAsync(step);
|
||||||
}
|
}
|
||||||
// We need to evaluate conditions for pre/post steps
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Register job cancellation call back only if job cancellation token not been fire before each step run
|
|
||||||
if (!ExecutionContext.Root.CancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
// Test the condition again. The job was canceled after the condition was originally evaluated.
|
|
||||||
jobCancelRegister = ExecutionContext.Root.CancellationToken.Register(() =>
|
|
||||||
{
|
|
||||||
// Mark job as cancelled
|
|
||||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
|
||||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
|
||||||
|
|
||||||
step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
|
|
||||||
var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
|
|
||||||
var conditionReTestResult = false;
|
|
||||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
|
|
||||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
|
||||||
conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Cancel the step since we get exception while re-evaluate step condition
|
|
||||||
Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
|
|
||||||
step.ExecutionContext.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conditionReTestResult)
|
|
||||||
{
|
|
||||||
// Cancel the step
|
|
||||||
Trace.Info("Cancel current running step.");
|
|
||||||
step.ExecutionContext.CancelToken();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ExecutionContext.Root.Result != TaskResult.Canceled)
|
|
||||||
{
|
|
||||||
// Mark job as cancelled
|
|
||||||
ExecutionContext.Root.Result = TaskResult.Canceled;
|
|
||||||
ExecutionContext.Root.JobContext.Status = ExecutionContext.Root.Result?.ToActionResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Evaluate condition
|
|
||||||
step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
|
|
||||||
var conditionTraceWriter = new ConditionTraceWriter(Trace, step.ExecutionContext);
|
|
||||||
var conditionResult = false;
|
|
||||||
var conditionEvaluateError = default(Exception);
|
|
||||||
if (HostContext.RunnerShutdownToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
|
|
||||||
var condition = new BasicExpressionToken(null, null, null, step.Condition);
|
|
||||||
conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Info("Caught exception from expression.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
conditionEvaluateError = ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!conditionResult && conditionEvaluateError == null)
|
|
||||||
{
|
|
||||||
// Condition is false
|
|
||||||
Trace.Info("Skipping step due to condition evaluation.");
|
|
||||||
step.ExecutionContext.Result = TaskResult.Skipped;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (conditionEvaluateError != null)
|
|
||||||
{
|
|
||||||
// Condition error
|
|
||||||
step.ExecutionContext.Error(conditionEvaluateError);
|
|
||||||
step.ExecutionContext.Result = TaskResult.Failed;
|
|
||||||
ExecutionContext.Result = TaskResult.Failed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await RunStepAsync(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -406,19 +403,15 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
jobCancelRegister = null;
|
jobCancelRegister = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check failed or canceled
|
// Check failed or canceled
|
||||||
if (step.ExecutionContext.Result == TaskResult.Failed || step.ExecutionContext.Result == TaskResult.Canceled)
|
if (step.ExecutionContext.Result == TaskResult.Failed || step.ExecutionContext.Result == TaskResult.Canceled)
|
||||||
{
|
{
|
||||||
Trace.Info($"Update job result with current composite step result '{step.ExecutionContext.Result}'.");
|
Trace.Info($"Update job result with current composite step result '{step.ExecutionContext.Result}'.");
|
||||||
ExecutionContext.Result = TaskResultUtil.MergeTaskResults(ExecutionContext.Result, step.ExecutionContext.Result.Value);
|
ExecutionContext.Result = TaskResultUtil.MergeTaskResults(ExecutionContext.Result, step.ExecutionContext.Result.Value);
|
||||||
|
|
||||||
// We should run cleanup even if one of the cleanup step fails
|
|
||||||
if (stage != ActionRunStage.Post)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update context
|
||||||
|
SetStepsContext(step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,13 +433,13 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
{
|
{
|
||||||
Trace.Error($"Caught timeout exception from step: {ex.Message}");
|
Trace.Error($"Caught timeout exception from step: {ex.Message}");
|
||||||
step.ExecutionContext.Error("The action has timed out.");
|
step.ExecutionContext.Error("The action has timed out.");
|
||||||
step.ExecutionContext.Result = TaskResult.Failed;
|
SetStepConclusion(step, TaskResult.Failed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Trace.Error($"Caught cancellation exception from step: {ex}");
|
Trace.Error($"Caught cancellation exception from step: {ex}");
|
||||||
step.ExecutionContext.Error(ex);
|
step.ExecutionContext.Error(ex);
|
||||||
step.ExecutionContext.Result = TaskResult.Canceled;
|
SetStepConclusion(step, TaskResult.Canceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -454,17 +447,32 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Log the error and fail the step
|
// Log the error and fail the step
|
||||||
Trace.Error($"Caught exception from step: {ex}");
|
Trace.Error($"Caught exception from step: {ex}");
|
||||||
step.ExecutionContext.Error(ex);
|
step.ExecutionContext.Error(ex);
|
||||||
step.ExecutionContext.Result = TaskResult.Failed;
|
SetStepConclusion(step, TaskResult.Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge execution context result with command result
|
// Merge execution context result with command result
|
||||||
if (step.ExecutionContext.CommandResult != null)
|
if (step.ExecutionContext.CommandResult != null)
|
||||||
{
|
{
|
||||||
step.ExecutionContext.Result = Common.Util.TaskResultUtil.MergeTaskResults(step.ExecutionContext.Result, step.ExecutionContext.CommandResult.Value);
|
SetStepConclusion(step, Common.Util.TaskResultUtil.MergeTaskResults(step.ExecutionContext.Result, step.ExecutionContext.CommandResult.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Info($"Step result: {step.ExecutionContext.Result}");
|
Trace.Info($"Step result: {step.ExecutionContext.Result}");
|
||||||
step.ExecutionContext.Debug($"Finished: {step.DisplayName}");
|
step.ExecutionContext.Debug($"Finished: {step.DisplayName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetStepConclusion(IStep step, TaskResult result)
|
||||||
|
{
|
||||||
|
step.ExecutionContext.Result = result;
|
||||||
|
SetStepsContext(step);
|
||||||
|
}
|
||||||
|
private void SetStepsContext(IStep step)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(step.ExecutionContext.ContextName) && !step.ExecutionContext.ContextName.StartsWith("__", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
// TODO: when we support continue on error, we may need to do logic here to change conclusion based on the continue on error result
|
||||||
|
step.ExecutionContext.Global.StepsContext.SetOutcome(step.ExecutionContext.ScopeName, step.ExecutionContext.ContextName, (step.ExecutionContext.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||||
|
step.ExecutionContext.Global.StepsContext.SetConclusion(step.ExecutionContext.ScopeName, step.ExecutionContext.ContextName, (step.ExecutionContext.Result ?? TaskResult.Succeeded).ToActionResult());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
HasPreStep = Data.HasPre,
|
HasPreStep = Data.HasPre,
|
||||||
HasPostStep = Data.HasPost,
|
HasPostStep = Data.HasPost,
|
||||||
IsEmbedded = ExecutionContext.IsEmbedded,
|
IsEmbedded = ExecutionContext.IsEmbedded,
|
||||||
Type = "node12"
|
Type = Data.NodeVersion
|
||||||
};
|
};
|
||||||
ExecutionContext.Root.ActionsStepsTelemetry.Add(telemetry);
|
ExecutionContext.Root.ActionsStepsTelemetry.Add(telemetry);
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
workingDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodeRuntimeVersion = await StepHost.DetermineNodeRuntimeVersion(ExecutionContext);
|
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}");
|
||||||
|
|
||||||
// Format the arguments passed to node.
|
// Format the arguments passed to node.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
|
|
||||||
string ResolvePathForStepHost(string path);
|
string ResolvePathForStepHost(string path);
|
||||||
|
|
||||||
Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext);
|
Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext, string preferredVersion);
|
||||||
|
|
||||||
Task<int> ExecuteAsync(string workingDirectory,
|
Task<int> ExecuteAsync(string workingDirectory,
|
||||||
string fileName,
|
string fileName,
|
||||||
@@ -58,9 +58,9 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext)
|
public Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext, string preferredVersion)
|
||||||
{
|
{
|
||||||
return Task.FromResult<string>("node12");
|
return Task.FromResult<string>(preferredVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> ExecuteAsync(string workingDirectory,
|
public async Task<int> ExecuteAsync(string workingDirectory,
|
||||||
@@ -123,7 +123,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext)
|
public async Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext, string preferredVersion)
|
||||||
{
|
{
|
||||||
// Best effort to determine a compatible node runtime
|
// Best effort to determine a compatible node runtime
|
||||||
// There may be more variation in which libraries are linked than just musl/glibc,
|
// There may be more variation in which libraries are linked than just musl/glibc,
|
||||||
@@ -148,14 +148,14 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
var msg = $"JavaScript Actions in Alpine containers are only supported on x64 Linux runners. Detected {os} {arch}";
|
var msg = $"JavaScript Actions in Alpine containers are only supported on x64 Linux runners. Detected {os} {arch}";
|
||||||
throw new NotSupportedException(msg);
|
throw new NotSupportedException(msg);
|
||||||
}
|
}
|
||||||
nodeExternal = "node12_alpine";
|
nodeExternal = $"{preferredVersion}_alpine";
|
||||||
executionContext.Debug($"Container distribution is alpine. Running JavaScript Action with external tool: {nodeExternal}");
|
executionContext.Debug($"Container distribution is alpine. Running JavaScript Action with external tool: {nodeExternal}");
|
||||||
return nodeExternal;
|
return nodeExternal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Optimistically use the default
|
// Optimistically use the default
|
||||||
nodeExternal = "node12";
|
nodeExternal = preferredVersion;
|
||||||
executionContext.Debug($"Running JavaScript Action with default external tool: {nodeExternal}");
|
executionContext.Debug($"Running JavaScript Action with default external tool: {nodeExternal}");
|
||||||
return nodeExternal;
|
return nodeExternal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace GitHub.Runner.Worker
|
|||||||
ArgUtil.NotNull(message, nameof(message));
|
ArgUtil.NotNull(message, nameof(message));
|
||||||
|
|
||||||
// Create a new timeline record for 'Set up job'
|
// Create a new timeline record for 'Set up job'
|
||||||
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Set up job", $"{nameof(JobExtension)}_Init", null, null);
|
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Set up job", $"{nameof(JobExtension)}_Init", null, null, ActionRunStage.Pre);
|
||||||
|
|
||||||
List<IStep> preJobSteps = new List<IStep>();
|
List<IStep> preJobSteps = new List<IStep>();
|
||||||
List<IStep> jobSteps = new List<IStep>();
|
List<IStep> jobSteps = new List<IStep>();
|
||||||
@@ -122,26 +122,32 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tokenPermissions = jobContext.Global.Variables.Get("system.github.token.permissions") ?? "";
|
var tokenPermissions = jobContext.Global.Variables.Get("system.github.token.permissions") ?? "";
|
||||||
if (!string.IsNullOrEmpty(tokenPermissions))
|
if (!string.IsNullOrEmpty(tokenPermissions))
|
||||||
{
|
{
|
||||||
context.Output($"##[group]GITHUB_TOKEN Permissions");
|
context.Output($"##[group]GITHUB_TOKEN Permissions");
|
||||||
var permissions = StringUtil.ConvertFromJson<Dictionary<string, string>>(tokenPermissions);
|
var permissions = StringUtil.ConvertFromJson<Dictionary<string, string>>(tokenPermissions);
|
||||||
foreach(KeyValuePair<string, string> entry in permissions)
|
foreach (KeyValuePair<string, string> entry in permissions)
|
||||||
{
|
{
|
||||||
context.Output($"{entry.Key}: {entry.Value}");
|
context.Output($"{entry.Key}: {entry.Value}");
|
||||||
}
|
}
|
||||||
context.Output("##[endgroup]");
|
context.Output("##[endgroup]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
context.Output($"Fail to parse and display GITHUB_TOKEN permissions list: {ex.Message}");
|
context.Output($"Fail to parse and display GITHUB_TOKEN permissions list: {ex.Message}");
|
||||||
Trace.Error(ex);
|
Trace.Error(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var secretSource = context.GetGitHubContext("secret_source");
|
||||||
|
if (!string.IsNullOrEmpty(secretSource))
|
||||||
|
{
|
||||||
|
context.Output($"Secret source: {secretSource}");
|
||||||
|
}
|
||||||
|
|
||||||
var repoFullName = context.GetGitHubContext("repository");
|
var repoFullName = context.GetGitHubContext("repository");
|
||||||
ArgUtil.NotNull(repoFullName, nameof(repoFullName));
|
ArgUtil.NotNull(repoFullName, nameof(repoFullName));
|
||||||
context.Debug($"Primary repository: {repoFullName}");
|
context.Debug($"Primary repository: {repoFullName}");
|
||||||
@@ -306,13 +312,13 @@ namespace GitHub.Runner.Worker
|
|||||||
JobExtensionRunner extensionStep = step as JobExtensionRunner;
|
JobExtensionRunner extensionStep = step as JobExtensionRunner;
|
||||||
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
|
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
|
||||||
Guid stepId = Guid.NewGuid();
|
Guid stepId = Guid.NewGuid();
|
||||||
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, null, null, stepId.ToString("N"));
|
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, stepId.ToString("N"), null, stepId.ToString("N"), ActionRunStage.Pre);
|
||||||
}
|
}
|
||||||
else if (step is IActionRunner actionStep)
|
else if (step is IActionRunner actionStep)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||||
Guid stepId = Guid.NewGuid();
|
Guid stepId = Guid.NewGuid();
|
||||||
actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, stepId.ToString("N"), null, null, intraActionStates[actionStep.Action.Id]);
|
actionStep.ExecutionContext = jobContext.CreateChild(stepId, actionStep.DisplayName, stepId.ToString("N"), null, null, ActionRunStage.Pre, intraActionStates[actionStep.Action.Id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +329,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
ArgUtil.NotNull(actionStep, step.DisplayName);
|
ArgUtil.NotNull(actionStep, step.DisplayName);
|
||||||
intraActionStates.TryGetValue(actionStep.Action.Id, out var intraActionState);
|
intraActionStates.TryGetValue(actionStep.Action.Id, out var intraActionState);
|
||||||
actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, null, actionStep.Action.ContextName, intraActionState);
|
actionStep.ExecutionContext = jobContext.CreateChild(actionStep.Action.Id, actionStep.DisplayName, actionStep.Action.Name, null, actionStep.Action.ContextName, ActionRunStage.Main, intraActionState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +400,7 @@ namespace GitHub.Runner.Worker
|
|||||||
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
||||||
|
|
||||||
// create a new timeline record node for 'Finalize job'
|
// create a new timeline record node for 'Finalize job'
|
||||||
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Complete job", $"{nameof(JobExtension)}_Final", null, null);
|
IExecutionContext context = jobContext.CreateChild(Guid.NewGuid(), "Complete job", $"{nameof(JobExtension)}_Final", null, null, ActionRunStage.Post);
|
||||||
using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); }))
|
using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); }))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
using GitHub.DistributedTask.WebApi;
|
using System;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
using GitHub.Runner.Common.Util;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -24,6 +25,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class JobRunner : RunnerService, IJobRunner
|
public sealed class JobRunner : RunnerService, IJobRunner
|
||||||
{
|
{
|
||||||
private IJobServerQueue _jobServerQueue;
|
private IJobServerQueue _jobServerQueue;
|
||||||
|
private RunnerSettings _runnerSettings;
|
||||||
private ITempDirectoryManager _tempDirectoryManager;
|
private ITempDirectoryManager _tempDirectoryManager;
|
||||||
|
|
||||||
public async Task<TaskResult> RunAsync(Pipelines.AgentJobRequestMessage message, CancellationToken jobRequestCancellationToken)
|
public async Task<TaskResult> RunAsync(Pipelines.AgentJobRequestMessage message, CancellationToken jobRequestCancellationToken)
|
||||||
@@ -105,9 +107,10 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
jobContext.SetRunnerContext("os", VarUtil.OS);
|
jobContext.SetRunnerContext("os", VarUtil.OS);
|
||||||
|
jobContext.SetRunnerContext("arch", VarUtil.OSArchitecture);
|
||||||
|
|
||||||
var runnerSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
|
_runnerSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
|
||||||
jobContext.SetRunnerContext("name", runnerSettings.AgentName);
|
jobContext.SetRunnerContext("name", _runnerSettings.AgentName);
|
||||||
|
|
||||||
string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools);
|
string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools);
|
||||||
Directory.CreateDirectory(toolsDirectory);
|
Directory.CreateDirectory(toolsDirectory);
|
||||||
@@ -207,6 +210,53 @@ namespace GitHub.Runner.Worker
|
|||||||
jobContext.Debug($"Finishing: {message.JobDisplayName}");
|
jobContext.Debug($"Finishing: {message.JobDisplayName}");
|
||||||
TaskResult result = jobContext.Complete(taskResult);
|
TaskResult result = jobContext.Complete(taskResult);
|
||||||
|
|
||||||
|
if (_runnerSettings.DisableUpdate == true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var currentVersion = new PackageVersion(BuildConstants.RunnerPackage.Version);
|
||||||
|
ServiceEndpoint systemConnection = message.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
|
VssCredentials serverCredential = VssUtil.GetVssCredential(systemConnection);
|
||||||
|
|
||||||
|
var runnerServer = HostContext.GetService<IRunnerServer>();
|
||||||
|
await runnerServer.ConnectAsync(systemConnection.Url, serverCredential);
|
||||||
|
var serverPackages = await runnerServer.GetPackagesAsync("agent", BuildConstants.RunnerPackage.PackageName, 5, includeToken: false, cancellationToken: CancellationToken.None);
|
||||||
|
if (serverPackages.Count > 0)
|
||||||
|
{
|
||||||
|
serverPackages = serverPackages.OrderByDescending(x => x.Version).ToList();
|
||||||
|
Trace.Info($"Newer packages {StringUtil.ConvertToJson(serverPackages.Select(x => x.Version.ToString()))}");
|
||||||
|
|
||||||
|
var warnOnFailedJob = false; // any minor/patch version behind.
|
||||||
|
var warnOnOldRunnerVersion = false; // >= 2 minor version behind
|
||||||
|
if (serverPackages.Any(x => x.Version.CompareTo(currentVersion) > 0))
|
||||||
|
{
|
||||||
|
Trace.Info($"Current runner version {currentVersion} is behind the latest runner version {serverPackages[0].Version}.");
|
||||||
|
warnOnFailedJob = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverPackages.Where(x => x.Version.Major == currentVersion.Major && x.Version.Minor > currentVersion.Minor).Count() > 1)
|
||||||
|
{
|
||||||
|
Trace.Info($"Current runner version {currentVersion} is way behind the latest runner version {serverPackages[0].Version}.");
|
||||||
|
warnOnOldRunnerVersion = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == TaskResult.Failed && warnOnFailedJob)
|
||||||
|
{
|
||||||
|
jobContext.Warning($"This job failure may be caused by using an out of date self-hosted runner. You are currently using runner version {currentVersion}. Please update to the latest version {serverPackages[0].Version}");
|
||||||
|
}
|
||||||
|
else if (warnOnOldRunnerVersion)
|
||||||
|
{
|
||||||
|
jobContext.Warning($"This self-hosted runner is currently using runner version {currentVersion}. This version is out of date. Please update to the latest version {serverPackages[0].Version}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Ignore any error since suggest runner update is best effort.
|
||||||
|
Trace.Error($"Caught exception during runner version check: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ShutdownQueue(throwOnFailure: true);
|
await ShutdownQueue(throwOnFailure: true);
|
||||||
@@ -228,6 +278,9 @@ namespace GitHub.Runner.Worker
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load any upgrade telemetry
|
||||||
|
LoadFromTelemetryFile(jobContext.JobTelemetry);
|
||||||
|
|
||||||
// Make sure we don't submit secrets as telemetry
|
// Make sure we don't submit secrets as telemetry
|
||||||
MaskTelemetrySecrets(jobContext.JobTelemetry);
|
MaskTelemetrySecrets(jobContext.JobTelemetry);
|
||||||
|
|
||||||
@@ -285,6 +338,30 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadFromTelemetryFile(List<JobTelemetry> jobTelemetry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var telemetryFilePath = HostContext.GetConfigFile(WellKnownConfigFile.Telemetry);
|
||||||
|
if (File.Exists(telemetryFilePath))
|
||||||
|
{
|
||||||
|
var telemetryData = File.ReadAllText(telemetryFilePath, Encoding.UTF8);
|
||||||
|
var telemetry = new JobTelemetry
|
||||||
|
{
|
||||||
|
Message = $"Runner File Telemetry:\n{telemetryData}",
|
||||||
|
Type = JobTelemetryType.General
|
||||||
|
};
|
||||||
|
jobTelemetry.Add(telemetry);
|
||||||
|
IOUtil.DeleteFile(telemetryFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Trace.Error("Error when trying to load telemetry from telemetry file");
|
||||||
|
Trace.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ShutdownQueue(bool throwOnFailure)
|
private async Task ShutdownQueue(bool throwOnFailure)
|
||||||
{
|
{
|
||||||
if (_jobServerQueue != null)
|
if (_jobServerQueue != null)
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
<PredefinedCulturesOnly>false</PredefinedCulturesOnly>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -22,12 +23,13 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
private readonly TimeSpan _workerStartTimeout = TimeSpan.FromSeconds(30);
|
private readonly TimeSpan _workerStartTimeout = TimeSpan.FromSeconds(30);
|
||||||
private ManualResetEvent _completedCommand = new ManualResetEvent(false);
|
private ManualResetEvent _completedCommand = new ManualResetEvent(false);
|
||||||
|
|
||||||
// Do not mask the values of these secrets
|
// Do not mask the values of these secrets
|
||||||
private static HashSet<String> SecretVariableMaskWhitelist = new HashSet<String>(StringComparer.OrdinalIgnoreCase){
|
private static HashSet<String> SecretVariableMaskWhitelist = new HashSet<String>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
Constants.Variables.Actions.StepDebug,
|
Constants.Variables.Actions.StepDebug,
|
||||||
Constants.Variables.Actions.RunnerDebug
|
Constants.Variables.Actions.RunnerDebug
|
||||||
};
|
};
|
||||||
|
|
||||||
public async Task<int> RunAsync(string pipeIn, string pipeOut)
|
public async Task<int> RunAsync(string pipeIn, string pipeOut)
|
||||||
{
|
{
|
||||||
@@ -42,6 +44,7 @@ namespace GitHub.Runner.Worker
|
|||||||
ArgUtil.NotNullOrEmpty(pipeOut, nameof(pipeOut));
|
ArgUtil.NotNullOrEmpty(pipeOut, nameof(pipeOut));
|
||||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgents, HostContext.WebProxy);
|
VssUtil.InitializeVssClientSettings(HostContext.UserAgents, HostContext.WebProxy);
|
||||||
var jobRunner = HostContext.CreateService<IJobRunner>();
|
var jobRunner = HostContext.CreateService<IJobRunner>();
|
||||||
|
var terminal = HostContext.GetService<ITerminal>();
|
||||||
|
|
||||||
using (var channel = HostContext.CreateService<IProcessChannel>())
|
using (var channel = HostContext.CreateService<IProcessChannel>())
|
||||||
using (var jobRequestCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken))
|
using (var jobRequestCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken))
|
||||||
@@ -63,7 +66,22 @@ namespace GitHub.Runner.Worker
|
|||||||
Trace.Info("Message received.");
|
Trace.Info("Message received.");
|
||||||
ArgUtil.Equal(MessageType.NewJobRequest, channelMessage.MessageType, nameof(channelMessage.MessageType));
|
ArgUtil.Equal(MessageType.NewJobRequest, channelMessage.MessageType, nameof(channelMessage.MessageType));
|
||||||
ArgUtil.NotNullOrEmpty(channelMessage.Body, nameof(channelMessage.Body));
|
ArgUtil.NotNullOrEmpty(channelMessage.Body, nameof(channelMessage.Body));
|
||||||
var jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(channelMessage.Body);
|
Pipelines.AgentJobRequestMessage jobMessage = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(channelMessage.Body);
|
||||||
|
}
|
||||||
|
catch (JsonReaderException ex)
|
||||||
|
{
|
||||||
|
if (channelMessage.Body.Length > ex.LinePosition + 10)
|
||||||
|
{
|
||||||
|
var errorChunk = channelMessage.Body.Substring(ex.LinePosition - 10, 20);
|
||||||
|
terminal.WriteError($"Worker received invalid Json at position '{ex.LinePosition}': {errorChunk} ({Convert.ToBase64String(Encoding.UTF8.GetBytes(errorChunk))})");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
ArgUtil.NotNull(jobMessage, nameof(jobMessage));
|
ArgUtil.NotNull(jobMessage, nameof(jobMessage));
|
||||||
HostContext.WritePerfCounter($"WorkerJobMessageReceived_{jobMessage.RequestId.ToString()}");
|
HostContext.WritePerfCounter($"WorkerJobMessageReceived_{jobMessage.RequestId.ToString()}");
|
||||||
|
|
||||||
@@ -138,10 +156,10 @@ namespace GitHub.Runner.Worker
|
|||||||
HostContext.SecretMasker.AddValue(value);
|
HostContext.SecretMasker.AddValue(value);
|
||||||
|
|
||||||
// Also add each individual line. Typically individual lines are processed from STDOUT of child processes.
|
// Also add each individual line. Typically individual lines are processed from STDOUT of child processes.
|
||||||
var split = value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
var split = value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
foreach (var item in split)
|
foreach (var item in split)
|
||||||
{
|
{
|
||||||
HostContext.SecretMasker.AddValue(item.Trim());
|
HostContext.SecretMasker.AddValue(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
"runs": {
|
"runs": {
|
||||||
"one-of": [
|
"one-of": [
|
||||||
"container-runs",
|
"container-runs",
|
||||||
"node12-runs",
|
"node-runs",
|
||||||
"plugin-runs",
|
"plugin-runs",
|
||||||
"composite-runs"
|
"composite-runs"
|
||||||
]
|
]
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"loose-value-type": "string"
|
"loose-value-type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node12-runs": {
|
"node-runs": {
|
||||||
"mapping": {
|
"mapping": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"using": "non-empty-string",
|
"using": "non-empty-string",
|
||||||
@@ -112,10 +112,10 @@
|
|||||||
"item-type": "composite-step"
|
"item-type": "composite-step"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"composite-step":{
|
"composite-step": {
|
||||||
"one-of": [
|
"one-of": [
|
||||||
"run-step",
|
"run-step",
|
||||||
"uses-step"
|
"uses-step"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"run-step": {
|
"run-step": {
|
||||||
@@ -123,6 +123,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"name": "string-steps-context",
|
"name": "string-steps-context",
|
||||||
"id": "non-empty-string",
|
"id": "non-empty-string",
|
||||||
|
"if": "step-if",
|
||||||
"run": {
|
"run": {
|
||||||
"type": "string-steps-context",
|
"type": "string-steps-context",
|
||||||
"required": true
|
"required": true
|
||||||
@@ -141,6 +142,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"name": "string-steps-context",
|
"name": "string-steps-context",
|
||||||
"id": "non-empty-string",
|
"id": "non-empty-string",
|
||||||
|
"if": "step-if",
|
||||||
"uses": {
|
"uses": {
|
||||||
"type": "non-empty-string",
|
"type": "non-empty-string",
|
||||||
"required": true
|
"required": true
|
||||||
@@ -216,6 +218,24 @@
|
|||||||
"loose-value-type": "string"
|
"loose-value-type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"step-if": {
|
||||||
|
"context": [
|
||||||
|
"github",
|
||||||
|
"inputs",
|
||||||
|
"strategy",
|
||||||
|
"matrix",
|
||||||
|
"steps",
|
||||||
|
"job",
|
||||||
|
"runner",
|
||||||
|
"env",
|
||||||
|
"always(0,0)",
|
||||||
|
"failure(0,0)",
|
||||||
|
"cancelled(0,0)",
|
||||||
|
"success(0,0)",
|
||||||
|
"hashFiles(1,255)"
|
||||||
|
],
|
||||||
|
"string": {}
|
||||||
|
},
|
||||||
"step-with": {
|
"step-with": {
|
||||||
"context": [
|
"context": [
|
||||||
"github",
|
"github",
|
||||||
@@ -234,4 +254,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,14 +28,6 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<string, object> Properties
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_request.Properties;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<String> IHttpHeaders.GetValues(String name)
|
IEnumerable<String> IHttpHeaders.GetValues(String name)
|
||||||
{
|
{
|
||||||
IEnumerable<String> values;
|
IEnumerable<String> values;
|
||||||
|
|||||||
@@ -14,10 +14,5 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDictionary<string, object> Properties
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace GitHub.Services.Common.Diagnostics
|
|||||||
public static VssTraceActivity GetActivity(this HttpRequestMessage message)
|
public static VssTraceActivity GetActivity(this HttpRequestMessage message)
|
||||||
{
|
{
|
||||||
Object traceActivity;
|
Object traceActivity;
|
||||||
if (!message.Properties.TryGetValue(VssTraceActivity.PropertyName, out traceActivity))
|
if (!message.Options.TryGetValue(VssTraceActivity.PropertyName, out traceActivity))
|
||||||
{
|
{
|
||||||
return VssTraceActivity.Empty;
|
return VssTraceActivity.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves to the message so the underlying token issuers may use it if necessary
|
// Add ourselves to the message so the underlying token issuers may use it if necessary
|
||||||
request.Properties[VssHttpMessageHandler.PropertyName] = this;
|
request.Options.Set(new HttpRequestOptionsKey<VssHttpMessageHandler>(VssHttpMessageHandler.PropertyName), this);
|
||||||
|
|
||||||
Boolean succeeded = false;
|
Boolean succeeded = false;
|
||||||
Boolean lastResponseDemandedProxyAuth = false;
|
Boolean lastResponseDemandedProxyAuth = false;
|
||||||
@@ -409,7 +409,7 @@ namespace GitHub.Services.Common
|
|||||||
// Read the completion option provided by the caller. If we don't find the property then we
|
// Read the completion option provided by the caller. If we don't find the property then we
|
||||||
// assume it is OK to buffer by default.
|
// assume it is OK to buffer by default.
|
||||||
HttpCompletionOption completionOption;
|
HttpCompletionOption completionOption;
|
||||||
if (!request.Properties.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
if (!request.Options.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption))
|
||||||
{
|
{
|
||||||
completionOption = HttpCompletionOption.ResponseContentRead;
|
completionOption = HttpCompletionOption.ResponseContentRead;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ namespace GitHub.Services.Common
|
|||||||
public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo)
|
public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo)
|
||||||
{
|
{
|
||||||
object existingTraceInfo;
|
object existingTraceInfo;
|
||||||
if (!message.Properties.TryGetValue(TfsTraceInfoKey, out existingTraceInfo))
|
if (!message.Options.TryGetValue(TfsTraceInfoKey, out existingTraceInfo))
|
||||||
{
|
{
|
||||||
message.Properties.Add(TfsTraceInfoKey, traceInfo);
|
message.Options.Set(new HttpRequestOptionsKey<VssHttpMessageHandlerTraceInfo>(TfsTraceInfoKey), traceInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
VssHttpMessageHandlerTraceInfo traceInfo = null;
|
VssHttpMessageHandlerTraceInfo traceInfo = null;
|
||||||
|
|
||||||
if (message.Properties.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
|
if (message.Options.TryGetValue(TfsTraceInfoKey, out object traceInfoObject))
|
||||||
{
|
{
|
||||||
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
|
traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
namespace GitHub.Services.Common
|
namespace GitHub.Services.Common
|
||||||
{
|
{
|
||||||
@@ -291,12 +292,12 @@ namespace GitHub.Services.Common
|
|||||||
protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
|
protected internal virtual Boolean ApplyTo(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
// Make sure we only apply the settings to the request once
|
// Make sure we only apply the settings to the request once
|
||||||
if (request.Properties.ContainsKey(PropertyName))
|
if (request.Options.TryGetValue<object>(PropertyName, out _))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Properties.Add(PropertyName, this);
|
request.Options.Set(new HttpRequestOptionsKey<VssHttpRequestSettings>(PropertyName), this);
|
||||||
|
|
||||||
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
|
if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
public VssHttpRetryMessageHandler(
|
public VssHttpRetryMessageHandler(
|
||||||
VssHttpRetryOptions options,
|
VssHttpRetryOptions options,
|
||||||
HttpMessageHandler innerHandler)
|
HttpMessageHandler innerHandler)
|
||||||
: base(innerHandler)
|
: base(innerHandler)
|
||||||
{
|
{
|
||||||
@@ -55,7 +55,7 @@ namespace GitHub.Services.Common
|
|||||||
// Allow overriding default retry options per request
|
// Allow overriding default retry options per request
|
||||||
VssHttpRetryOptions retryOptions = m_retryOptions;
|
VssHttpRetryOptions retryOptions = m_retryOptions;
|
||||||
object retryOptionsObject;
|
object retryOptionsObject;
|
||||||
if (request.Properties.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
if (request.Options.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
||||||
{
|
{
|
||||||
// Fallback to default options if object of unexpected type was passed
|
// Fallback to default options if object of unexpected type was passed
|
||||||
retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions;
|
retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions;
|
||||||
@@ -66,7 +66,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
IVssHttpRetryInfo retryInfo = null;
|
IVssHttpRetryInfo retryInfo = null;
|
||||||
object retryInfoObject;
|
object retryInfoObject;
|
||||||
if (request.Properties.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
if (request.Options.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue<T> is not
|
||||||
{
|
{
|
||||||
retryInfo = retryInfoObject as IVssHttpRetryInfo;
|
retryInfo = retryInfoObject as IVssHttpRetryInfo;
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
// implement in Server so retries are recorded in ProductTrace
|
// implement in Server so retries are recorded in ProductTrace
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void TraceHttpRequestFailed(VssTraceActivity activity, HttpRequestMessage request, HttpStatusCode statusCode, string afdRefInfo)
|
protected virtual void TraceHttpRequestFailed(VssTraceActivity activity, HttpRequestMessage request, HttpStatusCode statusCode, string afdRefInfo)
|
||||||
{
|
{
|
||||||
VssHttpEventSource.Log.HttpRequestFailed(activity, request, statusCode, afdRefInfo);
|
VssHttpEventSource.Log.HttpRequestFailed(activity, request, statusCode, afdRefInfo);
|
||||||
@@ -212,7 +212,7 @@ namespace GitHub.Services.Common
|
|||||||
private static bool IsLowPriority(HttpRequestMessage request)
|
private static bool IsLowPriority(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
bool isLowPriority = false;
|
bool isLowPriority = false;
|
||||||
|
|
||||||
IEnumerable<string> headers;
|
IEnumerable<string> headers;
|
||||||
|
|
||||||
if (request.Headers.TryGetValues(HttpHeaders.VssRequestPriority, out headers) && headers != null)
|
if (request.Headers.TryGetValues(HttpHeaders.VssRequestPriority, out headers) && headers != null)
|
||||||
|
|||||||
@@ -768,6 +768,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="poolId"></param>
|
/// <param name="poolId"></param>
|
||||||
/// <param name="agentId"></param>
|
/// <param name="agentId"></param>
|
||||||
/// <param name="currentState"></param>
|
/// <param name="currentState"></param>
|
||||||
|
/// <param name="updateTrace"></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)]
|
||||||
@@ -775,6 +776,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
int poolId,
|
int poolId,
|
||||||
int agentId,
|
int agentId,
|
||||||
string currentState,
|
string currentState,
|
||||||
|
string updateTrace,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -784,6 +786,7 @@ 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("currentState", currentState);
|
queryParams.Add("currentState", currentState);
|
||||||
|
queryParams.Add("updateTrace", updateTrace);
|
||||||
|
|
||||||
return SendAsync<TaskAgent>(
|
return SendAsync<TaskAgent>(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
@@ -794,65 +797,5 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
userState: userState,
|
userState: userState,
|
||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// [Preview API]
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="poolId"></param>
|
|
||||||
/// <param name="agentId"></param>
|
|
||||||
/// <param name="userState"></param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
|
||||||
public Task<String> GetAgentAuthUrlAsync(
|
|
||||||
int poolId,
|
|
||||||
int agentId,
|
|
||||||
object userState = null,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
HttpMethod httpMethod = new HttpMethod("GET");
|
|
||||||
Guid locationId = new Guid("a82a119c-1e46-44b6-8d75-c82a79cf975b");
|
|
||||||
object routeValues = new { poolId = poolId, agentId = agentId };
|
|
||||||
|
|
||||||
return SendAsync<String>(
|
|
||||||
httpMethod,
|
|
||||||
locationId,
|
|
||||||
routeValues: routeValues,
|
|
||||||
version: new ApiResourceVersion(6.0, 1),
|
|
||||||
userState: userState,
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// [Preview API]
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="poolId"></param>
|
|
||||||
/// <param name="agentId"></param>
|
|
||||||
/// <param name="error"></param>
|
|
||||||
/// <param name="userState"></param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
||||||
public virtual async Task ReportAgentAuthUrlMigrationErrorAsync(
|
|
||||||
int poolId,
|
|
||||||
int agentId,
|
|
||||||
string error,
|
|
||||||
object userState = null,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
HttpMethod httpMethod = new HttpMethod("POST");
|
|
||||||
Guid locationId = new Guid("a82a119c-1e46-44b6-8d75-c82a79cf975b");
|
|
||||||
object routeValues = new { poolId = poolId, agentId = agentId };
|
|
||||||
HttpContent content = new ObjectContent<string>(error, new VssJsonMediaTypeFormatter(true));
|
|
||||||
|
|
||||||
using (HttpResponseMessage response = await SendAsync(
|
|
||||||
httpMethod,
|
|
||||||
locationId,
|
|
||||||
routeValues: routeValues,
|
|
||||||
version: new ApiResourceVersion(6.0, 1),
|
|
||||||
userState: userState,
|
|
||||||
cancellationToken: cancellationToken,
|
|
||||||
content: content).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,20 @@ namespace GitHub.DistributedTask.Logging
|
|||||||
return Base64StringEscapeShift(value, 2);
|
return Base64StringEscapeShift(value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String BashComparand(String value)
|
||||||
|
{
|
||||||
|
var result = new StringBuilder();
|
||||||
|
foreach (var c in value)
|
||||||
|
{
|
||||||
|
if (!char.IsLowSurrogate(c))
|
||||||
|
{
|
||||||
|
result.Append('\\');
|
||||||
|
}
|
||||||
|
result.Append(c);
|
||||||
|
}
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
// Used when we pass environment variables to docker to escape " with \"
|
// Used when we pass environment variables to docker to escape " with \"
|
||||||
public static String CommandLineArgumentEscape(String value)
|
public static String CommandLineArgumentEscape(String value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -638,6 +638,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
||||||
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Inputs),
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
|
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
namespace GitHub.DistributedTask.WebApi
|
||||||
@@ -59,10 +61,21 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File ID in file service
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public Int32? FileId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Auth token to download the package
|
/// Auth token to download the package
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public String Token
|
public String Token
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -70,7 +83,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MD5 hash as a base64 string
|
/// SHA256 hash
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public String HashValue
|
public String HashValue
|
||||||
@@ -90,7 +103,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The UI uses this to display instructions, i.e. "unzip MyAgent.zip"
|
/// The UI uses this to display instructions, e.g. "unzip MyAgent.zip"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public String Filename
|
public String Filename
|
||||||
@@ -98,5 +111,43 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A set of trimmed down packages:
|
||||||
|
/// - the package without 'externals'
|
||||||
|
/// - the package without 'dotnet runtime'
|
||||||
|
/// - the package without 'dotnet runtime' and 'externals'
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public List<TrimmedPackageMetadata> TrimmedPackages
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract]
|
||||||
|
public class TrimmedPackageMetadata
|
||||||
|
{
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public string HashValue { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public string DownloadUrl { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> TrimmedContents
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_trimmedContents == null)
|
||||||
|
{
|
||||||
|
m_trimmedContents = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
return m_trimmedContents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "TrimmedContents", EmitDefaultValue = false)]
|
||||||
|
private Dictionary<string, string> m_trimmedContents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
this.ProvisioningState = referenceToBeCloned.ProvisioningState;
|
this.ProvisioningState = referenceToBeCloned.ProvisioningState;
|
||||||
this.AccessPoint = referenceToBeCloned.AccessPoint;
|
this.AccessPoint = referenceToBeCloned.AccessPoint;
|
||||||
this.Ephemeral = referenceToBeCloned.Ephemeral;
|
this.Ephemeral = referenceToBeCloned.Ephemeral;
|
||||||
|
this.DisableUpdate = referenceToBeCloned.DisableUpdate;
|
||||||
|
|
||||||
if (referenceToBeCloned.m_links != null)
|
if (referenceToBeCloned.m_links != null)
|
||||||
{
|
{
|
||||||
@@ -92,6 +93,16 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this agent should auto-update to latest version.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public bool? DisableUpdate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not the agent is online.
|
/// Whether or not the agent is online.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</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</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -833,20 +833,20 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
if (userState != null)
|
if (userState != null)
|
||||||
{
|
{
|
||||||
message.Properties[UserStatePropertyName] = userState;
|
message.Options.Set(new HttpRequestOptionsKey<object>(UserStatePropertyName), userState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
|
if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID))
|
||||||
{
|
{
|
||||||
message.Headers.Add(Common.Internal.HttpHeaders.VssE2EID, Guid.NewGuid().ToString("D"));
|
message.Headers.Add(Common.Internal.HttpHeaders.VssE2EID, Guid.NewGuid().ToString("D"));
|
||||||
}
|
}
|
||||||
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
|
VssHttpEventSource.Log.HttpRequestStart(traceActivity, message);
|
||||||
message.Trace();
|
message.Trace();
|
||||||
message.Properties[VssTraceActivity.PropertyName] = traceActivity;
|
message.Options.Set(new HttpRequestOptionsKey<VssTraceActivity>(VssTraceActivity.PropertyName), traceActivity);
|
||||||
|
|
||||||
// Send the completion option to the inner handler stack so we know when it's safe to buffer
|
// Send the completion option to the inner handler stack so we know when it's safe to buffer
|
||||||
// and when we should avoid buffering.
|
// and when we should avoid buffering.
|
||||||
message.Properties[VssHttpRequestSettings.HttpCompletionOptionPropertyName] = completionOption;
|
message.Options.Set(new HttpRequestOptionsKey<HttpCompletionOption>(VssHttpRequestSettings.HttpCompletionOptionPropertyName), completionOption);
|
||||||
|
|
||||||
//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
|
||||||
@@ -872,7 +872,7 @@ namespace GitHub.Services.WebApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async Task HandleResponseAsync(
|
protected virtual async Task HandleResponseAsync(
|
||||||
HttpResponseMessage response,
|
HttpResponseMessage response,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
response.Trace();
|
response.Trace();
|
||||||
@@ -1154,12 +1154,14 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
if (BaseAddress != null)
|
if (BaseAddress != null)
|
||||||
{
|
{
|
||||||
|
#pragma warning disable SYSLIB0014
|
||||||
ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress);
|
ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress);
|
||||||
servicePoint.UseNagleAlgorithm = false;
|
servicePoint.UseNagleAlgorithm = false;
|
||||||
servicePoint.SetTcpKeepAlive(
|
servicePoint.SetTcpKeepAlive(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
keepAliveTime: c_keepAliveTime,
|
keepAliveTime: c_keepAliveTime,
|
||||||
keepAliveInterval: c_keepAliveInterval);
|
keepAliveInterval: c_keepAliveInterval);
|
||||||
|
#pragma warning restore SYSLIB0014
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ namespace GitHub.Services.WebApi
|
|||||||
|
|
||||||
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.EscapeUri))
|
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.EscapeUri))
|
||||||
{
|
{
|
||||||
sbResult = new StringBuilder(Uri.EscapeUriString(sbResult.ToString()));
|
sbResult = new StringBuilder(Uri.EscapeDataString(sbResult.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.AppendUnusedAsQueryParams) && unusedValues.Count > 0)
|
if (routeReplacementOptions.HasFlag(RouteReplacementOptions.AppendUnusedAsQueryParams) && unusedValues.Count > 0)
|
||||||
|
|||||||
@@ -16,9 +16,8 @@ namespace GitHub.Services.WebApi
|
|||||||
|
|
||||||
internal static void Trace(this HttpRequestMessage request)
|
internal static void Trace(this HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
Object tracerObj = null;
|
VssRequestTimerTrace tracer;
|
||||||
VssRequestTimerTrace tracer = null;
|
if (request.Options.TryGetValue(tracerKey, out object tracerObj))
|
||||||
if (request.Properties.TryGetValue(tracerKey, out tracerObj))
|
|
||||||
{
|
{
|
||||||
tracer = tracerObj as VssRequestTimerTrace;
|
tracer = tracerObj as VssRequestTimerTrace;
|
||||||
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
||||||
@@ -26,7 +25,7 @@ namespace GitHub.Services.WebApi
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
tracer = new VssRequestTimerTrace();
|
tracer = new VssRequestTimerTrace();
|
||||||
request.Properties[tracerKey] = tracer;
|
request.Options.Set(new HttpRequestOptionsKey<VssRequestTimerTrace>(tracerKey), tracer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracer != null)
|
if (tracer != null)
|
||||||
@@ -37,9 +36,8 @@ namespace GitHub.Services.WebApi
|
|||||||
|
|
||||||
internal static void Trace(this HttpResponseMessage response)
|
internal static void Trace(this HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
Object tracerObj = null;
|
|
||||||
VssRequestTimerTrace tracer = null;
|
VssRequestTimerTrace tracer = null;
|
||||||
if (response.RequestMessage.Properties.TryGetValue(tracerKey, out tracerObj))
|
if (response.RequestMessage.Options.TryGetValue(tracerKey, out object tracerObj))
|
||||||
{
|
{
|
||||||
tracer = tracerObj as VssRequestTimerTrace;
|
tracer = tracerObj as VssRequestTimerTrace;
|
||||||
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
Debug.Assert(tracer != null, "Tracer object is the wrong type!");
|
||||||
|
|||||||
@@ -547,6 +547,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
[Trait("Category", nameof(CommandSettings))]
|
||||||
@@ -603,7 +604,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
Assert.Equal("some windows logon password", actual);
|
Assert.Equal("some windows logon password", actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
[Trait("Category", nameof(CommandSettings))]
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
_serviceControlManager = new Mock<ILinuxServiceControlManager>();
|
_serviceControlManager = new Mock<ILinuxServiceControlManager>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var expectedAgent = new TaskAgent(_expectedAgentName) { Id = 1 };
|
var expectedAgent = new TaskAgent(_expectedAgentName) { Id = 1, Ephemeral = true, DisableUpdate = true };
|
||||||
expectedAgent.Authorization = new TaskAgentAuthorization
|
expectedAgent.Authorization = new TaskAgentAuthorization
|
||||||
{
|
{
|
||||||
ClientId = Guid.NewGuid(),
|
ClientId = Guid.NewGuid(),
|
||||||
@@ -154,7 +154,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
tc,
|
tc,
|
||||||
new[]
|
new[]
|
||||||
{
|
{
|
||||||
"configure",
|
"configure",
|
||||||
"--url", _expectedServerUrl,
|
"--url", _expectedServerUrl,
|
||||||
"--name", _expectedAgentName,
|
"--name", _expectedAgentName,
|
||||||
"--runnergroup", _secondRunnerGroupName,
|
"--runnergroup", _secondRunnerGroupName,
|
||||||
@@ -163,6 +163,8 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
"--token", _expectedToken,
|
"--token", _expectedToken,
|
||||||
"--labels", userLabels,
|
"--labels", userLabels,
|
||||||
"--ephemeral",
|
"--ephemeral",
|
||||||
|
"--disableupdate",
|
||||||
|
"--unattended",
|
||||||
});
|
});
|
||||||
trace.Info("Constructed.");
|
trace.Info("Constructed.");
|
||||||
_store.Setup(x => x.IsConfigured()).Returns(false);
|
_store.Setup(x => x.IsConfigured()).Returns(false);
|
||||||
@@ -185,7 +187,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
// validate GetAgentPoolsAsync gets called twice with automation pool type
|
// validate GetAgentPoolsAsync gets called twice with automation pool type
|
||||||
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));
|
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));
|
||||||
|
|
||||||
var expectedLabels = new List<string>() { "self-hosted", VarUtil.OS, VarUtil.OSArchitecture};
|
var expectedLabels = new List<string>() { "self-hosted", VarUtil.OS, VarUtil.OSArchitecture };
|
||||||
expectedLabels.AddRange(userLabels.Split(",").ToList());
|
expectedLabels.AddRange(userLabels.Split(",").ToList());
|
||||||
|
|
||||||
_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Select(x => x.Name).ToHashSet().SetEquals(expectedLabels))), Times.Once);
|
_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Select(x => x.Name).ToHashSet().SetEquals(expectedLabels))), Times.Once);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Test.L0.Listener.Configuration
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
#pragma warning disable CA1416
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "ConfigurationManagement")]
|
[Trait("Category", "ConfigurationManagement")]
|
||||||
@@ -50,6 +51,7 @@ namespace Test.L0.Listener.Configuration
|
|||||||
Assert.True(defaultServiceAccount.ToString().Equals(@"NT AUTHORITY\SYSTEM"), "If agent is getting configured as deployment agent, default service accout should be 'NT AUTHORITY\\SYSTEM'");
|
Assert.True(defaultServiceAccount.ToString().Equals(@"NT AUTHORITY\SYSTEM"), "If agent is getting configured as deployment agent, default service accout should be 'NT AUTHORITY\\SYSTEM'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
786
src/Test/L0/Listener/SelfUpdaterL0.cs
Normal file
786
src/Test/L0/Listener/SelfUpdaterL0.cs
Normal file
@@ -0,0 +1,786 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using GitHub.Runner.Listener;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common.Tests.Listener
|
||||||
|
{
|
||||||
|
public sealed class SelfUpdaterL0
|
||||||
|
{
|
||||||
|
private Mock<IRunnerServer> _runnerServer;
|
||||||
|
private Mock<ITerminal> _term;
|
||||||
|
private Mock<IConfigurationStore> _configStore;
|
||||||
|
private Mock<IJobDispatcher> _jobDispatcher;
|
||||||
|
private AgentRefreshMessage _refreshMessage = new AgentRefreshMessage(1, "2.299.0");
|
||||||
|
private List<TrimmedPackageMetadata> _trimmedPackages = new List<TrimmedPackageMetadata>();
|
||||||
|
|
||||||
|
#if !OS_WINDOWS
|
||||||
|
private string _packageUrl = null;
|
||||||
|
#else
|
||||||
|
private string _packageUrl = null;
|
||||||
|
#endif
|
||||||
|
public SelfUpdaterL0()
|
||||||
|
{
|
||||||
|
_runnerServer = new Mock<IRunnerServer>();
|
||||||
|
_term = new Mock<ITerminal>();
|
||||||
|
_configStore = new Mock<IConfigurationStore>();
|
||||||
|
_jobDispatcher = new Mock<IJobDispatcher>();
|
||||||
|
_configStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1, AgentId = 1 });
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("_GITHUB_ACTION_EXECUTE_UPDATE_SCRIPT", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FetchLatestRunner()
|
||||||
|
{
|
||||||
|
var latestVersion = "";
|
||||||
|
var httpClientHandler = new HttpClientHandler();
|
||||||
|
httpClientHandler.AllowAutoRedirect = false;
|
||||||
|
using (var client = new HttpClient(httpClientHandler))
|
||||||
|
{
|
||||||
|
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://github.com/actions/runner/releases/latest"));
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.Redirect)
|
||||||
|
{
|
||||||
|
var redirect = await response.Content.ReadAsStringAsync();
|
||||||
|
Regex regex = new Regex(@"/runner/releases/tag/v(?<version>\d+\.\d+\.\d+)");
|
||||||
|
var match = regex.Match(redirect);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
latestVersion = match.Groups["version"].Value;
|
||||||
|
|
||||||
|
#if !OS_WINDOWS
|
||||||
|
_packageUrl = $"https://github.com/actions/runner/releases/download/v{latestVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{latestVersion}.tar.gz";
|
||||||
|
#else
|
||||||
|
_packageUrl = $"https://github.com/actions/runner/releases/download/v{latestVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{latestVersion}.zip";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
var json = await client.GetStringAsync($"https://github.com/actions/runner/releases/download/v{latestVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{latestVersion}-trimmedpackages.json");
|
||||||
|
_trimmedPackages = StringUtil.ConvertFromJson<List<TrimmedPackageMetadata>>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl }));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_NoUpdateOnOldVersion()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.200.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.200.0"), DownloadUrl = _packageUrl }));
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
var result = await updater.SelfUpdate(new AgentRefreshMessage(1, "2.200.0"), _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_DownloadRetry()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = $"https://github.com/actions/runner/notexists" }));
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
|
||||||
|
var ex = await Assert.ThrowsAsync<TaskCanceledException>(() => updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken));
|
||||||
|
Assert.Contains($"failed after {Constants.RunnerDownloadRetryMaxAttempts} download attempts", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_ValidateHash()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, HashValue = "bad_hash" }));
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
|
||||||
|
var ex = await Assert.ThrowsAsync<Exception>(() => updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken));
|
||||||
|
Assert.Contains("did not match expected Runner Hash", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_CloneHash_RuntimeAndExternals()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, TrimmedPackages = new List<TrimmedPackageMetadata>() { new TrimmedPackageMetadata() } }));
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
|
||||||
|
FieldInfo contentHashesProperty = updater.GetType().GetField("_contentHashes", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
Assert.NotNull(contentHashesProperty);
|
||||||
|
Dictionary<string, string> contentHashes = (Dictionary<string, string>)contentHashesProperty.GetValue(updater);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(contentHashes));
|
||||||
|
|
||||||
|
var dotnetRuntimeHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/dotnetRuntime/{BuildConstants.RunnerPackage.PackageName}");
|
||||||
|
var externalsHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}");
|
||||||
|
|
||||||
|
Assert.Equal(File.ReadAllText(dotnetRuntimeHashFile).Trim(), contentHashes["dotnetRuntime"]);
|
||||||
|
Assert.Equal(File.ReadAllText(externalsHashFile).Trim(), contentHashes["externals"]);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_Cancel_CloneHashTask_WhenNotNeeded()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new Mock<IHttpClientHandlerFactory>().Object);
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper();
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper();
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper();
|
||||||
|
p3.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
|
||||||
|
FieldInfo contentHashesProperty = updater.GetType().GetField("_contentHashes", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
Assert.NotNull(contentHashesProperty);
|
||||||
|
Dictionary<string, string> contentHashes = (Dictionary<string, string>)contentHashesProperty.GetValue(updater);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(contentHashes));
|
||||||
|
|
||||||
|
Assert.NotEqual(2, contentHashes.Count);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
hc.GetTrace().Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_UseExternalsTrimmedPackage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper(); // un-tar
|
||||||
|
p3.Initialize(hc);
|
||||||
|
var p4 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p4.Initialize(hc);
|
||||||
|
var p5 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p5.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p4);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p5);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
var trim = _trimmedPackages.Where(x => !x.TrimmedContents.ContainsKey("dotnetRuntime")).ToList();
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
var traceFile = Path.GetTempFileName();
|
||||||
|
File.Copy(hc.TraceFileName, traceFile, true);
|
||||||
|
|
||||||
|
var externalsHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}");
|
||||||
|
var externalsHash = await File.ReadAllTextAsync(externalsHashFile);
|
||||||
|
|
||||||
|
if (externalsHash == trim[0].TrimmedContents["externals"])
|
||||||
|
{
|
||||||
|
Assert.Contains("Use trimmed (externals) package", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Contains("the current runner does not carry those trimmed content (Hash mismatch)", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_UseExternalsRuntimeTrimmedPackage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper(); // un-tar
|
||||||
|
p3.Initialize(hc);
|
||||||
|
var p4 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p4.Initialize(hc);
|
||||||
|
var p5 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p5.Initialize(hc);
|
||||||
|
var p6 = new ProcessInvokerWrapper(); // runner -v
|
||||||
|
p6.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p4);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p5);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p6);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
var trim = _trimmedPackages.Where(x => x.TrimmedContents.ContainsKey("dotnetRuntime") && x.TrimmedContents.ContainsKey("externals")).ToList();
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
var traceFile = Path.GetTempFileName();
|
||||||
|
File.Copy(hc.TraceFileName, traceFile, true);
|
||||||
|
|
||||||
|
var externalsHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/externals/{BuildConstants.RunnerPackage.PackageName}");
|
||||||
|
var externalsHash = await File.ReadAllTextAsync(externalsHashFile);
|
||||||
|
|
||||||
|
var runtimeHashFile = Path.Combine(TestUtil.GetSrcPath(), $"Misc/contentHash/dotnetRuntime/{BuildConstants.RunnerPackage.PackageName}");
|
||||||
|
var runtimeHash = await File.ReadAllTextAsync(runtimeHashFile);
|
||||||
|
|
||||||
|
if (externalsHash == trim[0].TrimmedContents["externals"] &&
|
||||||
|
runtimeHash == trim[0].TrimmedContents["dotnetRuntime"])
|
||||||
|
{
|
||||||
|
Assert.Contains("Use trimmed (runtime+externals) package", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Contains("the current runner does not carry those trimmed content (Hash mismatch)", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_NotUseExternalsRuntimeTrimmedPackageOnHashMismatch()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper(); // un-tar
|
||||||
|
p3.Initialize(hc);
|
||||||
|
var p4 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p4.Initialize(hc);
|
||||||
|
var p5 = new ProcessInvokerWrapper(); // node -v
|
||||||
|
p5.Initialize(hc);
|
||||||
|
var p6 = new ProcessInvokerWrapper(); // runner -v
|
||||||
|
p6.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p4);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p5);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p6);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
var trim = _trimmedPackages.ToList();
|
||||||
|
foreach (var package in trim)
|
||||||
|
{
|
||||||
|
foreach (var hash in package.TrimmedContents.Keys)
|
||||||
|
{
|
||||||
|
package.TrimmedContents[hash] = "mismatch";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
var traceFile = Path.GetTempFileName();
|
||||||
|
File.Copy(hc.TraceFileName, traceFile, true);
|
||||||
|
Assert.Contains("the current runner does not carry those trimmed content (Hash mismatch)", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Runner")]
|
||||||
|
public async void TestSelfUpdateAsync_FallbackToFullPackage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FetchLatestRunner();
|
||||||
|
Assert.NotNull(_packageUrl);
|
||||||
|
Assert.NotNull(_trimmedPackages);
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", Path.GetFullPath(Path.Combine(TestUtil.GetSrcPath(), "..", "_layout", "bin")));
|
||||||
|
using (var hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(_packageUrl);
|
||||||
|
hc.GetTrace().Info(StringUtil.ConvertToJson(_trimmedPackages));
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
var updater = new Runner.Listener.SelfUpdater();
|
||||||
|
hc.SetSingleton<ITerminal>(_term.Object);
|
||||||
|
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
|
hc.SetSingleton<IConfigurationStore>(_configStore.Object);
|
||||||
|
hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|
||||||
|
var p1 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p1.Initialize(hc);
|
||||||
|
var p2 = new ProcessInvokerWrapper(); // hashfiles
|
||||||
|
p2.Initialize(hc);
|
||||||
|
var p3 = new ProcessInvokerWrapper(); // un-tar trim
|
||||||
|
p3.Initialize(hc);
|
||||||
|
var p4 = new ProcessInvokerWrapper(); // un-tar full
|
||||||
|
p4.Initialize(hc);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p1);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p2);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p3);
|
||||||
|
hc.EnqueueInstance<IProcessInvoker>(p4);
|
||||||
|
updater.Initialize(hc);
|
||||||
|
|
||||||
|
var trim = _trimmedPackages.ToList();
|
||||||
|
foreach (var package in trim)
|
||||||
|
{
|
||||||
|
package.HashValue = "mismatch";
|
||||||
|
}
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, TrimmedPackages = trim }));
|
||||||
|
|
||||||
|
_runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Callback((int p, int a, string s, string t) =>
|
||||||
|
{
|
||||||
|
hc.GetTrace().Info(t);
|
||||||
|
})
|
||||||
|
.Returns(Task.FromResult(new TaskAgent()));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken);
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0")));
|
||||||
|
Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0")));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None);
|
||||||
|
IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
var traceFile = Path.GetTempFileName();
|
||||||
|
File.Copy(hc.TraceFileName, traceFile, true);
|
||||||
|
Assert.Contains("Something wrong with the trimmed runner package, failback to use the full package for runner updates", File.ReadAllText(traceFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
154
src/Test/L0/PackagesTrimL0.cs
Normal file
154
src/Test/L0/PackagesTrimL0.cs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common.Tests
|
||||||
|
{
|
||||||
|
public sealed class PackagesTrimL0
|
||||||
|
{
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public async Task RunnerLayoutParts_NewFilesCrossAll()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
Tracing trace = hc.GetTrace();
|
||||||
|
var runnerCoreAssetsFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnercoreassets");
|
||||||
|
var runnerDotnetRuntimeFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnerdotnetruntimeassets");
|
||||||
|
string layoutBin = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin");
|
||||||
|
var newFiles = new List<string>();
|
||||||
|
if (Directory.Exists(layoutBin))
|
||||||
|
{
|
||||||
|
var coreAssets = await File.ReadAllLinesAsync(runnerCoreAssetsFile);
|
||||||
|
var runtimeAssets = await File.ReadAllLinesAsync(runnerDotnetRuntimeFile);
|
||||||
|
foreach (var file in Directory.GetFiles(layoutBin, "*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
if (!coreAssets.Any(x => file.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).EndsWith(x)) &&
|
||||||
|
!runtimeAssets.Any(x => file.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).EndsWith(x)))
|
||||||
|
{
|
||||||
|
newFiles.Add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newFiles.Count > 0)
|
||||||
|
{
|
||||||
|
Assert.True(false, $"Found new files '{string.Join('\n', newFiles)}'. These will break runner update using trimmed packages.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public async Task RunnerLayoutParts_OverlapFiles()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
Tracing trace = hc.GetTrace();
|
||||||
|
var runnerCoreAssetsFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnercoreassets");
|
||||||
|
var runnerDotnetRuntimeFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnerdotnetruntimeassets");
|
||||||
|
|
||||||
|
var coreAssets = await File.ReadAllLinesAsync(runnerCoreAssetsFile);
|
||||||
|
var runtimeAssets = await File.ReadAllLinesAsync(runnerDotnetRuntimeFile);
|
||||||
|
|
||||||
|
foreach (var line in coreAssets)
|
||||||
|
{
|
||||||
|
if (runtimeAssets.Contains(line, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Assert.True(false, $"'Misc/runnercoreassets' and 'Misc/runnerdotnetruntimeassets' should not overlap.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public async Task RunnerLayoutParts_NewRunnerCoreAssets()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
Tracing trace = hc.GetTrace();
|
||||||
|
var runnerCoreAssetsFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnercoreassets");
|
||||||
|
var coreAssets = await File.ReadAllLinesAsync(runnerCoreAssetsFile);
|
||||||
|
|
||||||
|
string layoutBin = Path.Combine(TestUtil.GetSrcPath(), @"../_layout/bin");
|
||||||
|
var newFiles = new List<string>();
|
||||||
|
if (Directory.Exists(layoutBin))
|
||||||
|
{
|
||||||
|
var binDirs = Directory.GetDirectories(TestUtil.GetSrcPath(), "net6.0", SearchOption.AllDirectories);
|
||||||
|
foreach (var binDir in binDirs)
|
||||||
|
{
|
||||||
|
if (binDir.Contains("Test") || binDir.Contains("obj"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.GetFiles(binDir, "*", SearchOption.TopDirectoryOnly).ToList().ForEach(x =>
|
||||||
|
{
|
||||||
|
if (!x.Contains("runtimeconfig.dev.json"))
|
||||||
|
{
|
||||||
|
if (!coreAssets.Any(y => x.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).EndsWith(y)))
|
||||||
|
{
|
||||||
|
newFiles.Add(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newFiles.Count > 0)
|
||||||
|
{
|
||||||
|
Assert.True(false, $"Found new files '{string.Join('\n', newFiles)}'. These will break runner update using trimmed packages. You might need to update `Misc/runnercoreassets`.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Common")]
|
||||||
|
public async Task RunnerLayoutParts_NewDotnetRuntimeAssets()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = new TestHostContext(this))
|
||||||
|
{
|
||||||
|
Tracing trace = hc.GetTrace();
|
||||||
|
var runnerDotnetRuntimeFile = Path.Combine(TestUtil.GetSrcPath(), @"Misc/runnerdotnetruntimeassets");
|
||||||
|
var runtimeAssets = await File.ReadAllLinesAsync(runnerDotnetRuntimeFile);
|
||||||
|
|
||||||
|
string layoutTrimsRuntimeAssets = Path.Combine(TestUtil.GetSrcPath(), @"../_layout_trims/runnerdotnetruntimeassets");
|
||||||
|
var newFiles = new List<string>();
|
||||||
|
if (File.Exists(layoutTrimsRuntimeAssets))
|
||||||
|
{
|
||||||
|
var runtimeAssetsCurrent = await File.ReadAllLinesAsync(layoutTrimsRuntimeAssets);
|
||||||
|
foreach (var runtimeFile in runtimeAssetsCurrent)
|
||||||
|
{
|
||||||
|
if (runtimeAssets.Any(x => runtimeFile.EndsWith(x, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newFiles.Add(runtimeFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newFiles.Count > 0)
|
||||||
|
{
|
||||||
|
Assert.True(false, $"Found new dotnet runtime files '{string.Join('\n', newFiles)}'. These will break runner update using trimmed packages. You might need to update `Misc/runnerdotnetruntimeassets`.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -197,7 +197,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
|
execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
|
||||||
#else
|
#else
|
||||||
execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token);
|
execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}\"", null, tokenSource.Token);
|
||||||
#endif
|
#endif
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
|
|||||||
@@ -165,7 +165,15 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
switch (directory)
|
switch (directory)
|
||||||
{
|
{
|
||||||
case WellKnownDirectory.Bin:
|
case WellKnownDirectory.Bin:
|
||||||
path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
var overwriteBinDir = Environment.GetEnvironmentVariable("RUNNER_L0_OVERRIDEBINDIR");
|
||||||
|
if (Directory.Exists(overwriteBinDir))
|
||||||
|
{
|
||||||
|
path = overwriteBinDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WellKnownDirectory.Diag:
|
case WellKnownDirectory.Diag:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
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.Container;
|
||||||
@@ -83,6 +84,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
|
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns((string tag, string line) =>
|
.Returns((string tag, string line) =>
|
||||||
{
|
{
|
||||||
@@ -105,6 +107,88 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("stop-commands", "1")]
|
||||||
|
[InlineData("", "1")]
|
||||||
|
[InlineData("set-env", "1")]
|
||||||
|
[InlineData("stop-commands", "true")]
|
||||||
|
[InlineData("", "true")]
|
||||||
|
[InlineData("set-env", "true")]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void StopProcessCommand__AllowsInvalidStopTokens__IfEnvVarIsSet(string invalidToken, string allowUnsupportedStopCommandTokens)
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
|
||||||
|
var expressionValues = new DictionaryContextData
|
||||||
|
{
|
||||||
|
["env"] =
|
||||||
|
#if OS_WINDOWS
|
||||||
|
new DictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }}
|
||||||
|
#else
|
||||||
|
new CaseSensitiveDictionaryContextData { { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) } }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
_ec.Setup(x => x.ExpressionValues).Returns(expressionValues);
|
||||||
|
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
|
||||||
|
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("stop-commands")]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("set-env")]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void StopProcessCommand__FailOnInvalidStopTokens(string invalidToken)
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
|
||||||
|
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
||||||
|
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
|
||||||
|
Assert.Throws<Exception>(() => _commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void StopProcessCommandAcceptsValidToken()
|
||||||
|
{
|
||||||
|
var validToken = "randomToken";
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
|
||||||
|
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void StopProcessCommandMasksValidTokenForEntireRun()
|
||||||
|
{
|
||||||
|
var validToken = "randomToken";
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
|
||||||
|
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
|
||||||
|
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
|
||||||
|
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -202,15 +286,15 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
var registeredCommands = new HashSet<string>(new string[1]{ "warning" });
|
var registeredCommands = new HashSet<string>(new string[1] { "warning" });
|
||||||
ActionCommand command;
|
ActionCommand command;
|
||||||
|
|
||||||
// Columns when lines are different
|
// Columns when lines are different
|
||||||
ActionCommand.TryParseV2("::warning line=1,endLine=2,col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
ActionCommand.TryParseV2("::warning line=1,endLine=2,col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
||||||
Assert.Equal("1", command.Properties["col"]);
|
Assert.Equal("1", command.Properties["col"]);
|
||||||
IssueCommandExtension.ValidateLinesAndColumns(command, _ec.Object);
|
IssueCommandExtension.ValidateLinesAndColumns(command, _ec.Object);
|
||||||
Assert.False(command.Properties.ContainsKey("col"));
|
Assert.False(command.Properties.ContainsKey("col"));
|
||||||
|
|
||||||
// No lines with columns
|
// No lines with columns
|
||||||
ActionCommand.TryParseV2("::warning col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
ActionCommand.TryParseV2("::warning col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
||||||
Assert.Equal("1", command.Properties["col"]);
|
Assert.Equal("1", command.Properties["col"]);
|
||||||
@@ -334,6 +418,31 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void AddMaskWithMultilineValue()
|
||||||
|
{
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_commandManager.TryProcessCommand(_ec.Object, $"::add-mask::abc%0Ddef%0Aghi%0D%0Ajkl", null);
|
||||||
|
_commandManager.TryProcessCommand(_ec.Object, $"::add-mask:: %0D %0A %0D%0A %0D", null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("abc"));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("def"));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("ghi"));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("jkl"));
|
||||||
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("abc\rdef\nghi\r\njkl"));
|
||||||
|
Assert.Equal("", hc.SecretMasker.MaskSecrets(""));
|
||||||
|
Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" "));
|
||||||
|
Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" "));
|
||||||
|
Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" "));
|
||||||
|
Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
|
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
|
||||||
{
|
{
|
||||||
var hostContext = new TestHostContext(this, testName);
|
var hostContext = new TestHostContext(this, testName);
|
||||||
@@ -347,6 +456,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
new InternalPluginSetRepoPathCommandExtension(),
|
new InternalPluginSetRepoPathCommandExtension(),
|
||||||
new SetEnvCommandExtension(),
|
new SetEnvCommandExtension(),
|
||||||
new WarningCommandExtension(),
|
new WarningCommandExtension(),
|
||||||
|
new AddMaskCommandExtension(),
|
||||||
};
|
};
|
||||||
foreach (var command in commands)
|
foreach (var command in commands)
|
||||||
{
|
{
|
||||||
@@ -375,5 +485,19 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
return hostContext;
|
return hostContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DictionaryContextData GetExpressionValues()
|
||||||
|
{
|
||||||
|
return new DictionaryContextData
|
||||||
|
{
|
||||||
|
["env"] =
|
||||||
|
#if OS_WINDOWS
|
||||||
|
new DictionaryContextData()
|
||||||
|
#else
|
||||||
|
new CaseSensitiveDictionaryContextData()
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user