mirror of
https://github.com/actions/runner.git
synced 2025-12-10 04:06:57 +00:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b8cfdae4e | ||
|
|
4935be5526 | ||
|
|
920fba93dc | ||
|
|
949269104d | ||
|
|
dca4f67143 | ||
|
|
01ff38f975 | ||
|
|
bc67f99bae | ||
|
|
ae2f4a6f27 | ||
|
|
15cbadb4af | ||
|
|
0678e8df09 | ||
|
|
3a1c89715c | ||
|
|
6cdd27263b | ||
|
|
32845a5448 | ||
|
|
6e6410d300 | ||
|
|
ed191b78ae | ||
|
|
75786756bb | ||
|
|
5e0c2ef816 | ||
|
|
95459dea5f | ||
|
|
59894790de | ||
|
|
cba19c4d7e | ||
|
|
01fd04464d | ||
|
|
1cb1779d6b | ||
|
|
42c86665a7 | ||
|
|
f9c2bf1dd7 | ||
|
|
84e7949457 | ||
|
|
694d73d43c | ||
|
|
352f201c62 | ||
|
|
503e50acb9 | ||
|
|
813af29886 | ||
|
|
72e2107b5e | ||
|
|
3567c042ea | ||
|
|
e646b6fec4 | ||
|
|
8d2be3d4fa | ||
|
|
407a347f83 | ||
|
|
7e74f8c9d5 | ||
|
|
efdda93aeb | ||
|
|
1d1998aabb | ||
|
|
d2c6a4e4bc | ||
|
|
d11bd3d8be | ||
|
|
761785620f | ||
|
|
416771d4b1 | ||
|
|
9499f477a2 | ||
|
|
6bc6d475f9 | ||
|
|
ca2b1bc6d5 | ||
|
|
591f8c3510 | ||
|
|
ac7b34a071 | ||
|
|
0d1e6fd57b | ||
|
|
9623a44c2f | ||
|
|
b2e2aa68c8 | ||
|
|
a9ce6b92c4 | ||
|
|
a1bf8401d7 | ||
|
|
a7152f1370 | ||
|
|
af285115e7 | ||
|
|
0431b6fd40 | ||
|
|
c3d5449146 | ||
|
|
9c5300b5b2 | ||
|
|
183b1f387c | ||
|
|
42ad85741e | ||
|
|
88ee16fb02 | ||
|
|
5cca207314 | ||
|
|
0b73794267 | ||
|
|
d7694774a4 | ||
|
|
0398f57125 | ||
|
|
fade0f46e7 | ||
|
|
02b52e8497 | ||
|
|
628f462ab7 | ||
|
|
7ba4f8587e | ||
|
|
88f7c56757 | ||
|
|
20b7e86e47 | ||
|
|
bd5f275830 | ||
|
|
a7aadf5615 | ||
|
|
1c582abc8b | ||
|
|
44d4d076fe | ||
|
|
b6195624ac | ||
|
|
ead3509d5a | ||
|
|
fee24199cb | ||
|
|
c8cb600ac7 | ||
|
|
f48f314a70 | ||
|
|
7b677e0618 | ||
|
|
d70f9f6174 | ||
|
|
0343e76789 | ||
|
|
909b05eb66 | ||
|
|
2e3976cf97 | ||
|
|
052ac521b0 | ||
|
|
408d6c579c | ||
|
|
46258428cd | ||
|
|
eb9a604b63 | ||
|
|
8792d8e5ee | ||
|
|
87e86e3d72 | ||
|
|
48b6cd9a42 | ||
|
|
d081289ed5 | ||
|
|
7d5e9cd70f | ||
|
|
98aa9c1152 | ||
|
|
ddc700e9eb | ||
|
|
a0458aebfe | ||
|
|
b2c6d093b2 | ||
|
|
292a2e0ab3 | ||
|
|
29cee52276 | ||
|
|
ad0d0c4d0a | ||
|
|
2c6064a655 | ||
|
|
af6c8e6edd | ||
|
|
c15d3f10b2 | ||
|
|
bdf1e90503 | ||
|
|
100c99f263 | ||
|
|
e8ccafea63 | ||
|
|
02d2cb8fcd | ||
|
|
0cbf3351f4 | ||
|
|
6abef8199f | ||
|
|
ec9830836b | ||
|
|
460c32a337 | ||
|
|
934027da60 | ||
|
|
28f0027938 | ||
|
|
17153c9b29 | ||
|
|
a65ac083b4 | ||
|
|
882f36dcf8 | ||
|
|
f2578529b0 | ||
|
|
bd77ccf34e | ||
|
|
cb19da9638 | ||
|
|
d64190927f | ||
|
|
101b74cab6 | ||
|
|
c06da82ccd | ||
|
|
374989b280 | ||
|
|
47fee8cd64 | ||
|
|
85dcd93d98 | ||
|
|
bac91075f4 | ||
|
|
9240a1cf6c | ||
|
|
2946801fb6 | ||
|
|
1a0d588d3a | ||
|
|
192ebfeccf | ||
|
|
f2347b7a59 | ||
|
|
8f160bc084 | ||
|
|
47ba1203c9 | ||
|
|
dc8b1b685f | ||
|
|
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 |
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,12 +1,18 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
name: 🛑 Report a bug in the runner application
|
||||
about: If you have issues with GitHub Actions, please follow the "support for GitHub Actions" link, below.
|
||||
title: ''
|
||||
labels: bug
|
||||
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**
|
||||
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
|
||||
about: Create a request to help us improve
|
||||
name: 🛑 Request a feature in the runner application
|
||||
about: If you have feature requests for GitHub Actions, please use the "feedback and suggestions for GitHub Actions" link below.
|
||||
title: ''
|
||||
labels: enhancement
|
||||
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 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:
|
||||
-->
|
||||
|
||||
**Describe the enhancement**
|
||||
A clear and concise description of what the features or enhancement you need.
|
||||
|
||||
47
.github/workflows/build.yml
vendored
47
.github/workflows/build.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ]
|
||||
include:
|
||||
- runtime: linux-x64
|
||||
os: ubuntu-latest
|
||||
@@ -36,13 +36,21 @@ jobs:
|
||||
os: macOS-latest
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: osx-arm64
|
||||
os: macOS-latest
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: win-x64
|
||||
os: windows-2019
|
||||
devScript: ./dev
|
||||
|
||||
- runtime: win-arm64
|
||||
os: windows-latest
|
||||
devScript: ./dev
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Build runner layout
|
||||
- name: Build & Layout Release
|
||||
@@ -50,12 +58,35 @@ jobs:
|
||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||
working-directory: src
|
||||
|
||||
# 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/**/*')}}
|
||||
|
||||
# Run tests
|
||||
- name: L0
|
||||
run: |
|
||||
${{ matrix.devScript }} test
|
||||
working-directory: src
|
||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' && matrix.runtime != 'win-arm64'
|
||||
|
||||
# Create runner package tar.gz/zip
|
||||
- name: Package Release
|
||||
@@ -67,7 +98,11 @@ jobs:
|
||||
# Upload runner package tar.gz/zip as artifact
|
||||
- name: Publish Artifact
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: runner-package-${{ matrix.runtime }}
|
||||
path: _package
|
||||
path: |
|
||||
_package
|
||||
_package_trims/trim_externals
|
||||
_package_trims/trim_runtime
|
||||
_package_trims/trim_runtime_externals
|
||||
|
||||
7
.github/workflows/codeql.yml
vendored
7
.github/workflows/codeql.yml
vendored
@@ -1,7 +1,12 @@
|
||||
name: "Code Scanning - Action"
|
||||
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
@@ -18,7 +23,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
495
.github/workflows/release.yml
vendored
495
.github/workflows/release.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Make sure ./releaseVersion match ./src/runnerversion
|
||||
# Query GitHub release ensure version is not used
|
||||
@@ -50,10 +50,33 @@ jobs:
|
||||
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
|
||||
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
|
||||
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
|
||||
win-arm64-sha: ${{ steps.sha.outputs.win-arm64-sha256 }}
|
||||
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
|
||||
osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }}
|
||||
linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }}
|
||||
linux-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 }}
|
||||
win-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-arm64-sha256 }}
|
||||
osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }}
|
||||
osx-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-arm64-sha256 }}
|
||||
linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }}
|
||||
linux-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 }}
|
||||
win-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-arm64-sha256 }}
|
||||
osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }}
|
||||
osx-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-arm64-sha256 }}
|
||||
linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }}
|
||||
linux-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 }}
|
||||
win-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-arm64-sha256 }}
|
||||
osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }}
|
||||
osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }}
|
||||
strategy:
|
||||
matrix:
|
||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64, win-arm64 ]
|
||||
include:
|
||||
- runtime: linux-x64
|
||||
os: ubuntu-latest
|
||||
@@ -71,13 +94,21 @@ jobs:
|
||||
os: macOS-latest
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: osx-arm64
|
||||
os: macOS-latest
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: win-x64
|
||||
os: windows-2019
|
||||
devScript: ./dev
|
||||
|
||||
- runtime: win-arm64
|
||||
os: windows-latest
|
||||
devScript: ./dev
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Build runner layout
|
||||
- name: Build & Layout Release
|
||||
@@ -85,13 +116,6 @@ jobs:
|
||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||
working-directory: src
|
||||
|
||||
# Run tests
|
||||
- name: L0
|
||||
run: |
|
||||
${{ matrix.devScript }} test
|
||||
working-directory: src
|
||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||
|
||||
# Create runner package tar.gz/zip
|
||||
- name: Package Release
|
||||
if: github.event_name != 'pull_request'
|
||||
@@ -99,14 +123,6 @@ jobs:
|
||||
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
||||
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
|
||||
- run: brew install coreutils #needed for shasum util
|
||||
if: ${{ matrix.os == 'macOS-latest' }}
|
||||
@@ -120,12 +136,97 @@ jobs:
|
||||
id: sha
|
||||
name: Compute SHA256
|
||||
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' || matrix.runtime == 'win-arm64'
|
||||
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' && matrix.runtime != 'win-arm64'
|
||||
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:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Download runner package tar.gz/zip produced by 'build' job
|
||||
- name: Download Artifact
|
||||
@@ -146,13 +247,49 @@ jobs:
|
||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
||||
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
|
||||
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-arm64-sha}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_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(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-arm64-sha-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_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(/<WIN_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-arm64-sha-noruntime}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-x64-sha-noruntime}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-x64-sha-noruntime}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_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(/<WIN_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-arm64-sha-noruntime-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}')
|
||||
releaseNote = releaseNote.replace(/<LINUX_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)
|
||||
core.setOutput('version', runnerVersion);
|
||||
core.setOutput('note', releaseNote);
|
||||
|
||||
- name: Validate Packages HASH
|
||||
working-directory: _package
|
||||
run: |
|
||||
ls -l
|
||||
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.win-arm64-sha}} actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.linux-arm-sha}} actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||
echo "${{needs.build.outputs.linux-arm64-sha}} actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||
|
||||
# Create GitHub release
|
||||
- uses: actions/create-release@master
|
||||
id: createRelease
|
||||
@@ -165,24 +302,34 @@ jobs:
|
||||
body: |
|
||||
${{ steps.releaseNote.outputs.note }}
|
||||
|
||||
# Upload release assets
|
||||
# Upload release assets (full runner packages)
|
||||
- name: Upload Release Asset (win-x64)
|
||||
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 }}/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_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (win-arm64)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/_package/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
||||
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-x64)
|
||||
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 }}/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_content_type: application/octet-stream
|
||||
|
||||
@@ -192,17 +339,27 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
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_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (osx-arm64)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/_package/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-arm)
|
||||
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 }}/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_content_type: application/octet-stream
|
||||
|
||||
@@ -212,6 +369,294 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
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_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
|
||||
|
||||
# Upload release assets (trim externals)
|
||||
- name: Upload Release Asset (win-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-win-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
|
||||
asset_name: actions-runner-win-arm64-${{ 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 (osx-arm64-noexternals)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-arm-noexternals)
|
||||
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
|
||||
|
||||
# Upload release assets (trim runtime)
|
||||
- name: Upload Release Asset (win-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-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
|
||||
asset_name: actions-runner-win-arm64-${{ 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 (osx-arm64-noruntime)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-arm-noruntime)
|
||||
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
|
||||
|
||||
# Upload release assets (trim runtime and externals)
|
||||
- name: Upload Release Asset (win-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-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
|
||||
asset_name: actions-runner-win-arm64-${{ 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 (osx-arm64-noruntime-noexternals)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime_externals/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.tar.gz
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-arm-noruntime-noexternals)
|
||||
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
|
||||
|
||||
# Upload release assets (trimmedpackages.json)
|
||||
- name: Upload Release Asset (win-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 }}/win-arm64-trimmedpackages.json
|
||||
asset_name: actions-runner-win-arm64-${{ 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 (osx-arm64-trimmedpackages.json)
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||
asset_path: ${{ github.workspace }}/osx-arm64-trimmedpackages.json
|
||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Release Asset (linux-arm-trimmedpackages.json)
|
||||
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
|
||||
_downloads
|
||||
_layout
|
||||
_layout_trims
|
||||
_package
|
||||
_package_trims
|
||||
_dotnetsdk
|
||||
TestResults
|
||||
TestLogs
|
||||
|
||||
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"cwd": "${workspaceFolder}/src",
|
||||
"console": "integratedTerminal",
|
||||
"requireExactSource": false,
|
||||
"requireExactSource": false
|
||||
},
|
||||
{
|
||||
"name": "Run",
|
||||
@@ -24,7 +24,7 @@
|
||||
],
|
||||
"cwd": "${workspaceFolder}/src",
|
||||
"console": "integratedTerminal",
|
||||
"requireExactSource": false,
|
||||
"requireExactSource": false
|
||||
},
|
||||
{
|
||||
"name": "Configure",
|
||||
@@ -37,21 +37,22 @@
|
||||
],
|
||||
"cwd": "${workspaceFolder}/src",
|
||||
"console": "integratedTerminal",
|
||||
"requireExactSource": false,
|
||||
"requireExactSource": false
|
||||
},
|
||||
{
|
||||
"name": "Debug Worker",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processName": "Runner.Worker",
|
||||
"requireExactSource": false,
|
||||
"requireExactSource": false
|
||||
},
|
||||
{
|
||||
"name": "Attach Debugger",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}",
|
||||
"requireExactSource": false,
|
||||
"requireExactSource": false
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# GitHub Actions Runner
|
||||
|
||||
[](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.
|
||||
|
||||
|
||||
@@ -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".
|
||||
|
||||
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.
|
||||
|
||||
@@ -18,21 +18,23 @@ The problem-matcher concept fits well with "setup" actions. For example, the `se
|
||||
|
||||
### 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
|
||||
- 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.
|
||||
|
||||
#### 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.
|
||||
|
||||
`##[remove-matcher]owner`
|
||||
`::remove-matcher::owner`
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
83
docs/adrs/1751-runner-job-hooks.md
Normal file
83
docs/adrs/1751-runner-job-hooks.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# ADR: Notification Hooks for Runners
|
||||
|
||||
## Context
|
||||
|
||||
This ADR details the design changes for supporting custom configurable hooks for on various runner events. This has been a long requested user feature [here](https://github.com/actions/runner/issues/1543), [here](https://github.com/actions/runner/issues/699) and [here](https://github.com/actions/runner/issues/1116) for users to have more information on runner observability, and for the ability to run cleanup and teardown jobs.
|
||||
|
||||
This feature is mainly intended for self hosted runner administrators.
|
||||
|
||||
**What we hope to solve with this feature**
|
||||
1. A runner admininstrator is able to add custom scripts to cleanup their runner environment at the start or end of a job
|
||||
2. A runner admininstrator is able to add custom scripts to help setup their runner environment at the beginning of a job, for reasons like [caching](https://github.com/actions/runner/issues/1543#issuecomment-1050346279)
|
||||
3. A runner administrator is able to grab custom telemetry of jobs running on their self hosted runner
|
||||
|
||||
**What we don't think this will solve**
|
||||
- Policy features that require certain steps run at the beginning or end of all jobs
|
||||
- This would be better solved to in a central place in settings, rather then decentralized on each runner.
|
||||
- The Proposed `Notification Hooks for Runners` is limited to self hosted runners, we don't beileve Policy features should be
|
||||
- Reuse scenarios between jobs are covered by [composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) and [resuable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows)
|
||||
- Security applications, security should be handled on the policy side on the server, not decentralized on each runner
|
||||
|
||||
## Hooks
|
||||
- We will expose 2 variables that users can set to enable hooks
|
||||
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
|
||||
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
|
||||
|
||||
You can set these variables to the **absolute** path of a a `.sh` or `.ps1` file.
|
||||
|
||||
We will execute `pwsh` (fallback to `powershell`) or `bash` (fallback to `sh`) as appropriate.
|
||||
- `.sh` files will execute with the args `-e {pathtofile}`
|
||||
- `.ps1` files will execute with the args `-command \". '{pathtofile}'\"`
|
||||
|
||||
We will **not** set the [standard flags we typically set](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell) for `runs` commands. So, if you want to set `pipefail` on `bash` for example, you will need to do that in your script.
|
||||
|
||||
### UI
|
||||
We want to ensure the experience for users invoking workflows is good, if hooks take too long, you may feel your job is delayed or broken. So, much like `Set Up Job`, we will generate two new steps automatically in your job, one for each configured hook:
|
||||
- `Set up runner`
|
||||
- `Complete runner`
|
||||
|
||||
These steps will contain all of the output from invoking your hook, so you will have visibility into the runtime. We will also provide information on the path to the hook, and what shell we are invoking it as, much like we do for `run: ` steps.
|
||||
|
||||
### Contexts
|
||||
When running your hooks, some context on your job may be helpful.
|
||||
- The scripts will have access to the standard [default environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables)
|
||||
- Some of these variables are step specific like `GITHUB_ACTION`, in which case they will not be set
|
||||
- You can pull the full webhook event payload from `GITHUB_EVENT_PATH`
|
||||
|
||||
### Commands
|
||||
Should we expose [Commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions) and [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files)
|
||||
|
||||
**Yes**. Imagine a scenario where a runner administrator is deprecating a runner pool, and they need to [warn users](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message) to swap to a different pool, we should support them in doing this. However, there are some limitations:
|
||||
- [save-state](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions) will **not** be supported, these are not traditional steps with pre and post actions
|
||||
- [set-output](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions) will **not** be supported, there is no `id` as this is not a traditional step
|
||||
|
||||
|
||||
### Environment Files
|
||||
We will also enable [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files) to support setup scenarios for the runner environment.
|
||||
|
||||
While a self hosted runner admin can [set env variables](https://docs.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners#using-a-env-file-to-set-the-proxy-configuration), these apply to all jobs. By enabling the ability to `add a path` and `set an env` we give runner admins the ability to do this dynamically based on the [workflows environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables) to empower setup scenarios.
|
||||
|
||||
|
||||
### Exit codes
|
||||
These are **synchronous** hooks, so they will block job execution while they are being run. Exit code 0 will indicate a successful run of the hook and we will proceed with the job, any other exit code will fail the job with an appropriate annotation.
|
||||
- There will be no support for `continue-on-error`
|
||||
|
||||
## Key Decisions
|
||||
- We will expose 2 variables that users can set to enable hooks
|
||||
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
|
||||
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
|
||||
- Users can set these variables to the path of a `.sh` or `.ps1` file, which we will execute when Jobs are started or completed.
|
||||
- Output from these will be added to a new step at the start/end of a job named `Set up runner` or `Complete runner`.
|
||||
- These steps will only be generated on runs with these hooks
|
||||
- These hooks `always()` execute if the env variable is set
|
||||
- These files will execute as the Runner user, outside of any container specification on the job
|
||||
- These are **synchronous** hooks
|
||||
- Runner admins can execute a background process for async hooks if they want
|
||||
- We will fail the job and halt execution on any exit code that is not 0. The Runner admin is responsible for returning the correct exit code and ensuring resilency.
|
||||
- This includes that the runner user needs access to the file in the env and the file must exist
|
||||
- There will be no `continue-on-error` type option on launch
|
||||
- There will be no `timeout` option on launch
|
||||
|
||||
## Consequences
|
||||
- Runner admins have the ability to tie into the runner job execution to publish their own telemetry or perform their own cleanup or setup
|
||||
- New steps will be added to the UI showcasing the output of these hooks
|
||||
596
docs/adrs/1891-container-hooks.md
Normal file
596
docs/adrs/1891-container-hooks.md
Normal file
@@ -0,0 +1,596 @@
|
||||
# ADR 0000: Container Hooks
|
||||
|
||||
**Date**: 2022-05-12
|
||||
|
||||
**Status**: Accepted
|
||||
|
||||
# Background
|
||||
|
||||
[Job Hooks](https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md) have given users the ability to customize how their self hosted runners run a job.
|
||||
Users also want the ability to customize how they run containers during the scope of the job, rather then being locked into the docker implementation we have in the runner. They may want to use podman, kubernetes, or even change the docker commands we run.
|
||||
We should give them that option, and publish examples how how they can create their own hooks.
|
||||
|
||||
# Guiding Principles
|
||||
- **Extensibility** is the focus, we need to make sure we are flexible enough to cover current and future scenarios, even at the cost of making it harder to utilize these hooks
|
||||
- Args should map **directly** to yaml values provided by the user.
|
||||
- For example, the current runner overrides `HOME`, we can do that in the hook, but we shouldn't pass that hook as an ENV with the other env's the user has set, as that is not user input, it is how the runner invokes containers
|
||||
|
||||
## Interface
|
||||
- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOKS=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler.
|
||||
- There is no partial opt in, you must handle every hook
|
||||
- We will pass a command and some args via `stdin`
|
||||
- An exit code of 0 is a success, every other exit code is a failure
|
||||
- We will support the same runner commands we support in [Job Hooks](https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md)
|
||||
- On timeout, we will send a sigint to your process. If you fail to terminate within a reasonable amount of time, we will send a sigkill, and eventually kill the process tree.
|
||||
|
||||
An example input looks like
|
||||
```json
|
||||
{
|
||||
"command": "job_cleanup",
|
||||
"responseFile": "/users/thboop/runner/_work/{guid}.json",
|
||||
"args": {},
|
||||
"state":
|
||||
{
|
||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`command` is the command we expect you to invoke
|
||||
`responseFile` is the file you need to write your output to, if the command has output
|
||||
`args` are the specific arguments the command needs
|
||||
`state` is a json blog you can pass around to maintain your state, this is covered in more details below.
|
||||
|
||||
### Writing responses to a file
|
||||
All text written to stdout or stderr should appear in the job or step logs. With that in mind, we support a few ways to actually return data:
|
||||
1. Wrapping the json in some unique tag and processing it like we do commands
|
||||
2. Writing to a file
|
||||
|
||||
For 1, users typically view logging information as a safe action, so we worry someone accidentialy logging unsantized information and causing unexpected or un-secure behavior. We eventually plan to move off of stdout/stderr style commands in favor of a runner cli.
|
||||
Investing in this area doesn't make a lot of sense at this time.
|
||||
|
||||
While writing to a file to communicate isn't the most ideal pattern, its an existing pattern in the runner and serves us well, so lets reuse it.
|
||||
|
||||
### Output
|
||||
Your output must be correctly formatted json. An example output looks like:
|
||||
|
||||
```
|
||||
{
|
||||
"state": {},
|
||||
"context"
|
||||
{
|
||||
"container" :
|
||||
{
|
||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
||||
}
|
||||
"services": {
|
||||
"redis": {
|
||||
"id": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105",
|
||||
"ports": {
|
||||
"8080": "8080"
|
||||
},
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
||||
}
|
||||
}
|
||||
"alpine: true,
|
||||
}
|
||||
```
|
||||
|
||||
`state` is a unique field any command can return. If it is not empty, we will store the state for you and pass it into all future commands. You can overwrite it by having the next hook invoked return a unique state.
|
||||
|
||||
Other fields are dependent upon the command being run.
|
||||
|
||||
### Versioning
|
||||
We will not version these hooks at launch. If needed, we can always major version split these hooks in the future. We will ship in Beta to allow for breaking changes for a few months.
|
||||
|
||||
### The Job Context
|
||||
The [job context](https://docs.github.com/en/actions/learn-github-actions/contexts#example-contents-of-the-job-context) currently has a variety of fields that correspond to containers. We should consider allowing hooks to populate new fields in the job context. That is out of scope for this original release however.
|
||||
|
||||
## Hooks
|
||||
Hooks are to be implemented at a very high level, and map to actions the runner does, rather then specific docker actions like `docker build` or `docker create`. By mapping to runner actions, we create a very extensible framework that is flexible enough to solve any user concerns in the future. By providing first party implementations, we give users easy starting points to customize specific hooks (like `docker build`) without having to write full blown solutions.
|
||||
|
||||
The other would be to provide hooks that mirror every docker call we make, and expose more hooks to help support k8s users, with the expectation that users may have to no-op on multiple hooks if they don't correspond to our use case.
|
||||
|
||||
Why we don't want to go that way
|
||||
- It feels clunky, users need to understand which hooks they need to implement and which they can ignore, which isn't a great UX
|
||||
- It doesn't scale well, I don't want to build a solution where we may need to add more hooks, by mapping to runner actions, updating hooks is a painful experience for users
|
||||
- Its overwhelming, its easier to tell users to build 4 hooks and track data themselves, rather then 16 hooks where the runner needs certain information and then needs to provide that information back into each hook. If we expose `Container Create`, you need to return the container you created, then we do `container run` which uses that container. If we just give you an image and say create and run this container, you don't need to store the container id in the runner, and it maps better to k8s scenarios where we don't really have container ids.
|
||||
|
||||
### Prepare_job hook
|
||||
The `prepare_job` hook is called when a job is started. We pass in any job or service containers the job has. We expect that you:
|
||||
- Prune anything from previous jobs if needed
|
||||
- Create a network if needed
|
||||
- Pull the job and service containers
|
||||
- Start the job container
|
||||
- Start the service containers
|
||||
- Write to the response file some information we need
|
||||
- Required: if the container is alpine, otherwise x64
|
||||
- Optional: any context fields you want to set on the job context, otherwise they will be unavailable for users to use
|
||||
- Return 0 when the health checks have succeeded and the job/service containers are started
|
||||
|
||||
This hook will **always** be called if you have container hooks enabled, even if no service or job containers exist in the job. This allows you to fail the job or implement a default job container if you want to and no job container has been provided.
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Example Input</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
{
|
||||
"command": "prepare_job",
|
||||
"responseFile": "/users/thboop/runner/_work/{guid}.json",
|
||||
"state": {},
|
||||
"args":
|
||||
{
|
||||
"jobContainer": {
|
||||
"image": "node:14.16",
|
||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
||||
"createOptions": "--cpus 1",
|
||||
"environmentVariables": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"userMountVolumes:[
|
||||
{
|
||||
"sourceVolumePath": "my_docker_volume",
|
||||
"targetVolumePath": "/volume_mount",
|
||||
"readOnly": false
|
||||
},
|
||||
],
|
||||
"mountVolumes": [
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
||||
"targetVolumePath": "/__w",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
||||
"targetVolumePath": "/__e",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
||||
"targetVolumePath": "/__w/_temp",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
||||
"targetVolumePath": "/__w/_actions",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
||||
"targetVolumePath": "/__w/_tool",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
||||
"targetVolumePath": "/github/home",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
||||
"targetVolumePath": "/github/workflow",
|
||||
"readOnly": false
|
||||
}
|
||||
],
|
||||
"registry": {
|
||||
"username": "foo",
|
||||
"password": "bar",
|
||||
"serverUrl": "https://index.docker.io/v1"
|
||||
},
|
||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"contextName": "redis",
|
||||
"image": "redis",
|
||||
"createOptions": "--cpus 1",
|
||||
"environmentVariables": {},
|
||||
"mountVolumes": [],
|
||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
||||
"registry": {
|
||||
"username": "foo",
|
||||
"password": "bar",
|
||||
"serverUrl": "https://index.docker.io/v1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Field Descriptions</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
Arg Fields:
|
||||
|
||||
jobContainer: **Optional** An Object containing information about the specified job container
|
||||
"image": **Required** A string containing the docker image
|
||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
||||
"environmentVariables": **Optional** A map of key value env's to set
|
||||
"userMountVolumes: ** Optional** an array of user mount volumes set in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
||||
"readOnly": false **Required** whether or not the mount should be read only
|
||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
||||
"readOnly": false **Required** whether or not the mount should be read only
|
||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
||||
"username": **Optional** the username
|
||||
"password": **Optional** the password
|
||||
"serverUrl": **Optional** the registry url
|
||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
||||
|
||||
"services": an array of service containers to spin up
|
||||
"contextName": **Required** the name of the service in the Job context
|
||||
"image": **Required** A string containing the docker image
|
||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
||||
"environmentVariables": **Optional** A map of key value env's to set
|
||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
||||
"readOnly": false **Required** whether or not the mount should be read only
|
||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
||||
"username": **Optional** the username
|
||||
"password": **Optional** the password
|
||||
"serverUrl": **Optional** the registry url
|
||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Example Output</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
{
|
||||
"state":
|
||||
{
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
||||
"serviceContainers":
|
||||
{
|
||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
||||
}
|
||||
},
|
||||
"context"
|
||||
{
|
||||
"container" :
|
||||
{
|
||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
||||
}
|
||||
"services": {
|
||||
"redis": {
|
||||
"id": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105",
|
||||
"ports": {
|
||||
"8080": "8080"
|
||||
},
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
||||
}
|
||||
}
|
||||
"alpine: true,
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### Cleanup Job
|
||||
The `cleanup_job` hook is called at the end of a job and expects you to:
|
||||
- Stop any running service or job containers (or the equiavalent pod)
|
||||
- Stop the network (if one exists)
|
||||
- Delete any job or service containers (or the equiavalent pod)
|
||||
- Delete the network (if one exists)
|
||||
- Cleanup anything else that was created for the run
|
||||
|
||||
Its input looks like
|
||||
|
||||
<details>
|
||||
<summary>Example Input</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
"command": "cleanup_job",
|
||||
"responseFile": null,
|
||||
"state":
|
||||
{
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
||||
"serviceContainers":
|
||||
{
|
||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
||||
}
|
||||
}
|
||||
"args": {}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
No args are provided.
|
||||
|
||||
No output is expected.
|
||||
|
||||
|
||||
### Run Container Step
|
||||
The `run_container_step` is called once per container action in your job and expects you to:
|
||||
- Pull or build the required container (or fail if you cannot)
|
||||
- Run the container action and return the exit code of the container
|
||||
- Stream any step logs output to stdout and stderr
|
||||
- Cleanup the container after it executes
|
||||
|
||||
<details>
|
||||
<summary>Example Input for Image</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
"command": "run_container_step",
|
||||
"responseFile": null,
|
||||
"state":
|
||||
{
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
||||
"serviceContainers":
|
||||
{
|
||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
||||
}
|
||||
}
|
||||
"args":
|
||||
{
|
||||
"image": "node:14.16",
|
||||
"dockerfile": null,
|
||||
"entryPointArgs": ["-f", "/dev/null"],
|
||||
"entryPoint": "tail",
|
||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
||||
"createOptions": "--cpus 1",
|
||||
"environmentVariables": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"prependPath":["/foo/bar", "bar/foo"]
|
||||
"userMountVolumes:[
|
||||
{
|
||||
"sourceVolumePath": "my_docker_volume",
|
||||
"targetVolumePath": "/volume_mount",
|
||||
"readOnly": false
|
||||
},
|
||||
],
|
||||
"mountVolumes": [
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
||||
"targetVolumePath": "/__w",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
||||
"targetVolumePath": "/__e",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
||||
"targetVolumePath": "/__w/_temp",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
||||
"targetVolumePath": "/__w/_actions",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
||||
"targetVolumePath": "/__w/_tool",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
||||
"targetVolumePath": "/github/home",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
||||
"targetVolumePath": "/github/workflow",
|
||||
"readOnly": false
|
||||
}
|
||||
],
|
||||
"registry": null,
|
||||
"portMappings": { "80": "801" }
|
||||
},
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Example Input for dockerfile</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
"command": "run_container_step",
|
||||
"responseFile": null,
|
||||
"state":
|
||||
{
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
||||
"services":
|
||||
{
|
||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
||||
}
|
||||
}
|
||||
"args":
|
||||
{
|
||||
"image": null,
|
||||
"dockerfile": /__w/_actions/foo/dockerfile,
|
||||
"entryPointArgs": ["hello world"],
|
||||
"entryPoint": "echo",
|
||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
||||
"createOptions": "--cpus 1",
|
||||
"environmentVariables": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"prependPath":["/foo/bar", "bar/foo"]
|
||||
"userMountVolumes:[
|
||||
{
|
||||
"sourceVolumePath": "my_docker_volume",
|
||||
"targetVolumePath": "/volume_mount",
|
||||
"readOnly": false
|
||||
},
|
||||
],
|
||||
"mountVolumes": [
|
||||
{
|
||||
"sourceVolumePath": "my_docker_volume",
|
||||
"targetVolumePath": "/volume_mount",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
||||
"targetVolumePath": "/__w",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
||||
"targetVolumePath": "/__e",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
||||
"targetVolumePath": "/__w/_temp",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
||||
"targetVolumePath": "/__w/_actions",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
||||
"targetVolumePath": "/__w/_tool",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
||||
"targetVolumePath": "/github/home",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
||||
"targetVolumePath": "/github/workflow",
|
||||
"readOnly": false
|
||||
}
|
||||
],
|
||||
"registry": null,
|
||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Field Descriptions</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
Arg Fields:
|
||||
|
||||
|
||||
"image": **Optional** A string containing the docker image. Otherwise a dockerfile must be provided
|
||||
"dockerfile": **Optional** A string containing the path to the dockerfile, otherwise an image must be provided
|
||||
"entryPointArgs": **Optional** A list containing the entry point args
|
||||
"entryPoint": **Optional** The container entry point to use if the default image entrypoint should be overwritten
|
||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
||||
"environmentVariables": **Optional** A map of key value env's to set
|
||||
"prependPath": **Optional** an array of additional paths to prepend to the $PATH variable
|
||||
"userMountVolumes: ** Optional** an array of user mount volumes set in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
||||
"readOnly": false **Required** whether or not the mount should be read only
|
||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
||||
"readOnly": false **Required** whether or not the mount should be read only
|
||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
||||
"username": **Optional** the username
|
||||
"password": **Optional** the password
|
||||
"serverUrl": **Optional** the registry url
|
||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
No output is expected
|
||||
|
||||
Currently we build all container actions at the start of the job. By doing it during the hook, we move this to just in time building for hooks. We could expose a hook to build/pull a container action, and have those called at the start of a job, but doing so would require hook authors to track the build containers in the state, which could be painful.
|
||||
|
||||
### Run Script Step
|
||||
The `run_script_step` expects you to:
|
||||
- Invoke the provided script inside the job container and return the exit code
|
||||
- Stream any step log output to stdout and stderr
|
||||
|
||||
<details>
|
||||
<summary>Example Input</summary>
|
||||
<br>
|
||||
|
||||
|
||||
```
|
||||
"command": "run_script_step",
|
||||
"responseFile": null,
|
||||
"state":
|
||||
{
|
||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
||||
"serviceContainers":
|
||||
{
|
||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
||||
}
|
||||
}
|
||||
"args":
|
||||
{
|
||||
"entryPointArgs": ["-e", "/runner/temp/abc123.sh"],
|
||||
"entryPoint": "bash",
|
||||
"environmentVariables": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"prependPath": ["/foo/bar", "bar/foo"],
|
||||
"workingDirectory": "/__w/thboop-test2/thboop-test2"
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Field Descriptions</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
Arg Fields:
|
||||
|
||||
|
||||
"entryPointArgs": **Optional** A list containing the entry point args
|
||||
"entryPoint": **Optional** The container entry point to use if the default image entrypoint should be overwritten
|
||||
"prependPath": **Optional** an array of additional paths to prepend to the $PATH variable
|
||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
||||
"environmentVariables": **Optional** A map of key value env's to set
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
No output is expected
|
||||
|
||||
|
||||
## Limitations
|
||||
- We will only support linux on launch
|
||||
- Hooks are set by the runner admin, and thus are only supported on self hosted runners
|
||||
|
||||
## Consequences
|
||||
- We support non docker scenarios for self hosted runners and allow customers to customize their docker invocations
|
||||
- We ship/maintain docs on docker hooks and an open source repo with examples
|
||||
- We support these hooks and add enough telemetry to be able to troubleshoot support issues as they come in.
|
||||
@@ -6,13 +6,35 @@
|
||||
Make sure the runner has access to actions service for GitHub.com or GitHub Enterprise Server
|
||||
|
||||
- For GitHub.com
|
||||
- The runner needs to access https://api.github.com for downloading actions.
|
||||
- The runner needs to access https://vstoken.actions.githubusercontent.com/_apis/.../ for requesting an access token.
|
||||
- The runner needs to access https://pipelines.actions.githubusercontent.com/_apis/.../ for receiving workflow jobs.
|
||||
- The runner needs to access `https://api.github.com` for downloading actions.
|
||||
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
||||
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
||||
|
||||
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
||||
|
||||
```
|
||||
curl -v https://api.github.com/api/v3/zen
|
||||
curl -v https://vstoken.actions.githubusercontent.com/_apis/health
|
||||
curl -v https://pipelines.actions.githubusercontent.com/_apis/health
|
||||
```
|
||||
|
||||
- For GitHub Enterprise Server
|
||||
- The runner needs to access https://myGHES.com/api/v3 for downloading actions.
|
||||
- The runner needs to access https://myGHES.com/_services/vstoken/_apis/.../ for requesting an access token.
|
||||
- The runner needs to access https://myGHES.com/_services/pipelines/_apis/.../ for receiving workflow jobs.
|
||||
- The runner needs to access `https://[hostname]/api/v3` for downloading actions.
|
||||
- The runner needs to access `https://[hostname]/_services/vstoken/_apis/.../` for requesting an access token.
|
||||
- The runner needs to access `https://[hostname]/_services/pipelines/_apis/.../` for receiving workflow jobs.
|
||||
|
||||
These can by tested by running the following `curl` commands from your self-hosted runner machine, replacing `[hostname]` with the hostname of your appliance, for instance `github.example.com`:
|
||||
|
||||
```
|
||||
curl -v https://[hostname]/api/v3/zen
|
||||
curl -v https://[hostname]/_services/vstoken/_apis/health
|
||||
curl -v https://[hostname]/_services/pipelines/_apis/health
|
||||
```
|
||||
|
||||
A common cause of this these connectivity issues is if your to GitHub Enterprise Server appliance is using [the self-signed certificate that is enabled the first time](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls) your appliance is started. As self-signed certificates are not trusted by web browsers and Git clients, these clients (including the GitHub Actions runner) will report certificate warnings.
|
||||
|
||||
We recommend [upload a certificate signed by a trusted authority](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls) to GitHub Enterprise Server, or enabling the built-in ][Let's Encrypt support](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls).
|
||||
|
||||
|
||||
## What is checked?
|
||||
|
||||
@@ -42,4 +64,4 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
||||
|
||||
## Still not working?
|
||||
|
||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||
Contact [GitHub Support](https://support.github.com] if you have further questuons, or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||
|
||||
@@ -20,11 +20,30 @@ The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` be
|
||||
|
||||
## How to fix the issue?
|
||||
|
||||
### 1. Check the common network issue
|
||||
### 1. Check global and system git config
|
||||
|
||||
If you are having issues connecting to the server, check your global and system git config for any unexpected authentication headers. You might be seeing an error like:
|
||||
|
||||
```
|
||||
fatal: unable to access 'https://github.com/actions/checkout/': The requested URL returned error: 400
|
||||
```
|
||||
|
||||
The following commands can be used to check for unexpected authentication headers:
|
||||
|
||||
```
|
||||
$ git config --global --list | grep extraheader
|
||||
http.extraheader=AUTHORIZATION: unexpected_auth_header
|
||||
|
||||
$ git config --system --list | grep extraheader
|
||||
```
|
||||
|
||||
The following command can be used to remove the above value: `git config --global --unset http.extraheader`
|
||||
|
||||
### 2. Check the common network issue
|
||||
|
||||
> Please check the [network doc](./network.md)
|
||||
|
||||
### 2. SSL certificate related issue
|
||||
### 3. SSL certificate related issue
|
||||
|
||||
If you are seeing `SSL Certificate problem:` in the log, it means the `git` can't connect to the GitHub server due to SSL handshake failure.
|
||||
> Please check the [SSL cert doc](./sslcert.md)
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
Make sure the built-in node.js has access to GitHub.com or GitHub Enterprise Server.
|
||||
|
||||
The runner carries it's own copy of node.js executable under `<runner_root>/externals/node12/`.
|
||||
The runner carries its own copy of node.js executable under `<runner_root>/externals/node16/`.
|
||||
|
||||
All javascript base Actions will get executed by the built-in `node` at `<runner_root>/externals/node12/`.
|
||||
All javascript base Actions will get executed by the built-in `node` at `<runner_root>/externals/node16/`.
|
||||
|
||||
> Not the `node` from `$PATH`
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ 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)
|
||||
|
||||
 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)
|
||||
|
||||
 Visual Studio 2022 17.3 Preview or later. [Install here](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview)
|
||||
|
||||
## 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:
|
||||
|
||||
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
|
||||
libunwind.so.8 => not found
|
||||
libunwind-x86_64.so.8 => not found
|
||||
Dependencies is missing for Dotnet Core 3.0
|
||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
||||
Dependencies is missing for Dotnet Core 6.0
|
||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.
|
||||
```
|
||||
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
|
||||
@@ -34,7 +34,7 @@ The `installdependencies.sh` script should install all required dependencies on
|
||||
|
||||
Debian based OS (Debian, Ubuntu, Linux Mint)
|
||||
|
||||
- liblttng-ust0
|
||||
- liblttng-ust1 or liblttng-ust0
|
||||
- libkrb5-3
|
||||
- zlib1g
|
||||
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
## Supported Versions
|
||||
|
||||
- macOS High Sierra (10.13) and later versions
|
||||
|
||||
## Apple Silicon M1
|
||||
|
||||
The runner is currently not supported on devices with an Apple M1 chip.
|
||||
We are waiting for official .NET support. You can read more here about the [current state of support here](https://github.com/orgs/dotnet/projects/18#card-56812463).
|
||||
Current .NET project board about M1 support:
|
||||
https://github.com/orgs/dotnet/projects/18#card-56812463
|
||||
- x64 and arm64 (Apple Silicon)
|
||||
|
||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
## Features
|
||||
- Service containers startup error logs are now included in workflow's logs (#2110)
|
||||
|
||||
- Expose GITHUB_REF_* as environment variable (#1314)
|
||||
- Add arch to runner context (#1372)
|
||||
- Support Conditional Steps in Composite Actions (#1438)
|
||||
- Log current runner version in terminal (#1441)
|
||||
|
||||
## Bugs
|
||||
|
||||
- Makes the user keychains available to the service (#847)
|
||||
- Use Actions Service health and api.github.com endpoints after connection failure on Actions Server and Hosted (#1385)
|
||||
- Fix an issue where nested local composite actions did not correctly register post steps (#1433)
|
||||
<!-- ## Bugs -->
|
||||
|
||||
## Misc
|
||||
|
||||
- Cleanup Older versions on MacOS now that we recreate node versions as needed (#1410)
|
||||
- Added a feature flag to start warning on `save-state` and `set-output` deprecation (#2164)
|
||||
- Prepare supporting `vars` in workflow templates (#2096)
|
||||
|
||||
## 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.
|
||||
@@ -29,7 +21,23 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
||||
```
|
||||
|
||||
## OSX
|
||||
## [Pre-release] Windows arm64
|
||||
**Warning:** Windows arm64 runners are currently in preview status and use [unofficial versions of nodejs](https://unofficial-builds.nodejs.org/). They are not intended for production workflows.
|
||||
|
||||
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.
|
||||
|
||||
The following snipped needs to be run on `powershell`:
|
||||
``` powershell
|
||||
# Create a folder under the drive root
|
||||
mkdir \actions-runner ; cd \actions-runner
|
||||
# Download the latest runner package
|
||||
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-arm64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-arm64-<RUNNER_VERSION>.zip
|
||||
# Extract the installer
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-arm64-<RUNNER_VERSION>.zip", "$PWD")
|
||||
```
|
||||
|
||||
## OSX x64
|
||||
|
||||
``` bash
|
||||
# Create a folder
|
||||
@@ -40,6 +48,17 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
||||
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
||||
```
|
||||
|
||||
## OSX arm64 (Apple silicon)
|
||||
|
||||
``` bash
|
||||
# Create a folder
|
||||
mkdir actions-runner && cd actions-runner
|
||||
# Download the latest runner package
|
||||
curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
|
||||
# Extract the installer
|
||||
tar xzf ./actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
|
||||
```
|
||||
|
||||
## Linux x64
|
||||
|
||||
``` bash
|
||||
@@ -81,7 +100,33 @@ For additional details about configuring, running, or shutting down the runner p
|
||||
The SHA-256 checksums for the packages included in this build are shown below:
|
||||
|
||||
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
|
||||
- actions-runner-win-arm64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-arm64 --><WIN_ARM64_SHA><!-- END SHA win-arm64 -->
|
||||
- actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 -->
|
||||
- actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 -->
|
||||
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
|
||||
- actions-runner-linux-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-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals -->
|
||||
- actions-runner-win-arm64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-arm64_noexternals --><WIN_ARM64_SHA_NOEXTERNALS><!-- END SHA win-arm64_noexternals -->
|
||||
- actions-runner-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-x64_noexternals -->
|
||||
- actions-runner-osx-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noexternals --><OSX_ARM64_SHA_NOEXTERNALS><!-- END SHA osx-arm64_noexternals -->
|
||||
- actions-runner-linux-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noexternals --><LINUX_X64_SHA_NOEXTERNALS><!-- END SHA linux-x64_noexternals -->
|
||||
- actions-runner-linux-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-win-arm64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-arm64_noruntime --><WIN_ARM64_SHA_NORUNTIME><!-- END SHA win-arm64_noruntime -->
|
||||
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-x64_noruntime -->
|
||||
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-arm64_noruntime --><OSX_ARM64_SHA_NORUNTIME><!-- END SHA osx-arm64_noruntime -->
|
||||
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-x64_noruntime --><LINUX_X64_SHA_NORUNTIME><!-- END SHA linux-x64_noruntime -->
|
||||
- actions-runner-linux-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-win-arm64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-arm64_noruntime_noexternals --><WIN_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-arm64_noruntime_noexternals -->
|
||||
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noruntime_noexternals --><OSX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-x64_noruntime_noexternals -->
|
||||
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noruntime_noexternals --><OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-arm64_noruntime_noexternals -->
|
||||
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noruntime_noexternals --><LINUX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-x64_noruntime_noexternals -->
|
||||
- actions-runner-linux-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 +1 @@
|
||||
<Update to ./src/runnerversion when creating release>
|
||||
2.298.0
|
||||
|
||||
@@ -13,7 +13,7 @@ set -e
|
||||
|
||||
flags_found=false
|
||||
|
||||
while getopts 's:g:n:u:l:' opt; do
|
||||
while getopts 's:g:n:r:u:l:' opt; do
|
||||
flags_found=true
|
||||
|
||||
case $opt in
|
||||
@@ -26,6 +26,9 @@ while getopts 's:g:n:u:l:' opt; do
|
||||
n)
|
||||
runner_name=$OPTARG
|
||||
;;
|
||||
r)
|
||||
runner_group=$OPTARG
|
||||
;;
|
||||
u)
|
||||
svc_user=$OPTARG
|
||||
;;
|
||||
@@ -44,6 +47,7 @@ Usage:
|
||||
-s required scope: repo (:owner/:repo) or org (:organization)
|
||||
-g optional ghe_hostname: the fully qualified domain name of your GitHub Enterprise Server deployment
|
||||
-n optional name of the runner, defaults to hostname
|
||||
-r optional name of the runner group to add the runner to, defaults to the Default group
|
||||
-u optional user svc will run as, defaults to current
|
||||
-l optional list of labels (split by comma) applied on the runner"
|
||||
exit 0
|
||||
@@ -59,6 +63,7 @@ if ! "$flags_found"; then
|
||||
runner_name=${3:-$(hostname)}
|
||||
svc_user=${4:-$USER}
|
||||
labels=${5}
|
||||
runner_group=${6}
|
||||
fi
|
||||
|
||||
# apply defaults
|
||||
@@ -164,8 +169,8 @@ fi
|
||||
|
||||
echo
|
||||
echo "Configuring ${runner_name} @ $runner_url"
|
||||
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name --labels $labels"
|
||||
sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN --name $runner_name --labels $labels
|
||||
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup \"$runner_group\"}"
|
||||
sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup "$runner_group"}
|
||||
|
||||
#---------------------------------------
|
||||
# Configuring as a service
|
||||
|
||||
@@ -24,10 +24,16 @@
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
||||
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-arm64'">
|
||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
|
||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-arm64'">
|
||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
|
||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
||||
|
||||
1
src/Misc/contentHash/dotnetRuntime/linux-arm
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-arm
Normal file
@@ -0,0 +1 @@
|
||||
1d709d93e5d3c6c6c656a61aa6c1781050224788a05b0e6ecc4c3c0408bdf89c
|
||||
1
src/Misc/contentHash/dotnetRuntime/linux-arm64
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-arm64
Normal file
@@ -0,0 +1 @@
|
||||
b92a47cfeaad02255b1f7a377060651b73ae5e5db22a188dbbcb4183ab03a03d
|
||||
1
src/Misc/contentHash/dotnetRuntime/linux-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/linux-x64
Normal file
@@ -0,0 +1 @@
|
||||
68a9a8ef0843a8bb74241894f6f63fd76241a82295c5337d3cc7a940a314c78e
|
||||
1
src/Misc/contentHash/dotnetRuntime/osx-arm64
Normal file
1
src/Misc/contentHash/dotnetRuntime/osx-arm64
Normal file
@@ -0,0 +1 @@
|
||||
02c7126ff4d63ee2a0ae390c81434c125630522aadf35903bbeebb1a99d8af99
|
||||
1
src/Misc/contentHash/dotnetRuntime/osx-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/osx-x64
Normal file
@@ -0,0 +1 @@
|
||||
c9d5a542f8d765168855a89e83ae0a8970d00869041c4f9a766651c04c72b212
|
||||
1
src/Misc/contentHash/dotnetRuntime/win-arm64
Normal file
1
src/Misc/contentHash/dotnetRuntime/win-arm64
Normal file
@@ -0,0 +1 @@
|
||||
39d0683f0f115a211cb10c473e9574c16549a19d4e9a6c637ded3d7022bf809f
|
||||
1
src/Misc/contentHash/dotnetRuntime/win-x64
Normal file
1
src/Misc/contentHash/dotnetRuntime/win-x64
Normal file
@@ -0,0 +1 @@
|
||||
d94f2fbaf210297162bc9f3add819d73682c3aa6899e321c3872412b924d5504
|
||||
1
src/Misc/contentHash/externals/linux-arm
vendored
Normal file
1
src/Misc/contentHash/externals/linux-arm
vendored
Normal file
@@ -0,0 +1 @@
|
||||
6ed30a2c1ee403a610d63e82bb230b9ba846a9c25cec9e4ea8672fb6ed4e1a51
|
||||
1
src/Misc/contentHash/externals/linux-arm64
vendored
Normal file
1
src/Misc/contentHash/externals/linux-arm64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
711c30c51ec52c9b7a9a2eb399d6ab2ab5ee1dc72de11879f2f36f919f163d78
|
||||
1
src/Misc/contentHash/externals/linux-x64
vendored
Normal file
1
src/Misc/contentHash/externals/linux-x64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
a49479ca4b4988a06c097e8d22c51fd08a11c13f40807366236213d0e008cf6a
|
||||
1
src/Misc/contentHash/externals/osx-arm64
vendored
Normal file
1
src/Misc/contentHash/externals/osx-arm64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cc4708962a80325de0baa5ae8484e0cb9ae976ac6a4178c1c0d448b8c52bd7f7
|
||||
1
src/Misc/contentHash/externals/osx-x64
vendored
Normal file
1
src/Misc/contentHash/externals/osx-x64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
8e97df75230b843462a9b4c578ccec604ee4b4a1066120c85b04374317fa372b
|
||||
1
src/Misc/contentHash/externals/win-arm64
vendored
Normal file
1
src/Misc/contentHash/externals/win-arm64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
e5dace2d41cc0682d096dcce4970079ad48ec7107e46195970eecfdb3df2acef
|
||||
1
src/Misc/contentHash/externals/win-x64
vendored
Normal file
1
src/Misc/contentHash/externals/win-x64
vendored
Normal file
@@ -0,0 +1 @@
|
||||
f75a671e5a188c76680739689aa75331a2c09d483dce9c80023518c48fd67a18
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"extends": ["plugin:github/recommended"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
@@ -17,13 +17,16 @@
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": "default",
|
||||
"format": ["camelCase"]
|
||||
}
|
||||
],
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
@@ -33,7 +36,6 @@
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
@@ -41,19 +43,19 @@
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
"@typescript-eslint/unbound-method": "error",
|
||||
"filenames/match-regex" : "off",
|
||||
"github/no-then" : 1, // warning
|
||||
"semi": "off"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
"es6": true
|
||||
}
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
To update hashFiles under `Misc/layoutbin` run `npm install && npm run all`
|
||||
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run all`.
|
||||
|
||||
> Note: this package also needs to be recompiled for dependabot PRs updating one of
|
||||
> its dependencies.
|
||||
|
||||
5225
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
5225
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -25,10 +25,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@typescript-eslint/parser": "^5.15.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-plugin-github": "^4.3.5",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.6.4"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as glob from '@actions/glob'
|
||||
import * as crypto from 'crypto'
|
||||
import * as fs from 'fs'
|
||||
import * as glob from '@actions/glob'
|
||||
import * as path from 'path'
|
||||
import * as stream from 'stream'
|
||||
import * as util from 'util'
|
||||
import * as path from 'path'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
// arg0 -> node
|
||||
@@ -45,7 +45,7 @@ async function run(): Promise<void> {
|
||||
result.end()
|
||||
|
||||
if (hasMatch) {
|
||||
console.log(`Find ${count} files to hash.`)
|
||||
console.log(`Found ${count} files to hash.`)
|
||||
console.error(`__OUTPUT__${result.digest('hex')}__OUTPUT__`)
|
||||
} else {
|
||||
console.error(`__OUTPUT____OUTPUT__`)
|
||||
@@ -53,3 +53,11 @@ async function run(): Promise<void> {
|
||||
}
|
||||
|
||||
run()
|
||||
.then(out => {
|
||||
console.log(out)
|
||||
process.exit(0)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
@@ -3,7 +3,9 @@ PACKAGERUNTIME=$1
|
||||
PRECACHE=$2
|
||||
|
||||
NODE_URL=https://nodejs.org/dist
|
||||
NODE12_VERSION="12.13.1"
|
||||
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
|
||||
NODE12_VERSION="12.22.7"
|
||||
NODE16_VERSION="16.13.0"
|
||||
|
||||
get_abs_path() {
|
||||
# exploits the fact that pwd will print abs path when no args
|
||||
@@ -126,6 +128,18 @@ function acquireExternalTool() {
|
||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||
if [[ "$PRECACHE" != "" ]]; then
|
||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||
fi
|
||||
fi
|
||||
|
||||
# Download the external tools only for Windows.
|
||||
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
|
||||
# todo: replace these with official release when available
|
||||
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||
if [[ "$PRECACHE" != "" ]]; then
|
||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||
fi
|
||||
@@ -134,18 +148,28 @@ fi
|
||||
# Download the external tools only for OSX.
|
||||
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
||||
fi
|
||||
|
||||
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
||||
# node.js v12 doesn't support macOS on arm64.
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
|
||||
fi
|
||||
|
||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-v${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
||||
fi
|
||||
|
||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
||||
fi
|
||||
|
||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
||||
fi
|
||||
|
||||
@@ -3,94 +3,135 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
var childProcess = require("child_process");
|
||||
var path = require("path")
|
||||
var path = require("path");
|
||||
|
||||
var supported = ['linux', 'darwin']
|
||||
var supported = ["linux", "darwin"];
|
||||
|
||||
if (supported.indexOf(process.platform) == -1) {
|
||||
console.log('Unsupported platform: ' + process.platform);
|
||||
console.log('Supported platforms are: ' + supported.toString());
|
||||
process.exit(1);
|
||||
console.log("Unsupported platform: " + process.platform);
|
||||
console.log("Supported platforms are: " + supported.toString());
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var stopping = false;
|
||||
var listener = null;
|
||||
|
||||
var runService = function () {
|
||||
var listenerExePath = path.join(__dirname, '../bin/Runner.Listener');
|
||||
var interactive = process.argv[2] === "interactive";
|
||||
var exitServiceAfterNFailures = Number(
|
||||
process.env.GITHUB_ACTIONS_SERVICE_EXIT_AFTER_N_FAILURES
|
||||
);
|
||||
|
||||
if (!stopping) {
|
||||
try {
|
||||
if (interactive) {
|
||||
console.log('Starting Runner listener interactively');
|
||||
listener = childProcess.spawn(listenerExePath, ['run'], { env: process.env });
|
||||
} else {
|
||||
console.log('Starting Runner listener with startup type: service');
|
||||
listener = childProcess.spawn(listenerExePath, ['run', '--startuptype', 'service'], { env: process.env });
|
||||
}
|
||||
|
||||
console.log(`Started listener process, pid: ${listener.pid}`);
|
||||
|
||||
listener.stdout.on('data', (data) => {
|
||||
process.stdout.write(data.toString('utf8'));
|
||||
});
|
||||
|
||||
listener.stderr.on('data', (data) => {
|
||||
process.stdout.write(data.toString('utf8'));
|
||||
});
|
||||
|
||||
listener.on("error", (err) => {
|
||||
console.log(`Runner listener fail to start with error ${err.message}`);
|
||||
});
|
||||
|
||||
listener.on('close', (code) => {
|
||||
console.log(`Runner listener exited with error code ${code}`);
|
||||
|
||||
if (code === 0) {
|
||||
console.log('Runner listener exit with 0 return code, stop the service, no retry needed.');
|
||||
stopping = true;
|
||||
} else if (code === 1) {
|
||||
console.log('Runner listener exit with terminated error, stop the service, no retry needed.');
|
||||
stopping = true;
|
||||
} else if (code === 2) {
|
||||
console.log('Runner listener exit with retryable error, re-launch runner in 5 seconds.');
|
||||
} else if (code === 3) {
|
||||
console.log('Runner listener exit because of updating, re-launch runner in 5 seconds.');
|
||||
} else {
|
||||
console.log('Runner listener exit with undefined return code, re-launch runner in 5 seconds.');
|
||||
}
|
||||
|
||||
if (!stopping) {
|
||||
setTimeout(runService, 5000);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
if (exitServiceAfterNFailures <= 0) {
|
||||
exitServiceAfterNFailures = NaN;
|
||||
}
|
||||
|
||||
var consecutiveFailureCount = 0;
|
||||
|
||||
var gracefulShutdown = function () {
|
||||
console.log("Shutting down runner listener");
|
||||
stopping = true;
|
||||
if (listener) {
|
||||
console.log("Sending SIGINT to runner listener to stop");
|
||||
listener.kill("SIGINT");
|
||||
|
||||
console.log("Sending SIGKILL to runner listener");
|
||||
setTimeout(() => listener.kill("SIGKILL"), 30000).unref();
|
||||
}
|
||||
};
|
||||
|
||||
var runService = function () {
|
||||
var listenerExePath = path.join(__dirname, "../bin/Runner.Listener");
|
||||
var interactive = process.argv[2] === "interactive";
|
||||
|
||||
if (!stopping) {
|
||||
try {
|
||||
if (interactive) {
|
||||
console.log("Starting Runner listener interactively");
|
||||
listener = childProcess.spawn(listenerExePath, ["run"], {
|
||||
env: process.env,
|
||||
});
|
||||
} else {
|
||||
console.log("Starting Runner listener with startup type: service");
|
||||
listener = childProcess.spawn(
|
||||
listenerExePath,
|
||||
["run", "--startuptype", "service"],
|
||||
{ env: process.env }
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`Started listener process, pid: ${listener.pid}`);
|
||||
|
||||
listener.stdout.on("data", (data) => {
|
||||
if (data.toString("utf8").includes("Listening for Jobs")) {
|
||||
consecutiveFailureCount = 0;
|
||||
}
|
||||
process.stdout.write(data.toString("utf8"));
|
||||
});
|
||||
|
||||
listener.stderr.on("data", (data) => {
|
||||
process.stdout.write(data.toString("utf8"));
|
||||
});
|
||||
|
||||
listener.on("error", (err) => {
|
||||
console.log(`Runner listener fail to start with error ${err.message}`);
|
||||
});
|
||||
|
||||
listener.on("close", (code) => {
|
||||
console.log(`Runner listener exited with error code ${code}`);
|
||||
|
||||
if (code === 0) {
|
||||
console.log(
|
||||
"Runner listener exit with 0 return code, stop the service, no retry needed."
|
||||
);
|
||||
stopping = true;
|
||||
} else if (code === 1) {
|
||||
console.log(
|
||||
"Runner listener exit with terminated error, stop the service, no retry needed."
|
||||
);
|
||||
stopping = true;
|
||||
} else if (code === 2) {
|
||||
console.log(
|
||||
"Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
||||
);
|
||||
consecutiveFailureCount = 0;
|
||||
} else if (code === 3 || code === 4) {
|
||||
console.log(
|
||||
"Runner listener exit because of updating, re-launch runner in 5 seconds."
|
||||
);
|
||||
consecutiveFailureCount = 0;
|
||||
} else {
|
||||
var messagePrefix = "Runner listener exit with undefined return code";
|
||||
consecutiveFailureCount++;
|
||||
if (
|
||||
!isNaN(exitServiceAfterNFailures) &&
|
||||
consecutiveFailureCount >= exitServiceAfterNFailures
|
||||
) {
|
||||
console.error(
|
||||
`${messagePrefix}, exiting service after ${consecutiveFailureCount} consecutive failures`
|
||||
);
|
||||
gracefulShutdown();
|
||||
return;
|
||||
} else {
|
||||
console.log(`${messagePrefix}, re-launch runner in 5 seconds.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stopping) {
|
||||
setTimeout(runService, 5000);
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
runService();
|
||||
console.log('Started running service');
|
||||
console.log("Started running service");
|
||||
|
||||
var gracefulShutdown = function (code) {
|
||||
console.log('Shutting down runner listener');
|
||||
stopping = true;
|
||||
if (listener) {
|
||||
console.log('Sending SIGINT to runner listener to stop');
|
||||
listener.kill('SIGINT');
|
||||
|
||||
console.log('Sending SIGKILL to runner listener');
|
||||
setTimeout(() => listener.kill('SIGKILL'), 30000);
|
||||
}
|
||||
}
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
gracefulShutdown(0);
|
||||
process.on("SIGINT", () => {
|
||||
gracefulShutdown();
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
gracefulShutdown(0);
|
||||
process.on("SIGTERM", () => {
|
||||
gracefulShutdown();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,13 @@ RUNNER_ROOT=`pwd`
|
||||
|
||||
LAUNCH_PATH="${HOME}/Library/LaunchAgents"
|
||||
PLIST_PATH="${LAUNCH_PATH}/${SVC_NAME}.plist"
|
||||
TEMPLATE_PATH=./bin/actions.runner.plist.template
|
||||
TEMPLATE_PATH=$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE
|
||||
IS_CUSTOM_TEMPLATE=0
|
||||
if [[ -z $TEMPLATE_PATH ]]; then
|
||||
TEMPLATE_PATH=./bin/actions.runner.plist.template
|
||||
else
|
||||
IS_CUSTOM_TEMPLATE=1
|
||||
fi
|
||||
TEMP_PATH=./bin/actions.runner.plist.temp
|
||||
CONFIG_PATH=.service
|
||||
|
||||
@@ -29,7 +35,11 @@ function failed()
|
||||
}
|
||||
|
||||
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
||||
failed "Must run from runner root or install is corrupt"
|
||||
if [[ $IS_CUSTOM_TEMPLATE = 0 ]]; then
|
||||
failed "Must run from runner root or install is corrupt"
|
||||
else
|
||||
failed "Service file at '$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE' using GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE env variable is not found"
|
||||
fi
|
||||
fi
|
||||
|
||||
function install()
|
||||
@@ -53,7 +63,7 @@ function install()
|
||||
mkdir -p "${log_path}" || failed "failed to create ${log_path}"
|
||||
|
||||
echo Creating ${PLIST_PATH}
|
||||
sed "s/{{User}}/${SUDO_USER:-$USER}/g; s/{{SvcName}}/$SVC_NAME/g; s@{{RunnerRoot}}@${RUNNER_ROOT}@g; s@{{UserHome}}@$HOME@g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
||||
sed "s/{{User}}/${USER:-$SUDO_USER}/g; s/{{SvcName}}/$SVC_NAME/g; s@{{RunnerRoot}}@${RUNNER_ROOT}@g; s@{{UserHome}}@$HOME@g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
||||
mv "${TEMP_PATH}" "${PLIST_PATH}" || failed "failed to copy plist"
|
||||
|
||||
# Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
$apt_get update && $apt_get install -y liblttng-ust0 libkrb5-3 zlib1g
|
||||
$apt_get update && $apt_get install -y libkrb5-3 zlib1g
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "'$apt_get' failed with exit code '$?'"
|
||||
@@ -94,6 +94,14 @@ then
|
||||
fi
|
||||
}
|
||||
|
||||
apt_get_with_fallbacks liblttng-ust1 liblttng-ust0
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "'$apt_get' failed with exit code '$?'"
|
||||
print_errormessage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
apt_get_with_fallbacks libssl1.1$ libssl1.0.2$ libssl1.0.0$
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
|
||||
@@ -10,10 +10,11 @@ if [ -f ".path" ]; then
|
||||
echo ".path=${PATH}"
|
||||
fi
|
||||
|
||||
# insert anything to setup env when running as a service
|
||||
nodever=${GITHUB_ACTIONS_RUNNER_FORCED_NODE_VERSION:-node16}
|
||||
|
||||
# insert anything to setup env when running as a service
|
||||
# run the host process which keep the listener alive
|
||||
./externals/node12/bin/node ./bin/RunnerService.js &
|
||||
./externals/$nodever/bin/node ./bin/RunnerService.js &
|
||||
PID=$!
|
||||
wait $PID
|
||||
trap - TERM INT
|
||||
|
||||
@@ -10,7 +10,13 @@ arg_2=${2}
|
||||
RUNNER_ROOT=`pwd`
|
||||
|
||||
UNIT_PATH=/etc/systemd/system/${SVC_NAME}
|
||||
TEMPLATE_PATH=./bin/actions.runner.service.template
|
||||
TEMPLATE_PATH=$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE
|
||||
IS_CUSTOM_TEMPLATE=0
|
||||
if [[ -z $TEMPLATE_PATH ]]; then
|
||||
TEMPLATE_PATH=./bin/actions.runner.service.template
|
||||
else
|
||||
IS_CUSTOM_TEMPLATE=1
|
||||
fi
|
||||
TEMP_PATH=./bin/actions.runner.service.temp
|
||||
CONFIG_PATH=.service
|
||||
|
||||
@@ -31,7 +37,11 @@ function failed()
|
||||
}
|
||||
|
||||
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
||||
failed "Must run from runner root or install is corrupt"
|
||||
if [[ $IS_CUSTOM_TEMPLATE = 0 ]]; then
|
||||
failed "Must run from runner root or install is corrupt"
|
||||
else
|
||||
failed "Service file at '$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE' using GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE env variable is not found"
|
||||
fi
|
||||
fi
|
||||
|
||||
#check if we run as root
|
||||
|
||||
@@ -120,6 +120,9 @@ if ERRORLEVEL 1 (
|
||||
|
||||
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
|
||||
|
||||
type nul > update.finished
|
||||
echo [%date% %time%] update.finished file creation succeed >> "%logfile%" 2>&1
|
||||
|
||||
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||
rem runner service host can base on the log file name determin the result of the runner update
|
||||
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
||||
|
||||
@@ -30,13 +30,13 @@ date "+[%F %T-%4N] Waiting for $runnerprocessname ($runnerpid) to complete" >> "
|
||||
while [ -e /proc/$runnerpid ]
|
||||
do
|
||||
date "+[%F %T-%4N] Process $runnerpid still running" >> "$logfile" 2>&1
|
||||
sleep 2
|
||||
"$rootfolder"/safe_sleep.sh 2
|
||||
done
|
||||
date "+[%F %T-%4N] Process $runnerpid finished running" >> "$logfile" 2>&1
|
||||
|
||||
# start re-organize folders
|
||||
date "+[%F %T-%4N] Sleep 1 more second to make sure process exited" >> "$logfile" 2>&1
|
||||
sleep 1
|
||||
"$rootfolder"/safe_sleep.sh 1
|
||||
|
||||
# the folder structure under runner root will be
|
||||
# ./bin -> bin.2.100.0 (junction folder)
|
||||
@@ -125,7 +125,7 @@ attemptedtargetedfix=0
|
||||
currentplatform=$(uname | awk '{print tolower($0)}')
|
||||
if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
||||
# We needed a fix for https://github.com/actions/runner/issues/743
|
||||
# We will recreate the ./externals/node12/bin/node of the past runner version that launched the runnerlistener service
|
||||
# We will recreate the ./externals/nodeXY/bin/node of the past runner version that launched the runnerlistener service
|
||||
# Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file
|
||||
|
||||
# We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid
|
||||
@@ -135,7 +135,13 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
||||
then
|
||||
# inspect the open file handles to find the node process
|
||||
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks
|
||||
path=$(lsof -a -g "$procgroup" -F n | grep node12/bin/node | grep externals | tail -1 | cut -c2-)
|
||||
nodever="node16"
|
||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
||||
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node12
|
||||
then
|
||||
nodever="node12"
|
||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
||||
fi
|
||||
if [[ $? -eq 0 && -n "$path" ]]
|
||||
then
|
||||
# trim the last 5 characters of the path '/node'
|
||||
@@ -148,7 +154,7 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
||||
then
|
||||
date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1
|
||||
mkdir -p "$trimmedpath"
|
||||
cp "$rootfolder/externals/node12/bin/node" "$path"
|
||||
cp "$rootfolder/externals/$nodever/bin/node" "$path"
|
||||
else
|
||||
date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1
|
||||
fi
|
||||
@@ -174,6 +180,9 @@ fi
|
||||
|
||||
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
||||
|
||||
touch update.finished
|
||||
date "+[%F %T-%4N] update.finished file creation succeed" >> "$logfile"
|
||||
|
||||
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||
# runner service host can base on the log file name determin the result of the runner update
|
||||
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
||||
|
||||
@@ -8,7 +8,7 @@ if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check dotnet core 3.0 dependencies for Linux
|
||||
# Check dotnet Core 6.0 dependencies for Linux
|
||||
if [[ (`uname` == "Linux") ]]
|
||||
then
|
||||
command -v ldd > /dev/null
|
||||
@@ -18,25 +18,25 @@ then
|
||||
exit 1
|
||||
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'
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||
echo $message
|
||||
exit 1
|
||||
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
|
||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||
echo $message
|
||||
exit 1
|
||||
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
|
||||
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
||||
echo $message
|
||||
exit 1
|
||||
fi
|
||||
@@ -54,7 +54,7 @@ then
|
||||
libpath=${LD_LIBRARY_PATH:-}
|
||||
$LDCONFIG_COMMAND -NXv ${libpath//:/ } 2>&1 | grep libicu >/dev/null 2>&1
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
53
src/Misc/layoutroot/run-helper.cmd.template
Normal file
53
src/Misc/layoutroot/run-helper.cmd.template
Normal file
@@ -0,0 +1,53 @@
|
||||
@echo off
|
||||
SET UPDATEFILE=update.finished
|
||||
"%~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 Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||
FOR /L %%G IN (1,1,30) DO (
|
||||
IF EXIST %UPDATEFILE% (
|
||||
echo "Update finished successfully."
|
||||
del %FILE%
|
||||
exit /b 1
|
||||
)
|
||||
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
||||
)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if %ERRORLEVEL% EQU 4 (
|
||||
rem Wait for 30 seconds or for flag file to exists for the runner update process finish
|
||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||
FOR /L %%G IN (1,1,30) DO (
|
||||
IF EXIST %UPDATEFILE% (
|
||||
echo "Update finished successfully."
|
||||
del %FILE%
|
||||
exit /b 1
|
||||
)
|
||||
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
||||
)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo "Exiting after unknown error code: %ERRORLEVEL%"
|
||||
exit /b 0
|
||||
62
src/Misc/layoutroot/run-helper.sh.template
Executable file
62
src/Misc/layoutroot/run-helper.sh.template
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/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
|
||||
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||
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
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||
|
||||
updateFile="update.finished"
|
||||
"$DIR"/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."
|
||||
"$DIR"/safe_sleep.sh 5
|
||||
exit 2
|
||||
elif [[ $returnCode == 3 ]]; then
|
||||
# Wait for 30 seconds or for flag file to exists for the runner update process finish
|
||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||
for i in {0..30}; do
|
||||
if test -f "$updateFile"; then
|
||||
echo "Update finished successfully."
|
||||
rm "$updateFile"
|
||||
break
|
||||
fi
|
||||
"$DIR"/safe_sleep.sh 1
|
||||
done
|
||||
exit 2
|
||||
elif [[ $returnCode == 4 ]]; then
|
||||
# Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
||||
for i in {0..30}; do
|
||||
if test -f "$updateFile"; then
|
||||
echo "Update finished successfully."
|
||||
rm "$updateFile"
|
||||
break
|
||||
fi
|
||||
"$DIR"/safe_sleep.sh 1
|
||||
done
|
||||
exit 2
|
||||
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.
|
||||
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 Sleep 5 seconds to wait for the update process finish and run the runner again.
|
||||
if ERRORLEVEL 4 (
|
||||
timeout /t 5 /nobreak > NUL
|
||||
"%~dp0bin\Runner.Listener.exe" run %*
|
||||
)
|
||||
rem ********************************************************************************
|
||||
rem Run.
|
||||
rem ********************************************************************************
|
||||
|
||||
:launch_helper
|
||||
copy "%~dp0run-helper.cmd.template" "%~dp0run-helper.cmd" /Y
|
||||
call "%~dp0run-helper.cmd" %*
|
||||
|
||||
if %ERRORLEVEL% EQU 1 (
|
||||
echo "Restarting runner..."
|
||||
goto :launch_helper
|
||||
) else (
|
||||
echo "Exiting runner..."
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
@@ -1,64 +1,24 @@
|
||||
#!/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
|
||||
# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||
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
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||
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
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||
|
||||
# Do not "cd $DIR". For localRun, the current directory is expected to be the repo location on disk.
|
||||
|
||||
# Run
|
||||
shopt -s nocasematch
|
||||
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
|
||||
# run the helper process which keep the listener alive
|
||||
while :;
|
||||
do
|
||||
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
||||
"$DIR"/run-helper.sh $*
|
||||
returnCode=$?
|
||||
if [[ $returnCode == 3 ]]; then
|
||||
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
|
||||
elif [[ $returnCode == 4 ]]; then
|
||||
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
|
||||
"$DIR"/bin/Runner.Listener run $*
|
||||
if [[ $returnCode -eq 2 ]]; then
|
||||
echo "Restarting runner..."
|
||||
else
|
||||
exit $returnCode
|
||||
echo "Exiting runner..."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
6
src/Misc/layoutroot/safe_sleep.sh
Normal file
6
src/Misc/layoutroot/safe_sleep.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
SECONDS=0
|
||||
while [[ $SECONDS != $1 ]]; do
|
||||
:
|
||||
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
|
||||
266
src/Misc/runnerdotnetruntimeassets
Normal file
266
src/Misc/runnerdotnetruntimeassets
Normal file
@@ -0,0 +1,266 @@
|
||||
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-fibers-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.DiaSymReader.Native.arm64.dll
|
||||
Microsoft.VisualBasic.Core.dll
|
||||
Microsoft.VisualBasic.dll
|
||||
Microsoft.Win32.Primitives.dll
|
||||
Microsoft.Win32.Registry.dll
|
||||
mscordaccore.dll
|
||||
mscordaccore_amd64_amd64_6.0.522.21309.dll
|
||||
mscordaccore_arm64_arm64_6.0.522.21309.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>"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
public enum ActionResult
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GitHub.DistributedTask.Logging;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -33,6 +32,9 @@ namespace GitHub.Runner.Common
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public string PoolName { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public bool DisableUpdate { get; set; }
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public bool Ephemeral { get; set; }
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace GitHub.Runner.Common
|
||||
public static readonly Architecture PlatformArchitecture = Architecture.X64;
|
||||
#elif ARM
|
||||
public static readonly Architecture PlatformArchitecture = Architecture.Arm;
|
||||
#elif ARM64
|
||||
#elif ARM64
|
||||
public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
|
||||
#endif
|
||||
|
||||
@@ -86,10 +86,11 @@ namespace GitHub.Runner.Common
|
||||
public static class CommandLine
|
||||
{
|
||||
//if you are adding a new arg, please make sure you update the
|
||||
//validArgs array as well present in the CommandSettings.cs
|
||||
//validOptions dictionary as well present in the CommandSettings.cs
|
||||
public static class Args
|
||||
{
|
||||
public static readonly string Auth = "auth";
|
||||
public static readonly string JitConfig = "jitconfig";
|
||||
public static readonly string Labels = "labels";
|
||||
public static readonly string MonitorSocketAddress = "monitorsocketaddress";
|
||||
public static readonly string Name = "name";
|
||||
@@ -121,7 +122,7 @@ namespace GitHub.Runner.Common
|
||||
}
|
||||
|
||||
//if you are adding a new flag, please make sure you update the
|
||||
//validFlags array as well present in the CommandSettings.cs
|
||||
//validOptions dictionary as well present in the CommandSettings.cs
|
||||
public static class Flags
|
||||
{
|
||||
public static readonly string Check = "check";
|
||||
@@ -129,6 +130,7 @@ namespace GitHub.Runner.Common
|
||||
public static readonly string Ephemeral = "ephemeral";
|
||||
public static readonly string Help = "help";
|
||||
public static readonly string Replace = "replace";
|
||||
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 Unattended = "unattended";
|
||||
@@ -148,14 +150,20 @@ namespace GitHub.Runner.Common
|
||||
public static class Features
|
||||
{
|
||||
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
||||
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
|
||||
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
||||
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
|
||||
}
|
||||
|
||||
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
||||
public static readonly string WorkerCrash = "WORKER_CRASH";
|
||||
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
||||
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
||||
public static readonly string UnsupportedCommandMessage = "The `{0}` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-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 readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
||||
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
||||
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Please update the following actions to use Node.js 16: {0}";
|
||||
}
|
||||
|
||||
public static class RunnerEvent
|
||||
@@ -187,6 +195,13 @@ namespace GitHub.Runner.Common
|
||||
public static readonly string Success = "success";
|
||||
}
|
||||
|
||||
public static class Hooks
|
||||
{
|
||||
public static readonly string JobStartedStepName = "Set up runner";
|
||||
public static readonly string JobCompletedStepName = "Complete runner";
|
||||
public static readonly string ContainerHooksPath = "ACTIONS_RUNNER_CONTAINER_HOOKS";
|
||||
}
|
||||
|
||||
public static class Path
|
||||
{
|
||||
public static readonly string ActionsDirectory = "_actions";
|
||||
@@ -216,13 +231,19 @@ namespace GitHub.Runner.Common
|
||||
//
|
||||
public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS";
|
||||
public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS";
|
||||
public static readonly string RequireJobContainer = "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER";
|
||||
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
|
||||
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
||||
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";
|
||||
}
|
||||
|
||||
public static class Agent
|
||||
{
|
||||
public static readonly string ToolsDirectory = "agent.ToolsDirectory";
|
||||
|
||||
// Set this env var to "node12" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions.
|
||||
public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION";
|
||||
public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION";
|
||||
}
|
||||
|
||||
public static class System
|
||||
@@ -235,5 +256,12 @@ namespace GitHub.Runner.Common
|
||||
public static readonly string PhaseDisplayName = "system.phaseDisplayName";
|
||||
}
|
||||
}
|
||||
|
||||
public static class OperatingSystem
|
||||
{
|
||||
public static readonly int Windows11BuildVersion = 22000;
|
||||
// Both windows 10 and windows 11 share the same Major Version 10, need to use the build version to differentiate
|
||||
public static readonly int Windows11MajorVersion = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -60,6 +59,9 @@ namespace GitHub.Runner.Common
|
||||
case "GitHub.Runner.Worker.IFileCommandExtension":
|
||||
Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker");
|
||||
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, Runner.Worker");
|
||||
Add<T>(extensions, "GitHub.Runner.Worker.CreateStepSummaryCommand, Runner.Worker");
|
||||
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateFileCommand, Runner.Worker");
|
||||
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputFileCommand, Runner.Worker");
|
||||
break;
|
||||
case "GitHub.Runner.Listener.Check.ICheckExtension":
|
||||
Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener");
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Runtime.Loader;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.DistributedTask.Logging;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
@@ -98,14 +99,14 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
int logPageSize;
|
||||
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;
|
||||
}
|
||||
|
||||
int logRetentionDays;
|
||||
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;
|
||||
}
|
||||
@@ -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)");
|
||||
}
|
||||
|
||||
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);
|
||||
if (File.Exists(credFile))
|
||||
{
|
||||
@@ -200,9 +206,19 @@ namespace GitHub.Runner.Common
|
||||
if (credData != null &&
|
||||
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)));
|
||||
}
|
||||
|
||||
_userAgents.Add(new ProductInfoHeaderValue("CommitSHA", BuildConstants.Source.CommitHash));
|
||||
}
|
||||
|
||||
public string GetDirectory(WellKnownDirectory directory)
|
||||
@@ -342,7 +358,7 @@ namespace GitHub.Runner.Common
|
||||
GetDirectory(WellKnownDirectory.Root),
|
||||
".setup_info");
|
||||
break;
|
||||
|
||||
|
||||
case WellKnownConfigFile.Telemetry:
|
||||
path = Path.Combine(
|
||||
GetDirectory(WellKnownDirectory.Diag),
|
||||
@@ -626,6 +642,31 @@ namespace GitHub.Runner.Common
|
||||
var handlerFactory = context.GetService<IHttpClientHandlerFactory>();
|
||||
return handlerFactory.CreateClientHandler(context.WebProxy);
|
||||
}
|
||||
|
||||
public static string GetDefaultShellForScript(this IHostContext hostContext, string path, string prependPath)
|
||||
{
|
||||
var trace = hostContext.GetTrace(nameof(GetDefaultShellForScript));
|
||||
switch (Path.GetExtension(path))
|
||||
{
|
||||
case ".sh":
|
||||
// use 'sh' args but prefer bash
|
||||
if (WhichUtil.Which("bash", false, trace, prependPath) != null)
|
||||
{
|
||||
return "bash";
|
||||
}
|
||||
return "sh";
|
||||
case ".ps1":
|
||||
if (WhichUtil.Which("pwsh", false, trace, prependPath) != null)
|
||||
{
|
||||
return "pwsh";
|
||||
}
|
||||
return "powershell";
|
||||
case ".js":
|
||||
return Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetInternalNodeVersion(), "bin", $"node{IOUtil.ExeExtension}") + " {0}";
|
||||
default:
|
||||
throw new ArgumentException($"{path} is not a valid path to a script. Make sure it ends in '.sh', '.ps1' or '.js'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ShutdownReason
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
@@ -13,7 +14,14 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.WebApi;
|
||||
using GitHub.Services.WebApi.Utilities.Internal;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
[ServiceLocator(Default = typeof(JobServer))]
|
||||
public interface IJobServer : IRunnerService
|
||||
public interface IJobServer : IRunnerService, IAsyncDisposable
|
||||
{
|
||||
Task ConnectAsync(VssConnection jobConnection);
|
||||
|
||||
void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint);
|
||||
|
||||
// logging and console
|
||||
Task<TaskLog> AppendLogContentAsync(Guid scopeIdentifier, string hubName, Guid planId, int logId, Stream uploadStream, CancellationToken cancellationToken);
|
||||
Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, CancellationToken cancellationToken);
|
||||
Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long startLine, CancellationToken cancellationToken);
|
||||
Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken);
|
||||
Task<TaskAttachment> CreateAttachmentAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, String type, String name, Stream uploadStream, CancellationToken cancellationToken);
|
||||
Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken);
|
||||
Task<Timeline> CreateTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken);
|
||||
Task<List<TimelineRecord>> UpdateTimelineRecordsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
|
||||
Task RaisePlanEventAsync<T>(Guid scopeIdentifier, string hubName, Guid planId, T eventData, CancellationToken cancellationToken) where T : JobEvent;
|
||||
Task<Timeline> GetTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken);
|
||||
Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, ActionReferenceList actions, CancellationToken cancellationToken);
|
||||
Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid jobId, ActionReferenceList actions, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public sealed class JobServer : RunnerService, IJobServer
|
||||
@@ -34,6 +40,20 @@ namespace GitHub.Runner.Common
|
||||
private bool _hasConnection;
|
||||
private VssConnection _connection;
|
||||
private TaskHttpClient _taskClient;
|
||||
private ClientWebSocket _websocketClient;
|
||||
|
||||
private ServiceEndpoint _serviceEndpoint;
|
||||
|
||||
private int totalBatchedLinesAttemptedByWebsocket = 0;
|
||||
private int failedAttemptsToPostBatchedLinesByWebsocket = 0;
|
||||
|
||||
|
||||
private static readonly TimeSpan _minDelayForWebsocketReconnect = TimeSpan.FromMilliseconds(100);
|
||||
private static readonly TimeSpan _maxDelayForWebsocketReconnect = TimeSpan.FromMilliseconds(500);
|
||||
private static readonly int _minWebsocketFailurePercentageAllowed = 50;
|
||||
private static readonly int _minWebsocketBatchedLinesCountToConsider = 5;
|
||||
|
||||
private Task _websocketConnectTask;
|
||||
|
||||
public async Task ConnectAsync(VssConnection jobConnection)
|
||||
{
|
||||
@@ -42,7 +62,7 @@ namespace GitHub.Runner.Common
|
||||
int attemptCount = totalAttempts;
|
||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||
var runnerSettings = configurationStore.GetSettings();
|
||||
|
||||
|
||||
while (!_connection.HasAuthenticated && attemptCount-- > 0)
|
||||
{
|
||||
try
|
||||
@@ -117,6 +137,21 @@ namespace GitHub.Runner.Common
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint)
|
||||
{
|
||||
this._serviceEndpoint = serviceEndpoint;
|
||||
InitializeWebsocketClient(TimeSpan.Zero);
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
private void CheckConnection()
|
||||
{
|
||||
if (!_hasConnection)
|
||||
@@ -125,6 +160,53 @@ namespace GitHub.Runner.Common
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeWebsocketClient(TimeSpan delay)
|
||||
{
|
||||
if (_serviceEndpoint.Authorization != null &&
|
||||
_serviceEndpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.AccessToken, out var accessToken) &&
|
||||
!string.IsNullOrEmpty(accessToken))
|
||||
{
|
||||
if (_serviceEndpoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl) && !string.IsNullOrEmpty(feedStreamUrl))
|
||||
{
|
||||
// let's ensure we use the right scheme
|
||||
feedStreamUrl = feedStreamUrl.Replace("https://", "wss://").Replace("http://", "ws://");
|
||||
Trace.Info($"Creating websocket client ..." + feedStreamUrl);
|
||||
this._websocketClient = new ClientWebSocket();
|
||||
this._websocketClient.Options.SetRequestHeader("Authorization", $"Bearer {accessToken}");
|
||||
var userAgentValues = new List<ProductInfoHeaderValue>();
|
||||
userAgentValues.AddRange(UserAgentUtility.GetDefaultRestUserAgent());
|
||||
userAgentValues.AddRange(HostContext.UserAgents);
|
||||
this._websocketClient.Options.SetRequestHeader("User-Agent", string.Join(" ", userAgentValues.Select(x => x.ToString())));
|
||||
|
||||
this._websocketConnectTask = ConnectWebSocketClient(feedStreamUrl, delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.Info($"No FeedStreamUrl found, so we will use Rest API calls for sending feed data");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.Info($"No access token from the service endpoint");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ConnectWebSocketClient(string feedStreamUrl, TimeSpan delay)
|
||||
{
|
||||
try
|
||||
{
|
||||
Trace.Info($"Attempting to start websocket client with delay {delay}.");
|
||||
await Task.Delay(delay);
|
||||
await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), default(CancellationToken));
|
||||
Trace.Info($"Successfully started websocket client.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.Info("Exception caught during websocket client connect, fallback of HTTP would be used now instead of websocket.");
|
||||
Trace.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Feedback: WebConsole, TimelineRecords and Logs
|
||||
//-----------------------------------------------------------------
|
||||
@@ -135,16 +217,86 @@ namespace GitHub.Runner.Common
|
||||
return _taskClient.AppendLogContentAsync(scopeIdentifier, hubName, planId, logId, uploadStream, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, CancellationToken cancellationToken)
|
||||
public async Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckConnection();
|
||||
return _taskClient.AppendTimelineRecordFeedAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, stepId, lines, cancellationToken: cancellationToken);
|
||||
var pushedLinesViaWebsocket = false;
|
||||
if (_websocketConnectTask != null)
|
||||
{
|
||||
await _websocketConnectTask;
|
||||
}
|
||||
|
||||
// "_websocketClient != null" implies either: We have a successful connection OR we have to attempt sending again and then reconnect
|
||||
// ...in other words, if websocket client is null, we will skip sending to websocket and just use rest api calls to send data
|
||||
if (_websocketClient != null)
|
||||
{
|
||||
var linesWrapper = startLine.HasValue ? new TimelineRecordFeedLinesWrapper(stepId, lines, startLine.Value) : new TimelineRecordFeedLinesWrapper(stepId, lines);
|
||||
var jsonData = StringUtil.ConvertToJson(linesWrapper);
|
||||
try
|
||||
{
|
||||
totalBatchedLinesAttemptedByWebsocket++;
|
||||
var jsonDataBytes = Encoding.UTF8.GetBytes(jsonData);
|
||||
// break the message into chunks of 1024 bytes
|
||||
for (var i = 0; i < jsonDataBytes.Length; i += 1 * 1024)
|
||||
{
|
||||
var lastChunk = i + (1 * 1024) >= jsonDataBytes.Length;
|
||||
var chunk = new ArraySegment<byte>(jsonDataBytes, i, Math.Min(1 * 1024, jsonDataBytes.Length - i));
|
||||
await _websocketClient.SendAsync(chunk, WebSocketMessageType.Text, endOfMessage: lastChunk, cancellationToken);
|
||||
}
|
||||
|
||||
pushedLinesViaWebsocket = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failedAttemptsToPostBatchedLinesByWebsocket++;
|
||||
Trace.Info($"Caught exception during append web console line to websocket, let's fallback to sending via non-websocket call (total calls: {totalBatchedLinesAttemptedByWebsocket}, failed calls: {failedAttemptsToPostBatchedLinesByWebsocket}, websocket state: {this._websocketClient?.State}).");
|
||||
Trace.Error(ex);
|
||||
if (totalBatchedLinesAttemptedByWebsocket > _minWebsocketBatchedLinesCountToConsider)
|
||||
{
|
||||
// let's consider failure percentage
|
||||
if (failedAttemptsToPostBatchedLinesByWebsocket * 100 / totalBatchedLinesAttemptedByWebsocket > _minWebsocketFailurePercentageAllowed)
|
||||
{
|
||||
Trace.Info($"Exhausted websocket allowed retries, we will not attempt websocket connection for this job to post lines again.");
|
||||
CloseWebSocket(WebSocketCloseStatus.InternalServerError, cancellationToken);
|
||||
|
||||
// By setting it to null, we will ensure that we never try websocket path again for this job
|
||||
_websocketClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (_websocketClient != null)
|
||||
{
|
||||
var delay = BackoffTimerHelper.GetRandomBackoff(_minDelayForWebsocketReconnect, _maxDelayForWebsocketReconnect);
|
||||
Trace.Info($"Websocket is not open, let's attempt to connect back again with random backoff {delay} ms (total calls: {totalBatchedLinesAttemptedByWebsocket}, failed calls: {failedAttemptsToPostBatchedLinesByWebsocket}).");
|
||||
InitializeWebsocketClient(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pushedLinesViaWebsocket && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (startLine.HasValue)
|
||||
{
|
||||
await _taskClient.AppendTimelineRecordFeedAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, stepId, lines, startLine.Value, cancellationToken: cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _taskClient.AppendTimelineRecordFeedAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, stepId, lines, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long startLine, CancellationToken cancellationToken)
|
||||
private void CloseWebSocket(WebSocketCloseStatus closeStatus, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckConnection();
|
||||
return _taskClient.AppendTimelineRecordFeedAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, stepId, lines, startLine, cancellationToken: cancellationToken);
|
||||
try
|
||||
{
|
||||
_websocketClient?.CloseOutputAsync(closeStatus, "Closing websocket", cancellationToken);
|
||||
}
|
||||
catch (Exception websocketEx)
|
||||
{
|
||||
// In some cases this might be okay since the websocket might be open yet, so just close and don't trace exceptions
|
||||
Trace.Info($"Failed to close websocket gracefully {websocketEx.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TaskAttachment> CreateAttachmentAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, string type, string name, Stream uploadStream, CancellationToken cancellationToken)
|
||||
@@ -186,10 +338,10 @@ namespace GitHub.Runner.Common
|
||||
//-----------------------------------------------------------------
|
||||
// Action download info
|
||||
//-----------------------------------------------------------------
|
||||
public Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, ActionReferenceList actions, CancellationToken cancellationToken)
|
||||
public Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid jobId, ActionReferenceList actions, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckConnection();
|
||||
return _taskClient.ResolveActionDownloadInfoAsync(scopeIdentifier, hubName, planId, actions, cancellationToken: cancellationToken);
|
||||
return _taskClient.ResolveActionDownloadInfoAsync(scopeIdentifier, hubName, planId, jobId, actions, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Sdk;
|
||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
@@ -72,10 +71,11 @@ namespace GitHub.Runner.Common
|
||||
|
||||
// Web console dequeue will start with process queue every 250ms for the first 60*4 times (~60 seconds).
|
||||
// Then the dequeue will happen every 500ms.
|
||||
// In this way, customer still can get instance live console output on job start,
|
||||
// In this way, customer still can get instance live console output on job start,
|
||||
// at the same time we can cut the load to server after the build run for more than 60s
|
||||
private int _webConsoleLineAggressiveDequeueCount = 0;
|
||||
private const int _webConsoleLineAggressiveDequeueLimit = 4 * 60;
|
||||
private const int _webConsoleLineQueueSizeLimit = 1024;
|
||||
private bool _webConsoleLineAggressiveDequeue = true;
|
||||
private bool _firstConsoleOutputs = true;
|
||||
|
||||
@@ -89,6 +89,10 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
Trace.Entering();
|
||||
|
||||
var serviceEndPoint = jobRequest.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
_jobServer.InitializeWebsocketClient(serviceEndPoint);
|
||||
|
||||
if (_queueInProcess)
|
||||
{
|
||||
Trace.Info("No-opt, all queue process tasks are running.");
|
||||
@@ -156,13 +160,28 @@ namespace GitHub.Runner.Common
|
||||
await ProcessTimelinesUpdateQueueAsync(runOnce: true);
|
||||
Trace.Info("Timeline update queue drained.");
|
||||
|
||||
Trace.Info($"Disposing job server ...");
|
||||
await _jobServer.DisposeAsync();
|
||||
|
||||
Trace.Info("All queue process tasks have been stopped, and all queues are drained.");
|
||||
}
|
||||
|
||||
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
|
||||
{
|
||||
Trace.Verbose("Enqueue web console line queue: {0}", line);
|
||||
_webConsoleLineQueue.Enqueue(new ConsoleLineInfo(stepRecordId, line, lineNumber));
|
||||
// We only process 500 lines of the queue everytime.
|
||||
// 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)
|
||||
@@ -230,12 +249,6 @@ namespace GitHub.Runner.Common
|
||||
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));
|
||||
linesCounter++;
|
||||
|
||||
@@ -286,14 +299,10 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
try
|
||||
{
|
||||
// we will not requeue failed batch, since the web console lines are time sensitive.
|
||||
if (batch[0].LineNumber.HasValue)
|
||||
// Give at most 60s for each request.
|
||||
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
|
||||
{
|
||||
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber.Value, default(CancellationToken));
|
||||
}
|
||||
else
|
||||
{
|
||||
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), default(CancellationToken));
|
||||
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
|
||||
}
|
||||
|
||||
if (_firstConsoleOutputs)
|
||||
@@ -483,8 +492,8 @@ namespace GitHub.Runner.Common
|
||||
|
||||
if (runOnce)
|
||||
{
|
||||
// continue process timeline records update,
|
||||
// we might have more records need update,
|
||||
// continue process timeline records update,
|
||||
// we might have more records need update,
|
||||
// since we just create a new sub-timeline
|
||||
if (pendingSubtimelineUpdate)
|
||||
{
|
||||
|
||||
14
src/Runner.Common/JobStatusEventArgs.cs
Normal file
14
src/Runner.Common/JobStatusEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
public class JobStatusEventArgs : EventArgs
|
||||
{
|
||||
public JobStatusEventArgs(TaskAgentStatus status)
|
||||
{
|
||||
this.Status = status;
|
||||
}
|
||||
public TaskAgentStatus Status { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
103
src/Runner.Common/RunServer.cs
Normal file
103
src/Runner.Common/RunServer.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.DistributedTask.Pipelines;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.WebApi;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
[ServiceLocator(Default = typeof(RunServer))]
|
||||
public interface IRunServer : IRunnerService
|
||||
{
|
||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
||||
|
||||
Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken token);
|
||||
}
|
||||
|
||||
public sealed class RunServer : RunnerService, IRunServer
|
||||
{
|
||||
private bool _hasConnection;
|
||||
private VssConnection _connection;
|
||||
private TaskAgentHttpClient _taskAgentClient;
|
||||
|
||||
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
||||
{
|
||||
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
||||
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
|
||||
_hasConnection = true;
|
||||
}
|
||||
|
||||
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
|
||||
{
|
||||
Trace.Info($"EstablishVssConnection");
|
||||
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
|
||||
int attemptCount = 5;
|
||||
while (attemptCount-- > 0)
|
||||
{
|
||||
var connection = VssUtil.CreateConnection(serverUrl, credentials, timeout: timeout);
|
||||
try
|
||||
{
|
||||
await connection.ConnectAsync();
|
||||
return connection;
|
||||
}
|
||||
catch (Exception ex) when (attemptCount > 0)
|
||||
{
|
||||
Trace.Info($"Catch exception during connect. {attemptCount} attempt left.");
|
||||
Trace.Error(ex);
|
||||
|
||||
await HostContext.Delay(TimeSpan.FromMilliseconds(100), CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
// should never reach here.
|
||||
throw new InvalidOperationException(nameof(EstablishVssConnection));
|
||||
}
|
||||
|
||||
private void CheckConnection()
|
||||
{
|
||||
if (!_hasConnection)
|
||||
{
|
||||
throw new InvalidOperationException($"SetConnection");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckConnection();
|
||||
var jobMessage = RetryRequest<AgentJobRequestMessage>(async () =>
|
||||
{
|
||||
return await _taskAgentClient.GetJobMessageAsync(id, cancellationToken);
|
||||
}, cancellationToken);
|
||||
return jobMessage;
|
||||
}
|
||||
|
||||
private async Task<T> RetryRequest<T>(Func<Task<T>> func,
|
||||
CancellationToken cancellationToken,
|
||||
int maxRetryAttemptsCount = 5
|
||||
)
|
||||
{
|
||||
var retryCount = 0;
|
||||
while (true)
|
||||
{
|
||||
retryCount++;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
// TODO: Add handling of non-retriable exceptions: https://github.com/github/actions-broker/issues/122
|
||||
catch (Exception ex) when (retryCount < maxRetryAttemptsCount)
|
||||
{
|
||||
Trace.Error("Catch exception during get full job message");
|
||||
Trace.Error(ex);
|
||||
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
|
||||
Trace.Warning($"Back off {backOff.TotalSeconds} seconds before next retry. {maxRetryAttemptsCount - retryCount} attempt left.");
|
||||
await Task.Delay(backOff, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||
<NoWarn>NU1701;NU1603</NoWarn>
|
||||
<Version>$(Version)</Version>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -18,7 +16,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
|
||||
<PackageReference Include="System.Threading.Channels" Version="4.4.0" />
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Services.WebApi;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Runner.Sdk;
|
||||
@@ -39,7 +38,7 @@ namespace GitHub.Runner.Common
|
||||
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
|
||||
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
|
||||
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
|
||||
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken);
|
||||
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken);
|
||||
|
||||
// job request
|
||||
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
||||
@@ -51,7 +50,7 @@ namespace GitHub.Runner.Common
|
||||
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
||||
|
||||
// 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
|
||||
@@ -298,10 +297,10 @@ namespace GitHub.Runner.Common
|
||||
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
|
||||
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
|
||||
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
@@ -341,25 +340,10 @@ namespace GitHub.Runner.Common
|
||||
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);
|
||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// 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);
|
||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common.Internal;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
using GitHub.Runner.Common.Util;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
28
src/Runner.Common/Util/NodeUtil.cs
Normal file
28
src/Runner.Common/Util/NodeUtil.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace GitHub.Runner.Common.Util
|
||||
{
|
||||
public static class NodeUtil
|
||||
{
|
||||
private const string _defaultNodeVersion = "node16";
|
||||
|
||||
#if (OS_OSX || OS_WINDOWS) && ARM64
|
||||
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" });
|
||||
#else
|
||||
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node12", "node16" });
|
||||
#endif
|
||||
|
||||
public static string GetInternalNodeVersion()
|
||||
{
|
||||
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
|
||||
var isForcedInternalNodeVersion = !string.IsNullOrEmpty(forcedInternalNodeVersion) && BuiltInNodeVersions.Contains(forcedInternalNodeVersion);
|
||||
|
||||
if (isForcedInternalNodeVersion)
|
||||
{
|
||||
return forcedInternalNodeVersion;
|
||||
}
|
||||
return _defaultNodeVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
|
||||
namespace GitHub.Runner.Common.Util
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
|
||||
@@ -314,12 +315,12 @@ namespace GitHub.Runner.Listener.Check
|
||||
});
|
||||
|
||||
var downloadCertScript = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Bin), "checkScripts", "downloadCert");
|
||||
var node12 = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node12} \"{downloadCertScript}\"' ");
|
||||
var node = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetInternalNodeVersion(), "bin", $"node{IOUtil.ExeExtension}");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node} \"{downloadCertScript}\"' ");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} {StringUtil.ConvertToJson(env)}");
|
||||
await processInvoker.ExecuteAsync(
|
||||
hostContext.GetDirectory(WellKnownDirectory.Root),
|
||||
node12,
|
||||
node,
|
||||
$"\"{downloadCertScript}\"",
|
||||
env,
|
||||
true,
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Common;
|
||||
@@ -168,4 +167,4 @@ namespace GitHub.Runner.Listener.Check
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
namespace GitHub.Runner.Listener.Check
|
||||
@@ -144,12 +144,12 @@ namespace GitHub.Runner.Listener.Check
|
||||
});
|
||||
|
||||
var makeWebRequestScript = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "checkScripts", "makeWebRequest.js");
|
||||
var node12 = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node12} \"{makeWebRequestScript}\"' ");
|
||||
var node = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetInternalNodeVersion(), "bin", $"node{IOUtil.ExeExtension}");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node} \"{makeWebRequestScript}\"' ");
|
||||
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} {StringUtil.ConvertToJson(env)}");
|
||||
await processInvoker.ExecuteAsync(
|
||||
HostContext.GetDirectory(WellKnownDirectory.Root),
|
||||
node12,
|
||||
node,
|
||||
$"\"{makeWebRequestScript}\"",
|
||||
env,
|
||||
true,
|
||||
@@ -178,4 +178,4 @@ namespace GitHub.Runner.Listener.Check
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GitHub.DistributedTask.Logging;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
@@ -17,42 +16,58 @@ namespace GitHub.Runner.Listener
|
||||
private readonly IPromptManager _promptManager;
|
||||
private readonly Tracing _trace;
|
||||
|
||||
private readonly string[] validCommands =
|
||||
// Valid flags for all commands
|
||||
private readonly string[] genericOptions =
|
||||
{
|
||||
Constants.Runner.CommandLine.Commands.Configure,
|
||||
Constants.Runner.CommandLine.Commands.Remove,
|
||||
Constants.Runner.CommandLine.Commands.Run,
|
||||
Constants.Runner.CommandLine.Commands.Warmup,
|
||||
};
|
||||
|
||||
private readonly string[] validFlags =
|
||||
{
|
||||
Constants.Runner.CommandLine.Flags.Check,
|
||||
Constants.Runner.CommandLine.Flags.Commit,
|
||||
Constants.Runner.CommandLine.Flags.Ephemeral,
|
||||
Constants.Runner.CommandLine.Flags.Help,
|
||||
Constants.Runner.CommandLine.Flags.Once,
|
||||
Constants.Runner.CommandLine.Flags.Replace,
|
||||
Constants.Runner.CommandLine.Flags.RunAsService,
|
||||
Constants.Runner.CommandLine.Flags.Unattended,
|
||||
Constants.Runner.CommandLine.Flags.Version
|
||||
Constants.Runner.CommandLine.Flags.Version,
|
||||
Constants.Runner.CommandLine.Flags.Commit,
|
||||
Constants.Runner.CommandLine.Flags.Check
|
||||
};
|
||||
|
||||
private readonly string[] validArgs =
|
||||
// Valid flags and args for specific command - key: command, value: array of valid flags and args
|
||||
private readonly Dictionary<string, string[]> validOptions = new Dictionary<string, string[]>
|
||||
{
|
||||
Constants.Runner.CommandLine.Args.Auth,
|
||||
Constants.Runner.CommandLine.Args.Labels,
|
||||
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
||||
Constants.Runner.CommandLine.Args.Name,
|
||||
Constants.Runner.CommandLine.Args.PAT,
|
||||
Constants.Runner.CommandLine.Args.RunnerGroup,
|
||||
Constants.Runner.CommandLine.Args.StartupType,
|
||||
Constants.Runner.CommandLine.Args.Token,
|
||||
Constants.Runner.CommandLine.Args.Url,
|
||||
Constants.Runner.CommandLine.Args.UserName,
|
||||
Constants.Runner.CommandLine.Args.WindowsLogonAccount,
|
||||
Constants.Runner.CommandLine.Args.WindowsLogonPassword,
|
||||
Constants.Runner.CommandLine.Args.Work
|
||||
// Valid configure flags and args
|
||||
[Constants.Runner.CommandLine.Commands.Configure] =
|
||||
new string[]
|
||||
{
|
||||
Constants.Runner.CommandLine.Flags.DisableUpdate,
|
||||
Constants.Runner.CommandLine.Flags.Ephemeral,
|
||||
Constants.Runner.CommandLine.Flags.Replace,
|
||||
Constants.Runner.CommandLine.Flags.RunAsService,
|
||||
Constants.Runner.CommandLine.Flags.Unattended,
|
||||
Constants.Runner.CommandLine.Args.Auth,
|
||||
Constants.Runner.CommandLine.Args.Labels,
|
||||
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
||||
Constants.Runner.CommandLine.Args.Name,
|
||||
Constants.Runner.CommandLine.Args.PAT,
|
||||
Constants.Runner.CommandLine.Args.RunnerGroup,
|
||||
Constants.Runner.CommandLine.Args.Token,
|
||||
Constants.Runner.CommandLine.Args.Url,
|
||||
Constants.Runner.CommandLine.Args.UserName,
|
||||
Constants.Runner.CommandLine.Args.WindowsLogonAccount,
|
||||
Constants.Runner.CommandLine.Args.WindowsLogonPassword,
|
||||
Constants.Runner.CommandLine.Args.Work
|
||||
},
|
||||
// Valid remove flags and args
|
||||
[Constants.Runner.CommandLine.Commands.Remove] =
|
||||
new string[]
|
||||
{
|
||||
Constants.Runner.CommandLine.Args.Token,
|
||||
Constants.Runner.CommandLine.Args.PAT
|
||||
},
|
||||
// Valid run flags and args
|
||||
[Constants.Runner.CommandLine.Commands.Run] =
|
||||
new string[]
|
||||
{
|
||||
Constants.Runner.CommandLine.Flags.Once,
|
||||
Constants.Runner.CommandLine.Args.JitConfig,
|
||||
Constants.Runner.CommandLine.Args.StartupType
|
||||
},
|
||||
// valid warmup flags and args
|
||||
[Constants.Runner.CommandLine.Commands.Warmup] =
|
||||
new string[] { }
|
||||
};
|
||||
|
||||
// Commands.
|
||||
@@ -68,6 +83,7 @@ namespace GitHub.Runner.Listener
|
||||
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
|
||||
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
|
||||
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
|
||||
public bool DisableUpdate => TestFlag(Constants.Runner.CommandLine.Flags.DisableUpdate);
|
||||
|
||||
// Keep this around since customers still relies on it
|
||||
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
|
||||
@@ -124,17 +140,48 @@ namespace GitHub.Runner.Listener
|
||||
List<string> unknowns = new List<string>();
|
||||
|
||||
// detect unknown commands
|
||||
unknowns.AddRange(_parser.Commands.Where(x => !validCommands.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
unknowns.AddRange(_parser.Commands.Where(x => !validOptions.Keys.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
|
||||
// detect unknown flags
|
||||
unknowns.AddRange(_parser.Flags.Where(x => !validFlags.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
|
||||
// detect unknown args
|
||||
unknowns.AddRange(_parser.Args.Keys.Where(x => !validArgs.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
if (unknowns.Count == 0)
|
||||
{
|
||||
// detect unknown flags and args for valid commands
|
||||
foreach (var command in _parser.Commands)
|
||||
{
|
||||
if (validOptions.TryGetValue(command, out string[] options))
|
||||
{
|
||||
unknowns.AddRange(_parser.Flags.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase) && !genericOptions.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
unknowns.AddRange(_parser.Args.Keys.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unknowns;
|
||||
}
|
||||
|
||||
public string GetCommandName()
|
||||
{
|
||||
string command = string.Empty;
|
||||
|
||||
if (Configure)
|
||||
{
|
||||
command = Constants.Runner.CommandLine.Commands.Configure;
|
||||
}
|
||||
else if (Remove)
|
||||
{
|
||||
command = Constants.Runner.CommandLine.Commands.Remove;
|
||||
}
|
||||
else if (Run)
|
||||
{
|
||||
command = Constants.Runner.CommandLine.Commands.Run;
|
||||
}
|
||||
else if (Warmup)
|
||||
{
|
||||
command = Constants.Runner.CommandLine.Commands.Warmup;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
//
|
||||
// Interactive flags.
|
||||
//
|
||||
@@ -166,6 +213,12 @@ namespace GitHub.Runner.Listener
|
||||
validator: Validators.AuthSchemeValidator);
|
||||
}
|
||||
|
||||
public string GetJitConfig()
|
||||
{
|
||||
return GetArg(
|
||||
name: Constants.Runner.CommandLine.Args.JitConfig);
|
||||
}
|
||||
|
||||
public string GetRunnerName()
|
||||
{
|
||||
return GetArgOrPrompt(
|
||||
@@ -243,6 +296,7 @@ namespace GitHub.Runner.Listener
|
||||
validator: Validators.ServerUrlValidator);
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
public string GetWindowsLogonAccount(string defaultValue, string descriptionMsg)
|
||||
{
|
||||
return GetArgOrPrompt(
|
||||
@@ -260,7 +314,7 @@ namespace GitHub.Runner.Listener
|
||||
defaultValue: string.Empty,
|
||||
validator: Validators.NonEmptyValidator);
|
||||
}
|
||||
|
||||
#endif
|
||||
public string GetWork()
|
||||
{
|
||||
return GetArgOrPrompt(
|
||||
|
||||
@@ -3,6 +3,7 @@ using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.Common.Internal;
|
||||
using GitHub.Services.OAuth;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -54,7 +55,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
Trace.Info(nameof(LoadSettings));
|
||||
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();
|
||||
@@ -128,7 +129,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
// Example githubServerUrl is https://my-ghes
|
||||
var actionsServerUrl = new Uri(runnerSettings.ServerUrl);
|
||||
var githubServerUrl = new Uri(runnerSettings.GitHubUrl);
|
||||
if (!string.Equals(actionsServerUrl.Authority, githubServerUrl.Authority, StringComparison.OrdinalIgnoreCase))
|
||||
if (!UriUtility.IsSubdomainOf(actionsServerUrl.Authority, githubServerUrl.Authority))
|
||||
{
|
||||
throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}.");
|
||||
}
|
||||
@@ -196,6 +197,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
TaskAgent agent;
|
||||
while (true)
|
||||
{
|
||||
runnerSettings.DisableUpdate = command.DisableUpdate;
|
||||
runnerSettings.Ephemeral = command.Ephemeral;
|
||||
runnerSettings.AgentName = command.GetRunnerName();
|
||||
|
||||
@@ -213,11 +215,22 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
if (command.GetReplace())
|
||||
{
|
||||
// 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
|
||||
{
|
||||
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");
|
||||
break;
|
||||
}
|
||||
@@ -236,11 +249,22 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
else
|
||||
{
|
||||
// Create a new agent.
|
||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral);
|
||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
|
||||
|
||||
try
|
||||
{
|
||||
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");
|
||||
break;
|
||||
}
|
||||
@@ -466,7 +490,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));
|
||||
agent.Authorization = new TaskAgentAuthorization
|
||||
@@ -478,6 +502,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
agent.Version = BuildConstants.RunnerPackage.Version;
|
||||
agent.OSDescription = RuntimeInformation.OSDescription;
|
||||
agent.Ephemeral = ephemeral;
|
||||
agent.DisableUpdate = disableUpdate;
|
||||
agent.MaxParallelism = 1;
|
||||
|
||||
agent.Labels.Clear();
|
||||
@@ -494,7 +519,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
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)
|
||||
{
|
||||
@@ -506,6 +531,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
Version = BuildConstants.RunnerPackage.Version,
|
||||
OSDescription = RuntimeInformation.OSDescription,
|
||||
Ephemeral = ephemeral,
|
||||
DisableUpdate = disableUpdate
|
||||
};
|
||||
|
||||
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
|
||||
@@ -588,32 +614,50 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
throw new ArgumentException($"'{githubUrl}' should point to an org or repository.");
|
||||
}
|
||||
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var httpClient = new HttpClient(httpClientHandler))
|
||||
int retryCount = 0;
|
||||
while(retryCount < 3)
|
||||
{
|
||||
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"github:{githubToken}"));
|
||||
HostContext.SecretMasker.AddValue(base64EncodingToken);
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", base64EncodingToken);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github.v3+json");
|
||||
|
||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var httpClient = new HttpClient(httpClientHandler))
|
||||
{
|
||||
Trace.Info($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
return StringUtil.ConvertFromJson<GitHubRunnerRegisterToken>(jsonResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
_term.WriteError($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
||||
_term.WriteError(errorResponse);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return null;
|
||||
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"github:{githubToken}"));
|
||||
HostContext.SecretMasker.AddValue(base64EncodingToken);
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", base64EncodingToken);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github.v3+json");
|
||||
|
||||
var responseStatus = System.Net.HttpStatusCode.OK;
|
||||
try
|
||||
{
|
||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
||||
responseStatus = response.StatusCode;
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
Trace.Info($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
return StringUtil.ConvertFromJson<GitHubRunnerRegisterToken>(jsonResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
_term.WriteError($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
||||
_term.WriteError(errorResponse);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
catch(Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
retryCount++;
|
||||
Trace.Error($"Failed to get JIT runner token -- Atempt: {retryCount}");
|
||||
Trace.Error(ex);
|
||||
}
|
||||
}
|
||||
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
|
||||
Trace.Info($"Retrying in {backOff.Seconds} seconds");
|
||||
await Task.Delay(backOff);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<GitHubAuthResult> GetTenantCredential(string githubUrl, string githubToken, string runnerEvent)
|
||||
@@ -629,35 +673,53 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/actions/runner-registration";
|
||||
}
|
||||
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var httpClient = new HttpClient(httpClientHandler))
|
||||
int retryCount = 0;
|
||||
while (retryCount < 3)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
|
||||
var bodyObject = new Dictionary<string, string>()
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var httpClient = new HttpClient(httpClientHandler))
|
||||
{
|
||||
{"url", githubUrl},
|
||||
{"runner_event", runnerEvent}
|
||||
};
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
|
||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
|
||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
||||
var bodyObject = new Dictionary<string, string>()
|
||||
{
|
||||
{"url", githubUrl},
|
||||
{"runner_event", runnerEvent}
|
||||
};
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
Trace.Info($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
return StringUtil.ConvertFromJson<GitHubAuthResult>(jsonResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
_term.WriteError($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
||||
_term.WriteError(errorResponse);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return null;
|
||||
var responseStatus = System.Net.HttpStatusCode.OK;
|
||||
try
|
||||
{
|
||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
||||
responseStatus = response.StatusCode;
|
||||
|
||||
if(response.IsSuccessStatusCode)
|
||||
{
|
||||
Trace.Info($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
return StringUtil.ConvertFromJson<GitHubAuthResult>(jsonResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
_term.WriteError($"Http response code: {response.StatusCode} from 'POST {githubApiUrl}'");
|
||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
||||
_term.WriteError(errorResponse);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
catch(Exception ex) when (retryCount < 2 && responseStatus != System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
retryCount++;
|
||||
Trace.Error($"Failed to get tenant credentials -- Atempt: {retryCount}");
|
||||
Trace.Error(ex);
|
||||
}
|
||||
}
|
||||
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
|
||||
Trace.Info($"Retrying in {backOff.Seconds} seconds");
|
||||
await Task.Delay(backOff);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#if OS_WINDOWS
|
||||
#pragma warning disable CA1416
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -141,7 +142,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
Trace.Entering();
|
||||
LocalGroupInfo groupInfo = new LocalGroupInfo();
|
||||
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
|
||||
1, // 1 means include comment
|
||||
@@ -1327,4 +1328,5 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
public IntPtr hProfile;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
|
||||
@@ -72,7 +71,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
else if (isOptional)
|
||||
else if (isOptional)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -87,11 +86,12 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
// Write the message prompt.
|
||||
_terminal.Write($"{description} ");
|
||||
|
||||
if(!string.IsNullOrEmpty(defaultValue))
|
||||
if (!string.IsNullOrEmpty(defaultValue))
|
||||
{
|
||||
_terminal.Write($"[press Enter for {defaultValue}] ");
|
||||
}
|
||||
else if (isOptional){
|
||||
else if (isOptional)
|
||||
{
|
||||
_terminal.Write($"[press Enter to skip] ");
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return the value if it is not empty and it is valid.
|
||||
// Otherwise try the loop again.
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
|
||||
@@ -3,7 +3,6 @@ using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
|
||||
@@ -48,13 +48,12 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
string repoOrOrgName = regex.Replace(settings.RepoOrOrgName, "-");
|
||||
|
||||
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgName, settings.AgentName);
|
||||
|
||||
if (serviceName.Length > 80)
|
||||
if (serviceName.Length > MaxServiceNameLength)
|
||||
{
|
||||
Trace.Verbose($"Calculated service name is too long (> 80 chars). Trying again by calculating a shorter name.");
|
||||
|
||||
int exceededCharLength = serviceName.Length - 80;
|
||||
string repoOrOrgNameSubstring = StringUtil.SubstringPrefix(repoOrOrgName, 45);
|
||||
Trace.Verbose($"Calculated service name is too long (> {MaxServiceNameLength} chars). Trying again by calculating a shorter name.");
|
||||
// Add 5 to add -xxxx random number on the end
|
||||
int exceededCharLength = serviceName.Length - MaxServiceNameLength + 5;
|
||||
string repoOrOrgNameSubstring = StringUtil.SubstringPrefix(repoOrOrgName, MaxRepoOrgCharacters);
|
||||
|
||||
exceededCharLength -= repoOrOrgName.Length - repoOrOrgNameSubstring.Length;
|
||||
|
||||
@@ -66,6 +65,10 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
runnerNameSubstring = StringUtil.SubstringPrefix(settings.AgentName, settings.AgentName.Length - exceededCharLength);
|
||||
}
|
||||
|
||||
// Lets add a suffix with a random number to reduce the chance of collisions between runner names once we truncate
|
||||
var random = new Random();
|
||||
var num = random.Next(1000, 9999).ToString();
|
||||
runnerNameSubstring +=$"-{num}";
|
||||
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring);
|
||||
}
|
||||
|
||||
@@ -73,5 +76,12 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
|
||||
Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration.");
|
||||
}
|
||||
#if (OS_LINUX || OS_OSX)
|
||||
const int MaxServiceNameLength = 150;
|
||||
const int MaxRepoOrgCharacters = 70;
|
||||
#elif OS_WINDOWS
|
||||
const int MaxServiceNameLength = 80;
|
||||
const int MaxRepoOrgCharacters = 45;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if OS_LINUX
|
||||
#if OS_LINUX
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -6,7 +6,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
namespace GitHub.Runner.Listener.Configuration
|
||||
{
|
||||
|
||||
@@ -67,6 +67,8 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
#pragma warning disable CA1416
|
||||
public static bool NTAccountValidator(string arg)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arg) || String.IsNullOrEmpty(arg.TrimStart('.', '\\')))
|
||||
@@ -87,5 +89,7 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#if OS_WINDOWS
|
||||
#pragma warning disable CA1416
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -169,4 +170,5 @@ namespace GitHub.Runner.Listener.Configuration
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
#endif
|
||||
|
||||
@@ -2,17 +2,19 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
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.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.WebApi;
|
||||
using GitHub.Services.WebApi.Jwt;
|
||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||
|
||||
namespace GitHub.Runner.Listener
|
||||
{
|
||||
@@ -25,6 +27,7 @@ namespace GitHub.Runner.Listener
|
||||
bool Cancel(JobCancelMessage message);
|
||||
Task WaitAsync(CancellationToken token);
|
||||
Task ShutdownAsync();
|
||||
event EventHandler<JobStatusEventArgs> JobStatus;
|
||||
}
|
||||
|
||||
// This implementation of IJobDispatcher is not thread safe.
|
||||
@@ -34,6 +37,7 @@ namespace GitHub.Runner.Listener
|
||||
// and the server will not send another job while this one is still running.
|
||||
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 int _poolId;
|
||||
|
||||
@@ -52,6 +56,8 @@ namespace GitHub.Runner.Listener
|
||||
|
||||
private TaskCompletionSource<bool> _runOnceJobCompleted = new TaskCompletionSource<bool>();
|
||||
|
||||
public event EventHandler<JobStatusEventArgs> JobStatus;
|
||||
|
||||
public override void Initialize(IHostContext hostContext)
|
||||
{
|
||||
base.Initialize(hostContext);
|
||||
@@ -282,7 +288,7 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
// at this point, the job execution might encounter some dead lock and even not able to be cancelled.
|
||||
// no need to localize the exception string should never happen.
|
||||
throw new InvalidOperationException($"Job dispatch process for {jobDispatch.JobId} has encountered unexpected error, the dispatch task is not able to be canceled within 45 seconds.");
|
||||
throw new InvalidOperationException($"Job dispatch process for {jobDispatch.JobId} has encountered unexpected error, the dispatch task is not able to be cancelled within 45 seconds.");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -332,6 +338,11 @@ namespace GitHub.Runner.Listener
|
||||
Busy = true;
|
||||
try
|
||||
{
|
||||
if (JobStatus != null)
|
||||
{
|
||||
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Busy));
|
||||
}
|
||||
|
||||
if (previousJobDispatch != null)
|
||||
{
|
||||
Trace.Verbose($"Make sure the previous job request {previousJobDispatch.JobId} has successfully finished on worker.");
|
||||
@@ -360,7 +371,7 @@ namespace GitHub.Runner.Listener
|
||||
Trace.Info($"Start renew job request {requestId} for job {message.JobId}.");
|
||||
Task renewJobRequest = RenewJobRequestAsync(_poolId, requestId, lockToken, orchestrationId, firstJobRequestRenewed, lockRenewalTokenSource.Token);
|
||||
|
||||
// wait till first renew succeed or job request is canceled
|
||||
// wait till first renew succeed or job request is cancelled
|
||||
// not even start worker if the first renew fail
|
||||
await Task.WhenAny(firstJobRequestRenewed.Task, renewJobRequest, Task.Delay(-1, jobRequestCancellationToken));
|
||||
|
||||
@@ -647,6 +658,11 @@ namespace GitHub.Runner.Listener
|
||||
finally
|
||||
{
|
||||
Busy = false;
|
||||
|
||||
if (JobStatus != null)
|
||||
{
|
||||
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Online));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,7 +717,7 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
// OperationCanceledException may caused by http timeout or _lockRenewalTokenSource.Cance();
|
||||
// Stop renew only on cancellation token fired.
|
||||
Trace.Info($"job renew has been canceled, stop renew job request {requestId}.");
|
||||
Trace.Info($"job renew has been cancelled, stop renew job request {requestId}.");
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -759,7 +775,7 @@ namespace GitHub.Runner.Listener
|
||||
}
|
||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||
{
|
||||
Trace.Info($"job renew has been canceled, stop renew job request {requestId}.");
|
||||
Trace.Info($"job renew has been cancelled, stop renew job request {requestId}.");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -964,6 +980,30 @@ namespace GitHub.Runner.Listener
|
||||
TimelineRecord jobRecord = timeline.Records.FirstOrDefault(x => x.Id == message.JobId && x.RecordType == "Job");
|
||||
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 };
|
||||
unhandledExceptionIssue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.WorkerCrash;
|
||||
jobRecord.ErrorCount++;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Listener.Configuration;
|
||||
using GitHub.Services.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using GitHub.Services.OAuth;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Listener.Configuration;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.OAuth;
|
||||
|
||||
namespace GitHub.Runner.Listener
|
||||
{
|
||||
@@ -23,6 +23,7 @@ namespace GitHub.Runner.Listener
|
||||
Task DeleteSessionAsync();
|
||||
Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token);
|
||||
Task DeleteMessageAsync(TaskAgentMessage message);
|
||||
void OnJobStatus(object sender, JobStatusEventArgs e);
|
||||
}
|
||||
|
||||
public sealed class MessageListener : RunnerService, IMessageListener
|
||||
@@ -33,10 +34,13 @@ namespace GitHub.Runner.Listener
|
||||
private IRunnerServer _runnerServer;
|
||||
private TaskAgentSession _session;
|
||||
private TimeSpan _getNextMessageRetryInterval;
|
||||
private bool _accessTokenRevoked = false;
|
||||
private readonly TimeSpan _sessionCreationRetryInterval = TimeSpan.FromSeconds(30);
|
||||
private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4);
|
||||
private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30);
|
||||
private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new Dictionary<string, int>();
|
||||
private TaskAgentStatus runnerStatus = TaskAgentStatus.Online;
|
||||
private CancellationTokenSource _getMessagesTokenSource;
|
||||
|
||||
public override void Initialize(IHostContext hostContext)
|
||||
{
|
||||
@@ -111,6 +115,7 @@ namespace GitHub.Runner.Listener
|
||||
catch (TaskAgentAccessTokenExpiredException)
|
||||
{
|
||||
Trace.Info("Runner OAuth token has been revoked. Session creation failed.");
|
||||
_accessTokenRevoked = true;
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -154,9 +159,33 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
if (_session != null && _session.SessionId != Guid.Empty)
|
||||
{
|
||||
using (var ts = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
|
||||
if (!_accessTokenRevoked)
|
||||
{
|
||||
await _runnerServer.DeleteAgentSessionAsync(_settings.PoolId, _session.SessionId, ts.Token);
|
||||
using (var ts = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
|
||||
{
|
||||
await _runnerServer.DeleteAgentSessionAsync(_settings.PoolId, _session.SessionId, ts.Token);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.Warning("Runner OAuth token has been revoked. Skip deleting session.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnJobStatus(object sender, JobStatusEventArgs e)
|
||||
{
|
||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
|
||||
{
|
||||
Trace.Info("Received job status event. JobState: {0}", e.Status);
|
||||
runnerStatus = e.Status;
|
||||
try
|
||||
{
|
||||
_getMessagesTokenSource?.Cancel();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
Trace.Info("_getMessagesTokenSource is already disposed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,12 +204,14 @@ namespace GitHub.Runner.Listener
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
TaskAgentMessage message = null;
|
||||
_getMessagesTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
|
||||
try
|
||||
{
|
||||
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
|
||||
_session.SessionId,
|
||||
_lastMessageId,
|
||||
token);
|
||||
runnerStatus,
|
||||
_getMessagesTokenSource.Token);
|
||||
|
||||
// Decrypt the message body if the session is using encryption
|
||||
message = DecryptMessage(message);
|
||||
@@ -197,6 +228,11 @@ namespace GitHub.Runner.Listener
|
||||
continuousError = 0;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) when (_getMessagesTokenSource.Token.IsCancellationRequested && !token.IsCancellationRequested)
|
||||
{
|
||||
Trace.Info("Get messages has been cancelled using local token source. Continue to get messages with new status.");
|
||||
continue;
|
||||
}
|
||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||
{
|
||||
Trace.Info("Get next message has been cancelled.");
|
||||
@@ -205,6 +241,7 @@ namespace GitHub.Runner.Listener
|
||||
catch (TaskAgentAccessTokenExpiredException)
|
||||
{
|
||||
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
|
||||
_accessTokenRevoked = true;
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -251,6 +288,10 @@ namespace GitHub.Runner.Listener
|
||||
await HostContext.Delay(_getNextMessageRetryInterval, token);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_getMessagesTokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (message == null)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using GitHub.Runner.Common;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GitHub.Runner.Listener
|
||||
@@ -60,6 +58,18 @@ namespace GitHub.Runner.Listener
|
||||
terminal.WriteLine("This runner version is built for Windows. Please install a correct build for your OS.");
|
||||
return Constants.Runner.ReturnCode.TerminatedError;
|
||||
}
|
||||
#if ARM64
|
||||
// A little hacky, but windows gives no way to differentiate between windows 10 and 11.
|
||||
// By default only 11 supports native x64 app emulation on arm, so we only want to support windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/arm/overview#build-windows-apps-that-run-on-arm
|
||||
// Windows 10 and 11 share a MajorVersion, so we also check the build version. Minor for both is 0, so doing < 0 doesn't really make a lot of sense.
|
||||
if (Environment.OSVersion.Version.Major < Constants.OperatingSystem.Windows11MajorVersion ||
|
||||
Environment.OSVersion.Version.Build < Constants.OperatingSystem.Windows11BuildVersion)
|
||||
{
|
||||
terminal.WriteLine("Win-arm64 runners require windows 11 or later. Please upgrade your operating system.");
|
||||
return Constants.Runner.ReturnCode.TerminatedError;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
terminal.WriteLine($"Running the runner on this platform is not supported. The current platform is {RuntimeInformation.OSDescription} and it was built for {Constants.Runner.Platform.ToString()}.");
|
||||
@@ -95,7 +105,15 @@ namespace GitHub.Runner.Listener
|
||||
var unknownCommandlines = command.Validate();
|
||||
if (unknownCommandlines.Count > 0)
|
||||
{
|
||||
terminal.WriteError($"Unrecognized command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
||||
string commandName = command.GetCommandName();
|
||||
if (string.IsNullOrEmpty(commandName))
|
||||
{
|
||||
terminal.WriteError($"This command does not recognize the command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
||||
}
|
||||
else
|
||||
{
|
||||
terminal.WriteError($"Unrecognized command-line input arguments for command {commandName}: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the Runner class to execute the command.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user