mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Compare commits
3 Commits
thboop/add
...
v2.293.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a78e6e0594 | ||
|
|
150191724e | ||
|
|
7785d8e104 |
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Actions Runner Devcontainer",
|
|
||||||
"image": "mcr.microsoft.com/devcontainers/base:focal",
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/devcontainers/features/docker-in-docker:1": {},
|
|
||||||
"ghcr.io/devcontainers/features/dotnet": {
|
|
||||||
"version": "6.0.421"
|
|
||||||
},
|
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
|
||||||
"version": "16"
|
|
||||||
},
|
|
||||||
"ghcr.io/devcontainers/features/sshd:1": {
|
|
||||||
"version": "latest"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": [
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"ms-dotnettools.csharp",
|
|
||||||
"eamodio.gitlens"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost",
|
|
||||||
"remoteUser": "vscode"
|
|
||||||
}
|
|
||||||
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# https://editorconfig.org/
|
||||||
|
|
||||||
|
[*]
|
||||||
|
insert_final_newline = true # ensure all files end with a single newline
|
||||||
|
trim_trailing_whitespace = true # attempt to remove trailing whitespace on save
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false # in markdown, "two trailing spaces" is unfortunately meaningful; it means `<br>`
|
||||||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 🛑 Request a feature in the runner application
|
|
||||||
url: https://github.com/orgs/community/discussions/categories/actions-and-packages
|
|
||||||
about: If you have feature requests for GitHub Actions, please use the Actions and Packages section on the Github Product Feedback page.
|
|
||||||
- name: ✅ Support for GitHub Actions
|
- name: ✅ Support for GitHub Actions
|
||||||
url: https://github.community/c/code-to-cloud/52
|
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.
|
about: If you have questions about GitHub Actions or need support writing workflows, please ask in the GitHub Community Support forum.
|
||||||
|
|||||||
32
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
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: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
👋 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 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.
|
||||||
|
|
||||||
|
**Code Snippet**
|
||||||
|
If applicable, add a code snippet.
|
||||||
|
|
||||||
|
**Additional information**
|
||||||
|
Add any other context about the feature here.
|
||||||
|
|
||||||
|
NOTE: if the feature request has been agreed upon then the assignee will create an ADR. See docs/adrs/README.md
|
||||||
20
.github/dependabot.yml
vendored
20
.github/dependabot.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "docker"
|
|
||||||
directory: "/images"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
- package-ecosystem: "nuget"
|
|
||||||
directory: "/src"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
- package-ecosystem: "npm"
|
|
||||||
directory: "/src/Misc/expressionFunc/hashFiles"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
allow:
|
|
||||||
- dependency-type: direct
|
|
||||||
- dependency-type: production # check only dependencies, which are going to the compiled app, not supporting tools like @vue-cli
|
|
||||||
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -10,7 +10,7 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- '*'
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ]
|
||||||
include:
|
include:
|
||||||
- runtime: linux-x64
|
- runtime: linux-x64
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
@@ -44,10 +44,6 @@ jobs:
|
|||||||
os: windows-2019
|
os: windows-2019
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
- runtime: win-arm64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -58,12 +54,35 @@ jobs:
|
|||||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||||
working-directory: src
|
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
|
# Run tests
|
||||||
- name: L0
|
- name: L0
|
||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} test
|
${{ matrix.devScript }} test
|
||||||
working-directory: src
|
working-directory: src
|
||||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' && matrix.runtime != 'win-arm64'
|
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64'
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
# Create runner package tar.gz/zip
|
||||||
- name: Package Release
|
- name: Package Release
|
||||||
@@ -78,5 +97,8 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: runner-package-${{ matrix.runtime }}
|
name: runner-package-${{ matrix.runtime }}
|
||||||
path: |
|
path: |
|
||||||
_package
|
_package
|
||||||
|
_package_trims/trim_externals
|
||||||
|
_package_trims/trim_runtime
|
||||||
|
_package_trims/trim_runtime_externals
|
||||||
|
|||||||
17
.github/workflows/close-bugs-bot.yml
vendored
17
.github/workflows/close-bugs-bot.yml
vendored
@@ -1,17 +0,0 @@
|
|||||||
name: Close Bugs Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # every day at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v8
|
|
||||||
with:
|
|
||||||
close-issue-message: "This issue does not seem to be a problem with the runner application, it concerns the GitHub actions platform more generally. Could you please post your feedback on the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions) which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃"
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
stale-issue-label: "actions-bug"
|
|
||||||
only-labels: "actions-bug"
|
|
||||||
days-before-stale: 0
|
|
||||||
days-before-close: 1
|
|
||||||
17
.github/workflows/close-features-bot.yml
vendored
17
.github/workflows/close-features-bot.yml
vendored
@@ -1,17 +0,0 @@
|
|||||||
name: Close Features Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # every day at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v8
|
|
||||||
with:
|
|
||||||
close-issue-message: "Thank you for your interest in the runner application and taking the time to provide your valuable feedback. We kindly ask you to redirect this feedback to the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions-and-packages) which our team actively monitors and would be a better place to start a discussion for new feature requests in GitHub Actions. For more information on this policy please [read our contribution guidelines](https://github.com/actions/runner#contribute). 😃"
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
stale-issue-label: "actions-feature"
|
|
||||||
only-labels: "actions-feature"
|
|
||||||
days-before-stale: 0
|
|
||||||
days-before-close: 1
|
|
||||||
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v1
|
||||||
# Override language selection by uncommenting this and choosing your languages
|
# Override language selection by uncommenting this and choosing your languages
|
||||||
# with:
|
# with:
|
||||||
# languages: go, javascript, csharp, python, cpp, java
|
# languages: go, javascript, csharp, python, cpp, java
|
||||||
@@ -38,4 +38,4 @@ jobs:
|
|||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v1
|
||||||
|
|||||||
105
.github/workflows/dotnet-upgrade.yml
vendored
105
.github/workflows/dotnet-upgrade.yml
vendored
@@ -1,105 +0,0 @@
|
|||||||
name: "DotNet SDK Upgrade"
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 1'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dotnet-update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
SHOULD_UPDATE: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE }}
|
|
||||||
BRANCH_EXISTS: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS }}
|
|
||||||
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Get current major minor version
|
|
||||||
id: fetch_current_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
current_major_minor_patch_version=$(jq .sdk.version ./src/global.json | xargs)
|
|
||||||
current_major_minor_version=$(cut -d '.' -f 1,2 <<< "$current_major_minor_patch_version")
|
|
||||||
|
|
||||||
echo "DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION=${current_major_minor_patch_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "DOTNET_CURRENT_MAJOR_MINOR_VERSION=${current_major_minor_version}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Check patch version
|
|
||||||
id: fetch_latest_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
latest_patch_version=$(curl -sb -H "Accept: application/json" "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version")
|
|
||||||
current_patch_version=${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
|
|
||||||
should_update=0
|
|
||||||
[ "$current_patch_version" != "$latest_patch_version" ] && should_update=1
|
|
||||||
|
|
||||||
# check if git branch already exists for the upgrade
|
|
||||||
branch_already_exists=0
|
|
||||||
|
|
||||||
if git ls-remote --heads --exit-code origin refs/heads/feature/dotnetsdk-upgrade/${latest_patch_version};
|
|
||||||
then
|
|
||||||
branch_already_exists=1
|
|
||||||
should_update=0
|
|
||||||
fi
|
|
||||||
echo "DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION=${latest_patch_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "SHOULD_UPDATE=${should_update}" >> $GITHUB_OUTPUT
|
|
||||||
echo "BRANCH_EXISTS=${branch_already_exists}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Create an error annotation if branch exists
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS == 1 }}
|
|
||||||
run: echo "::error links::feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} https://github.com/actions/runner/tree/feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}::Branch feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} already exists. Please take a look and delete that branch if you wish to recreate"
|
|
||||||
- name: Create a warning annotation if no need to update
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 0 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
run: echo "::warning ::Latest DotNet SDK patch is ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}, and we are on ${{ steps.fetch_latest_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}. No need to update"
|
|
||||||
- name: Update patch version
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
patch_version="${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
current_version="${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
|
|
||||||
# Update globals
|
|
||||||
echo Updating globals
|
|
||||||
globals_temp=$(mktemp)
|
|
||||||
jq --unbuffered --arg patch_version "$patch_version" '.sdk.version = $patch_version' ./src/global.json > "$globals_temp" && mv "$globals_temp" ./src/global.json
|
|
||||||
|
|
||||||
# Update devcontainer
|
|
||||||
echo Updating devcontainer
|
|
||||||
devcontainer_temp=$(mktemp)
|
|
||||||
jq --unbuffered --arg patch_version "$patch_version" '.features."ghcr.io/devcontainers/features/dotnet".version = $patch_version' ./.devcontainer/devcontainer.json > "$devcontainer_temp" && mv "$devcontainer_temp" ./.devcontainer/devcontainer.json
|
|
||||||
|
|
||||||
# Update dev.sh
|
|
||||||
echo Updating start script
|
|
||||||
sed -i "s/DOTNETSDK_VERSION=\"$current_version\"/DOTNETSDK_VERSION=\"$patch_version\"/g" ./src/dev.sh
|
|
||||||
- name: GIT commit and push all changed files
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
id: create_branch
|
|
||||||
run: |
|
|
||||||
branch_name="feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
|
||||||
|
|
||||||
git checkout -b $branch_name
|
|
||||||
git commit -a -m "Upgrade dotnet sdk to v${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
git push --set-upstream origin $branch_name
|
|
||||||
|
|
||||||
create-pr:
|
|
||||||
needs: [dotnet-update]
|
|
||||||
if: ${{ needs.dotnet-update.outputs.SHOULD_UPDATE == 1 && needs.dotnet-update.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
- name: Create Pull Request
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
gh pr create -B main -H feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} --title "Update dotnet sdk to latest version @${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}" --body "
|
|
||||||
https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ needs.dotnet-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [DotNet SDK Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/dotnet-upgrade.yml)"
|
|
||||||
24
.github/workflows/lint.yml
vendored
24
.github/workflows/lint.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
name: Lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [ main ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
# Ensure full list of changed files within `super-linter`
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Run linters
|
|
||||||
uses: github/super-linter@v4
|
|
||||||
env:
|
|
||||||
DEFAULT_BRANCH: ${{ github.base_ref }}
|
|
||||||
EDITORCONFIG_FILE_NAME: .editorconfig
|
|
||||||
LINTER_RULES_PATH: /src/
|
|
||||||
VALIDATE_ALL_CODEBASE: false
|
|
||||||
VALIDATE_CSHARP: true
|
|
||||||
70
.github/workflows/publish-image.yml
vendored
70
.github/workflows/publish-image.yml
vendored
@@ -1,70 +0,0 @@
|
|||||||
name: Publish Runner Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
runnerVersion:
|
|
||||||
type: string
|
|
||||||
description: Version of the runner being installed
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository_owner }}/actions-runner
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Compute image version
|
|
||||||
id: image
|
|
||||||
uses: actions/github-script@v6
|
|
||||||
env:
|
|
||||||
RUNNER_VERSION: ${{ github.event.inputs.runnerVersion }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const inputRunnerVersion = process.env.RUNNER_VERSION;
|
|
||||||
if (inputRunnerVersion) {
|
|
||||||
console.log(`Using input runner version ${inputRunnerVersion}`)
|
|
||||||
core.setOutput('version', inputRunnerVersion);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
|
||||||
console.log(`Using runner version ${runnerVersion}`)
|
|
||||||
core.setOutput('version', runnerVersion);
|
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
id: build-and-push
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
context: ./images
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
|
||||||
build-args: |
|
|
||||||
RUNNER_VERSION=${{ steps.image.outputs.version }}
|
|
||||||
push: true
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
|
|
||||||
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
|
|
||||||
org.opencontainers.image.licenses=MIT
|
|
||||||
431
.github/workflows/release.yml
vendored
431
.github/workflows/release.yml
vendored
@@ -50,12 +50,29 @@ jobs:
|
|||||||
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
|
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
|
||||||
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
|
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
|
||||||
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
|
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
|
||||||
win-arm64-sha: ${{ steps.sha.outputs.win-arm64-sha256 }}
|
|
||||||
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
|
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
|
||||||
osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }}
|
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 }}
|
||||||
|
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 }}
|
||||||
|
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 }}
|
||||||
|
osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }}
|
||||||
|
osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64, win-arm64 ]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ]
|
||||||
include:
|
include:
|
||||||
- runtime: linux-x64
|
- runtime: linux-x64
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
@@ -81,10 +98,6 @@ jobs:
|
|||||||
os: windows-2019
|
os: windows-2019
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
- runtime: win-arm64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -110,11 +123,81 @@ jobs:
|
|||||||
file=$(ls)
|
file=$(ls)
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
echo "Computed sha256: $sha for $file"
|
echo "Computed sha256: $sha for $file"
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
shell: bash
|
shell: bash
|
||||||
id: sha
|
id: sha
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
working-directory: _package
|
working-directory: _package
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noexternals
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_externals
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noruntime
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_runtime
|
||||||
|
- run: |
|
||||||
|
file=$(ls)
|
||||||
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
|
echo "Computed sha256: $sha for $file"
|
||||||
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
|
echo "::set-output name=sha256::$sha"
|
||||||
|
shell: bash
|
||||||
|
id: sha_noruntime_noexternals
|
||||||
|
name: Compute SHA256
|
||||||
|
working-directory: _package_trims/trim_runtime_externals
|
||||||
|
|
||||||
|
- name: Create trimmedpackages.json for ${{ matrix.runtime }}
|
||||||
|
if: matrix.runtime == 'win-x64'
|
||||||
|
uses: actions/github-script@0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
|
const fs = require('fs');
|
||||||
|
const runnerVersion = fs.readFileSync('src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
|
var trimmedPackages = fs.readFileSync('src/Misc/trimmedpackages_zip.json', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion).replace(/<RUNNER_PLATFORM>/g, '${{ matrix.runtime }}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<RUNTIME_HASH>/g, '${{hashFiles('**/_layout_trims/runtime/**/*')}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<EXTERNALS_HASH>/g, '${{hashFiles('**/_layout_trims/externals/**/*')}}')
|
||||||
|
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_EXTERNALS_HASH>/g, '${{steps.sha_noruntime_noexternals.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_HASH>/g, '${{steps.sha_noruntime.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_EXTERNALS_HASH>/g, '${{steps.sha_noexternals.outputs.sha256}}')
|
||||||
|
|
||||||
|
console.log(trimmedPackages)
|
||||||
|
fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages)
|
||||||
|
|
||||||
|
- name: Create trimmedpackages.json for ${{ matrix.runtime }}
|
||||||
|
if: matrix.runtime != 'win-x64'
|
||||||
|
uses: actions/github-script@0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
|
const fs = require('fs');
|
||||||
|
const runnerVersion = fs.readFileSync('src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
|
var trimmedPackages = fs.readFileSync('src/Misc/trimmedpackages_targz.json', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion).replace(/<RUNNER_PLATFORM>/g, '${{ matrix.runtime }}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<RUNTIME_HASH>/g, '${{hashFiles('**/_layout_trims/runtime/**/*')}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<EXTERNALS_HASH>/g, '${{hashFiles('**/_layout_trims/externals/**/*')}}')
|
||||||
|
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_EXTERNALS_HASH>/g, '${{steps.sha_noruntime_noexternals.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_RUNTIME_HASH>/g, '${{steps.sha_noruntime.outputs.sha256}}')
|
||||||
|
trimmedPackages = trimmedPackages.replace(/<NO_EXTERNALS_HASH>/g, '${{steps.sha_noexternals.outputs.sha256}}')
|
||||||
|
|
||||||
|
console.log(trimmedPackages)
|
||||||
|
fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages)
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact.
|
# 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
|
# Since each package name is unique, so we don't need to put ${{matrix}} info into artifact name
|
||||||
@@ -125,6 +208,10 @@ jobs:
|
|||||||
name: runner-packages
|
name: runner-packages
|
||||||
path: |
|
path: |
|
||||||
_package
|
_package
|
||||||
|
_package_trims/trim_externals
|
||||||
|
_package_trims/trim_runtime
|
||||||
|
_package_trims/trim_runtime_externals
|
||||||
|
${{ matrix.runtime }}-trimmedpackages.json
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
@@ -152,21 +239,38 @@ jobs:
|
|||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
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)
|
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
||||||
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
|
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
|
||||||
releaseNote = releaseNote.replace(/<WIN_ARM64_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_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(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}')
|
||||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
|
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
|
||||||
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
|
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
|
||||||
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
|
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
|
||||||
|
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}')
|
||||||
|
releaseNote = releaseNote.replace(/<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(/<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(/<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)
|
console.log(releaseNote)
|
||||||
core.setOutput('version', runnerVersion);
|
core.setOutput('version', runnerVersion);
|
||||||
core.setOutput('note', releaseNote);
|
core.setOutput('note', releaseNote);
|
||||||
|
|
||||||
- name: Validate Packages HASH
|
- name: Validate Packages HASH
|
||||||
|
working-directory: _package
|
||||||
run: |
|
run: |
|
||||||
ls -l
|
ls -l
|
||||||
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
||||||
echo "${{needs.build.outputs.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-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.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||||
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
||||||
@@ -184,6 +288,7 @@ jobs:
|
|||||||
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
||||||
body: |
|
body: |
|
||||||
${{ steps.releaseNote.outputs.note }}
|
${{ steps.releaseNote.outputs.note }}
|
||||||
|
prerelease: true
|
||||||
|
|
||||||
# Upload release assets (full runner packages)
|
# Upload release assets (full runner packages)
|
||||||
- name: Upload Release Asset (win-x64)
|
- name: Upload Release Asset (win-x64)
|
||||||
@@ -192,27 +297,17 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
asset_path: ${{ github.workspace }}/_package/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
||||||
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- 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 }}/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)
|
- name: Upload Release Asset (linux-x64)
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -222,7 +317,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -232,7 +327,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
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_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -242,7 +337,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
@@ -252,58 +347,250 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/_package/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
publish-image:
|
# Upload release assets (trim externals)
|
||||||
needs: release
|
- name: Upload Release Asset (win-x64-noexternals)
|
||||||
runs-on: ubuntu-latest
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
permissions:
|
env:
|
||||||
contents: read
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
packages: write
|
with:
|
||||||
env:
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
REGISTRY: ghcr.io
|
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
|
||||||
IMAGE_NAME: ${{ github.repository_owner }}/actions-runner
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
|
||||||
steps:
|
asset_content_type: application/octet-stream
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Compute image version
|
- name: Upload Release Asset (linux-x64-noexternals)
|
||||||
id: image
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
uses: actions/github-script@v6
|
env:
|
||||||
with:
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
with:
|
||||||
const fs = require('fs');
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/releaseVersion', 'utf8').replace(/\n$/g, '')
|
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
console.log(`Using runner version ${runnerVersion}`)
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
core.setOutput('version', runnerVersion);
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
- name: Upload Release Asset (osx-x64-noexternals)
|
||||||
uses: docker/setup-buildx-action@v2
|
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: Log into registry ${{ env.REGISTRY }}
|
- name: Upload Release Asset (osx-arm64-noexternals)
|
||||||
uses: docker/login-action@v2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
with:
|
env:
|
||||||
registry: ${{ env.REGISTRY }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
username: ${{ github.actor }}
|
with:
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
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: Build and push Docker image
|
- name: Upload Release Asset (linux-arm-noexternals)
|
||||||
id: build-and-push
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
uses: docker/build-push-action@v3
|
env:
|
||||||
with:
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
context: ./images
|
with:
|
||||||
platforms: |
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
linux/amd64
|
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
linux/arm64
|
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
tags: |
|
asset_content_type: application/octet-stream
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
- name: Upload Release Asset (linux-arm64-noexternals)
|
||||||
build-args: |
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
RUNNER_VERSION=${{ steps.image.outputs.version }}
|
env:
|
||||||
push: true
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
labels: |
|
with:
|
||||||
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
|
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
org.opencontainers.image.licenses=MIT
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
# Upload release assets (trim runtime)
|
||||||
|
- name: Upload Release Asset (win-x64-noruntime)
|
||||||
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
|
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
|
||||||
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (linux-x64-noruntime)
|
||||||
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
|
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (osx-x64-noruntime)
|
||||||
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
|
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}-noruntime.tar.gz
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: Upload Release Asset (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
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|||||||
16
.github/workflows/stale-bot.yml
vendored
16
.github/workflows/stale-bot.yml
vendored
@@ -1,16 +0,0 @@
|
|||||||
name: Stale Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 1' # every monday at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v8
|
|
||||||
with:
|
|
||||||
stale-issue-message: "This issue is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 15 days."
|
|
||||||
close-issue-message: "This issue was closed because it has been stalled for 15 days with no activity."
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
days-before-stale: 365
|
|
||||||
days-before-close: 15
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
cd src/Misc/expressionFunc/hashFiles
|
|
||||||
|
|
||||||
npx lint-staged
|
|
||||||
@@ -22,4 +22,4 @@ Runner releases:
|
|||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
We accept contributions in the form of issues and pull requests. The runner typically requires changes across the entire system and we aim for issues in the runner to be entirely self contained and fixable here. Therefore, we will primarily handle bug issues opened in this repo and we kindly request you to create all feature and enhancement requests on the [GitHub Feedback](https://github.com/community/community/discussions/categories/actions-and-packages) page. [Read more about our guidelines here](docs/contribute.md) before contributing.
|
We accept contributions in the form of issues and pull requests. [Read more here](docs/contribute.md) before contributing.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ We should give them that option, and publish examples how how they can create th
|
|||||||
- 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
|
- 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
|
## Interface
|
||||||
- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOKS=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler.
|
- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOK=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler.
|
||||||
- There is no partial opt in, you must handle every hook
|
- There is no partial opt in, you must handle every hook
|
||||||
- We will pass a command and some args via `stdin`
|
- 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
|
- An exit code of 0 is a success, every other exit code is a failure
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# ADR 2494: Runner Image Tags
|
|
||||||
|
|
||||||
**Date**: 2023-03-17
|
|
||||||
|
|
||||||
**Status**: Accepted<!-- |Accepted|Rejected|Superceded|Deprecated -->
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
Following the [adoption of actions-runner-controller by GitHub](https://github.com/actions/actions-runner-controller/discussions/2072) and the introduction of the new runner scale set autoscaling mode, we needed to provide a basic runner image that could be used off the shelf without much friction.
|
|
||||||
|
|
||||||
The [current runner image](https://github.com/actions/runner/pkgs/container/actions-runner) is published to GHCR. Each release of this image is tagged with the runner version and the most recent release is also tagged with `latest`.
|
|
||||||
|
|
||||||
While the use of `latest` is common practice, we recommend that users pin a specific version of the runner image for a predictable runtime and improved security posture. However, we still notice that a large number of end users are relying on the `latest` tag & raising issues when they encounter problems.
|
|
||||||
|
|
||||||
Add to that, the community actions-runner-controller maintainers have issued a [deprecation notice](https://github.com/actions/actions-runner-controller/issues/2056) of the `latest` tag for the existing runner images (https://github.com/orgs/actions-runner-controller/packages).
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
Proceed with Option 2, keeping the `latest` tag and adding the `NOTES.txt` file to our helm charts with the notice.
|
|
||||||
|
|
||||||
### Option 1: Remove the `latest` tag
|
|
||||||
|
|
||||||
By removing the `latest` tag, we have to proceed with either of these options:
|
|
||||||
|
|
||||||
1. Remove the runner image reference in the `values.yaml` provided with the `gha-runner-scale-set` helm chart and mark these fields as required so that users have to explicitly specify a runner image and a specific tag. This will obviously introduce more friction for users who want to start using actions-runner-controller for the first time.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: ""
|
|
||||||
tag: ""
|
|
||||||
command: ["/home/runner/run.sh"]
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Pin a specific runner image tag in the `values.yaml` provided with the `gha-runner-scale-set` helm chart. This will reduce friction for users who want to start using actions-runner-controller for the first time but will require us to update the `values.yaml` with every new runner release.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: "ghcr.io/actions/actions-runner"
|
|
||||||
tag: "v2.300.0"
|
|
||||||
command: ["/home/runner/run.sh"]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 2: Keep the `latest` tag
|
|
||||||
|
|
||||||
Keeping the `latest` tag is also a reasonable option especially if we don't expect to make any breaking changes to the runner image. We could enhance this by adding a [NOTES.txt](https://helm.sh/docs/chart_template_guide/notes_files/) to the helm chart which will be displayed to the user after a successful helm install/upgrade. This will help users understand the implications of using the `latest` tag and how to pin a specific version of the runner image.
|
|
||||||
|
|
||||||
The runner image release workflow will need to be updated so that the image is pushed to GHCR and tagged only when the runner rollout has reached all scale units.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
Proceeding with **option 1** means:
|
|
||||||
|
|
||||||
1. We will enhance the runtime predictability and security posture of our end users
|
|
||||||
1. We will have to update the `values.yaml` with every new runner release (that can be automated)
|
|
||||||
1. We will introduce friction for users who want to start using actions-runner-controller for the first time
|
|
||||||
|
|
||||||
Proceeding with **option 2** means:
|
|
||||||
|
|
||||||
1. We will have to continue to maintain the `latest` tag
|
|
||||||
1. We will assume that end users will be able to handle the implications of using the `latest` tag
|
|
||||||
1. Runner image release workflow needs to be updated
|
|
||||||
@@ -7,26 +7,19 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
|
|
||||||
- For GitHub.com
|
- For GitHub.com
|
||||||
- The runner needs to access `https://api.github.com` for downloading actions.
|
- The runner needs to access `https://api.github.com` for downloading actions.
|
||||||
- The runner needs to access `https://codeload.github.com` for downloading actions tar.gz/zip.
|
|
||||||
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
||||||
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
||||||
- The runner needs to access `https://results-receiver.actions.githubusercontent.com/.../` for reporting progress and uploading logs during a workflow job execution.
|
|
||||||
---
|
|
||||||
**NOTE:** for the full list of domains that are required to be in the firewall allow list refer to the [GitHub self-hosted runners requirements documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github).
|
|
||||||
|
|
||||||
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -v https://api.github.com/zen
|
curl -v https://api.github.com/api/v3/zen
|
||||||
curl -v https://codeload.github.com/_ping
|
|
||||||
curl -v https://vstoken.actions.githubusercontent.com/_apis/health
|
curl -v https://vstoken.actions.githubusercontent.com/_apis/health
|
||||||
curl -v https://pipelines.actions.githubusercontent.com/_apis/health
|
curl -v https://pipelines.actions.githubusercontent/_apis/health
|
||||||
curl -v https://results-receiver.actions.githubusercontent.com/health
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- For GitHub Enterprise Server
|
- For GitHub Enterprise Server
|
||||||
- The runner needs to access `https://[hostname]/api/v3` for downloading actions.
|
- The runner needs to access `https://[hostname]/api/v3` for downloading actions.
|
||||||
- The runner needs to access `https://codeload.[hostname]/_ping` for downloading actions tar.gz/zip.
|
|
||||||
- The runner needs to access `https://[hostname]/_services/vstoken/_apis/.../` for requesting an access token.
|
- 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.
|
- The runner needs to access `https://[hostname]/_services/pipelines/_apis/.../` for receiving workflow jobs.
|
||||||
|
|
||||||
@@ -34,7 +27,6 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
|
|
||||||
```
|
```
|
||||||
curl -v https://[hostname]/api/v3/zen
|
curl -v https://[hostname]/api/v3/zen
|
||||||
curl -v https://codeload.[hostname]/_ping
|
|
||||||
curl -v https://[hostname]/_services/vstoken/_apis/health
|
curl -v https://[hostname]/_services/vstoken/_apis/health
|
||||||
curl -v https://[hostname]/_services/pipelines/_apis/health
|
curl -v https://[hostname]/_services/pipelines/_apis/health
|
||||||
```
|
```
|
||||||
@@ -50,10 +42,6 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
- Ping api.github.com or myGHES.com using dotnet
|
- Ping api.github.com or myGHES.com using dotnet
|
||||||
- Make HTTP GET to https://api.github.com or https://myGHES.com/api/v3 using dotnet, check response headers contains `X-GitHub-Request-Id`
|
- Make HTTP GET to https://api.github.com or https://myGHES.com/api/v3 using dotnet, check response headers contains `X-GitHub-Request-Id`
|
||||||
---
|
---
|
||||||
- DNS lookup for codeload.github.com or codeload.myGHES.com using dotnet
|
|
||||||
- Ping codeload.github.com or codeload.myGHES.com using dotnet
|
|
||||||
- Make HTTP GET to https://codeload.github.com/_ping or https://codeload.myGHES.com/_ping using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
---
|
|
||||||
- DNS lookup for vstoken.actions.githubusercontent.com using dotnet
|
- DNS lookup for vstoken.actions.githubusercontent.com using dotnet
|
||||||
- Ping vstoken.actions.githubusercontent.com using dotnet
|
- Ping vstoken.actions.githubusercontent.com using dotnet
|
||||||
- Make HTTP GET to https://vstoken.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/vstoken/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
- Make HTTP GET to https://vstoken.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/vstoken/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
||||||
@@ -62,10 +50,6 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
- Ping pipelines.actions.githubusercontent.com using dotnet
|
- Ping pipelines.actions.githubusercontent.com using dotnet
|
||||||
- Make HTTP GET to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
- Make HTTP GET to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
||||||
- Make HTTP POST to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
- Make HTTP POST to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
||||||
---
|
|
||||||
- DNS lookup for results-receiver.actions.githubusercontent.com using dotnet
|
|
||||||
- Ping results-receiver.actions.githubusercontent.com using dotnet
|
|
||||||
- Make HTTP GET to https://results-receiver.actions.githubusercontent.com/health using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
|
|
||||||
## How to fix the issue?
|
## How to fix the issue?
|
||||||
|
|
||||||
@@ -80,4 +64,4 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
|
|
||||||
## Still not working?
|
## Still not working?
|
||||||
|
|
||||||
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.
|
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,30 +20,11 @@ The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` be
|
|||||||
|
|
||||||
## How to fix the issue?
|
## How to fix the issue?
|
||||||
|
|
||||||
### 1. Check global and system git config
|
### 1. Check the common network issue
|
||||||
|
|
||||||
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)
|
> Please check the [network doc](./network.md)
|
||||||
|
|
||||||
### 3. SSL certificate related issue
|
### 2. 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.
|
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)
|
> Please check the [SSL cert doc](./sslcert.md)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
- A Proxy may try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
- A Proxy may try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
||||||
|
|
||||||
- Firewall rules that block action runner from accessing [certain hosts](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github), ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
|
- Firewall rules that block action runner from accessing certain hosts, ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
|
||||||
|
|
||||||
|
|
||||||
### Identify and solve these problems
|
### Identify and solve these problems
|
||||||
@@ -42,7 +42,6 @@ If you are having trouble connecting, try these steps:
|
|||||||
- https://api.github.com/
|
- https://api.github.com/
|
||||||
- https://vstoken.actions.githubusercontent.com/_apis/health
|
- https://vstoken.actions.githubusercontent.com/_apis/health
|
||||||
- https://pipelines.actions.githubusercontent.com/_apis/health
|
- https://pipelines.actions.githubusercontent.com/_apis/health
|
||||||
- https://results-receiver.actions.githubusercontent.com/health
|
|
||||||
- For GHES/GHAE
|
- For GHES/GHAE
|
||||||
- https://myGHES.com/_services/vstoken/_apis/health
|
- https://myGHES.com/_services/vstoken/_apis/health
|
||||||
- https://myGHES.com/_services/pipelines/_apis/health
|
- https://myGHES.com/_services/pipelines/_apis/health
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors.Please note the runner typically requires changes across the entire system and we aim for issues in the runner to be entirely self contained and fixable here. Therefore, we will primarily handle bug issues opened in this repo and we kindly request you to create all feature and enhancement requests on the [GitHub Feedback](https://github.com/community/community/discussions/categories/actions-and-packages) page.
|
We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors.
|
||||||
|
|
||||||
> IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost.
|
> IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost.
|
||||||
|
|
||||||
@@ -27,8 +27,6 @@ An ADR is an Architectural Decision Record. This allows consensus on the direct
|
|||||||
|
|
||||||
 Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev 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
|
## Quickstart: Run a job from a real repository
|
||||||
|
|
||||||
If you just want to get from building the sourcecode to using it to execute an action, you will need:
|
If you just want to get from building the sourcecode to using it to execute an action, you will need:
|
||||||
@@ -157,12 +155,4 @@ cat (Runner/Worker)_TIMESTAMP.log # view your log file
|
|||||||
## Styling
|
## Styling
|
||||||
|
|
||||||
We use the .NET Foundation and CoreCLR style guidelines [located here](
|
We use the .NET Foundation and CoreCLR style guidelines [located here](
|
||||||
https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md)
|
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md)
|
||||||
|
|
||||||
### Format C# Code
|
|
||||||
|
|
||||||
To format both staged and unstaged .cs files
|
|
||||||
```
|
|
||||||
cd ./src
|
|
||||||
./dev.(cmd|sh) format
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ All the configs below can be found in `.vscode/launch.json`.
|
|||||||
If you launch `Run` or `Run [build]`, it starts a process called `Runner.Listener`.
|
If you launch `Run` or `Run [build]`, it starts a process called `Runner.Listener`.
|
||||||
This process will receive any job queued on this repository if the job runs on matching labels (e.g `runs-on: self-hosted`).
|
This process will receive any job queued on this repository if the job runs on matching labels (e.g `runs-on: self-hosted`).
|
||||||
Once a job is received, a `Runner.Listener` starts a new process of `Runner.Worker`.
|
Once a job is received, a `Runner.Listener` starts a new process of `Runner.Worker`.
|
||||||
Since this is a different process, you can't use the same debugger session debug it.
|
Since this is a diferent process, you can't use the same debugger session debug it.
|
||||||
Instead, a parallel debugging session has to be started, using a different launch config.
|
Instead, a parallel debugging session has to be started, using a different launch config.
|
||||||
Luckily, VS Code supports multiple parallel debugging sessions.
|
Luckily, VS Code supports multiple parallel debugging sessions.
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,16 @@
|
|||||||
|
|
||||||
## Supported Distributions and Versions
|
## Supported Distributions and Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#linux)."
|
x64
|
||||||
|
- Red Hat Enterprise Linux 7
|
||||||
|
- CentOS 7
|
||||||
|
- Oracle Linux 7
|
||||||
|
- Fedora 29+
|
||||||
|
- Debian 9+
|
||||||
|
- Ubuntu 16.04+
|
||||||
|
- Linux Mint 18+
|
||||||
|
- openSUSE 15+
|
||||||
|
- SUSE Enterprise Linux (SLES) 12 SP2+
|
||||||
|
|
||||||
## Install .Net Core 3.x Linux Dependencies
|
## Install .Net Core 3.x Linux Dependencies
|
||||||
|
|
||||||
@@ -25,7 +34,7 @@ The `installdependencies.sh` script should install all required dependencies on
|
|||||||
|
|
||||||
Debian based OS (Debian, Ubuntu, Linux Mint)
|
Debian based OS (Debian, Ubuntu, Linux Mint)
|
||||||
|
|
||||||
- liblttng-ust1 or liblttng-ust0
|
- liblttng-ust0
|
||||||
- libkrb5-3
|
- libkrb5-3
|
||||||
- zlib1g
|
- zlib1g
|
||||||
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#macos)."
|
- macOS High Sierra (10.13) and later versions
|
||||||
|
- x64 and arm64 (Apple Silicon)
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#windows)."
|
- Windows 7 64-bit
|
||||||
|
- Windows 8.1 64-bit
|
||||||
|
- Windows 10 64-bit
|
||||||
|
- Windows Server 2012 R2 64-bit
|
||||||
|
- Windows Server 2016 64-bit
|
||||||
|
- Windows Server 2019 64-bit
|
||||||
|
|
||||||
## [More .NET Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
## [More .NET Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
# Source: https://github.com/dotnet/dotnet-docker
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy as build
|
|
||||||
|
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
ARG RUNNER_VERSION
|
|
||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.6.1
|
|
||||||
ARG DOCKER_VERSION=27.1.1
|
|
||||||
ARG BUILDX_VERSION=0.16.2
|
|
||||||
|
|
||||||
RUN apt update -y && apt install curl unzip -y
|
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
|
||||||
RUN export RUNNER_ARCH=${TARGETARCH} \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export RUNNER_ARCH=x64 ; fi \
|
|
||||||
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-${TARGETOS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
|
||||||
&& tar xzf ./runner.tar.gz \
|
|
||||||
&& rm runner.tar.gz
|
|
||||||
|
|
||||||
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
|
|
||||||
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
|
||||||
&& rm runner-container-hooks.zip
|
|
||||||
|
|
||||||
RUN export RUNNER_ARCH=${TARGETARCH} \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
|
|
||||||
&& curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
|
|
||||||
&& tar zxvf docker.tgz \
|
|
||||||
&& rm -rf docker.tgz \
|
|
||||||
&& mkdir -p /usr/local/lib/docker/cli-plugins \
|
|
||||||
&& curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
|
|
||||||
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
|
|
||||||
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-jammy
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
ENV RUNNER_MANUALLY_TRAP_SIG=1
|
|
||||||
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
|
|
||||||
ENV ImageOS=ubuntu22
|
|
||||||
|
|
||||||
# 'gpg-agent' and 'software-properties-common' are needed for the 'add-apt-repository' command that follows
|
|
||||||
RUN apt update -y \
|
|
||||||
&& apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Configure git-core/ppa based on guidance here: https://git-scm.com/download/linux
|
|
||||||
RUN add-apt-repository ppa:git-core/ppa \
|
|
||||||
&& apt update -y \
|
|
||||||
&& apt install -y --no-install-recommends git
|
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
|
|
||||||
&& groupadd docker --gid 123 \
|
|
||||||
&& usermod -aG sudo runner \
|
|
||||||
&& usermod -aG docker runner \
|
|
||||||
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
|
|
||||||
&& echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers
|
|
||||||
|
|
||||||
WORKDIR /home/runner
|
|
||||||
|
|
||||||
COPY --chown=runner:docker --from=build /actions-runner .
|
|
||||||
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
|
|
||||||
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
|
|
||||||
|
|
||||||
USER runner
|
|
||||||
@@ -1,22 +1,14 @@
|
|||||||
## What's Changed
|
## Features
|
||||||
|
## Bugs
|
||||||
|
- Fixed an issue where container environment variables names or values could escape the docker command (#2108)
|
||||||
|
|
||||||
- .NET 8 OS compatibility test https://github.com/actions/runner/pull/3422
|
## Misc
|
||||||
- Ignore ssl cert on websocket client https://github.com/actions/runner/pull/3423
|
|
||||||
- Revert "Bump runner to dotnet 8" https://github.com/actions/runner/pull/3412
|
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/actions/runner/compare/v2.318.0...v2.319.0
|
|
||||||
|
|
||||||
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
|
||||||
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
|
||||||
See https://docs.github.com/en/enterprise-cloud@latest/actions/hosting-your-own-runners/adding-self-hosted-runners_
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
|
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
|
|
||||||
The following snipped needs to be run on `powershell`:
|
The following snipped needs to be run on `powershell`:
|
||||||
|
``` powershell
|
||||||
```powershell
|
|
||||||
# Create a folder under the drive root
|
# Create a folder under the drive root
|
||||||
mkdir \actions-runner ; cd \actions-runner
|
mkdir \actions-runner ; cd \actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -26,27 +18,9 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
|||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
||||||
```
|
```
|
||||||
|
|
||||||
## [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
|
## OSX x64
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -55,9 +29,9 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
|||||||
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
## OSX arm64 (Apple silicon)
|
## [Pre-release] OSX arm64 (Apple silicon)
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -68,7 +42,7 @@ tar xzf ./actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
|
|||||||
|
|
||||||
## Linux x64
|
## Linux x64
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -79,7 +53,7 @@ tar xzf ./actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
|||||||
|
|
||||||
## Linux arm64
|
## Linux arm64
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -90,7 +64,7 @@ tar xzf ./actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz
|
|||||||
|
|
||||||
## Linux arm
|
## Linux arm
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -100,7 +74,6 @@ tar xzf ./actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Using your self hosted runner
|
## Using your self hosted runner
|
||||||
|
|
||||||
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
||||||
|
|
||||||
## SHA-256 Checksums
|
## SHA-256 Checksums
|
||||||
@@ -108,9 +81,29 @@ 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:
|
The SHA-256 checksums for the packages included in this build are shown below:
|
||||||
|
|
||||||
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
|
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
|
||||||
- actions-runner-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-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-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 -->
|
||||||
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
|
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
|
||||||
- actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 -->
|
- actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 -->
|
||||||
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
|
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
|
||||||
|
|
||||||
|
- actions-runner-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals -->
|
||||||
|
- actions-runner-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-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-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.293.1
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ set -e
|
|||||||
# Configures it as a service more secure
|
# Configures it as a service more secure
|
||||||
# Should be used on VMs and not containers
|
# Should be used on VMs and not containers
|
||||||
# Works on OSX and Linux
|
# Works on OSX and Linux
|
||||||
# Assumes x64 arch (support arm64)
|
# Assumes x64 arch
|
||||||
# See EXAMPLES below
|
# See EXAMPLES below
|
||||||
|
|
||||||
flags_found=false
|
flags_found=false
|
||||||
|
|
||||||
while getopts 's:g:n:r:u:l:df' opt; do
|
while getopts 's:g:n:r:u:l:' opt; do
|
||||||
flags_found=true
|
flags_found=true
|
||||||
|
|
||||||
case $opt in
|
case $opt in
|
||||||
@@ -35,12 +35,6 @@ while getopts 's:g:n:r:u:l:df' opt; do
|
|||||||
l)
|
l)
|
||||||
labels=$OPTARG
|
labels=$OPTARG
|
||||||
;;
|
;;
|
||||||
f)
|
|
||||||
replace='true'
|
|
||||||
;;
|
|
||||||
d)
|
|
||||||
disableupdate='true'
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
echo "
|
echo "
|
||||||
Runner Service Installer
|
Runner Service Installer
|
||||||
@@ -55,9 +49,7 @@ Usage:
|
|||||||
-n optional name of the runner, defaults to hostname
|
-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
|
-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
|
-u optional user svc will run as, defaults to current
|
||||||
-l optional list of labels (split by comma) applied on the runner
|
-l optional list of labels (split by comma) applied on the runner"
|
||||||
-d optional allow runner to remain on the current version for one month after the release of a newer version
|
|
||||||
-f optional replace any existing runner with the same name"
|
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -87,9 +79,6 @@ sudo echo
|
|||||||
runner_plat=linux
|
runner_plat=linux
|
||||||
[ ! -z "$(which sw_vers)" ] && runner_plat=osx;
|
[ ! -z "$(which sw_vers)" ] && runner_plat=osx;
|
||||||
|
|
||||||
runner_arch=x64
|
|
||||||
[ ! -z "$(arch | grep arm64)" ] && runner_arch=arm64
|
|
||||||
|
|
||||||
function fatal()
|
function fatal()
|
||||||
{
|
{
|
||||||
echo "error: $1" >&2
|
echo "error: $1" >&2
|
||||||
@@ -142,7 +131,7 @@ echo "Downloading latest runner ..."
|
|||||||
# For the GHES Alpha, download the runner from github.com
|
# For the GHES Alpha, download the runner from github.com
|
||||||
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
|
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
|
||||||
latest_version=$(echo ${latest_version_label:1})
|
latest_version=$(echo ${latest_version_label:1})
|
||||||
runner_file="actions-runner-${runner_plat}-${runner_arch}-${latest_version}.tar.gz"
|
runner_file="actions-runner-${runner_plat}-x64-${latest_version}.tar.gz"
|
||||||
|
|
||||||
if [ -f "${runner_file}" ]; then
|
if [ -f "${runner_file}" ]; then
|
||||||
echo "${runner_file} exists. skipping download."
|
echo "${runner_file} exists. skipping download."
|
||||||
@@ -180,8 +169,8 @@ fi
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Configuring ${runner_name} @ $runner_url"
|
echo "Configuring ${runner_name} @ $runner_url"
|
||||||
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup \"$runner_group\"} ${disableupdate:+--disableupdate}"
|
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 ${replace:+--replace} --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup "$runner_group"} ${disableupdate:+--disableupdate}
|
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
|
# Configuring as a service
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ set -e
|
|||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# export RUNNER_CFG_PAT=<yourPAT>
|
# export RUNNER_CFG_PAT=<yourPAT>
|
||||||
# ./delete.sh <scope> [<name>]
|
# ./delete.sh scope name
|
||||||
#
|
#
|
||||||
# scope required repo (:owner/:repo) or org (:organization)
|
# scope required repo (:owner/:repo) or org (:organization)
|
||||||
# name optional defaults to hostname. name to delete
|
# name optional defaults to hostname. name to delete
|
||||||
@@ -26,17 +26,17 @@ set -e
|
|||||||
runner_scope=${1}
|
runner_scope=${1}
|
||||||
runner_name=${2}
|
runner_name=${2}
|
||||||
|
|
||||||
function fatal()
|
echo "Deleting runner ${runner_name} @ ${runner_scope}"
|
||||||
|
|
||||||
|
function fatal()
|
||||||
{
|
{
|
||||||
echo "error: $1" >&2
|
echo "error: $1" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi
|
if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi
|
||||||
|
if [ -z "${runner_name}" ]; then fatal "supply name as argument 2"; fi
|
||||||
if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi
|
if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi
|
||||||
if [ -z "${runner_name}" ]; then runner_name=`hostname`; fi
|
|
||||||
|
|
||||||
echo "Deleting runner ${runner_name} @ ${runner_scope}"
|
|
||||||
|
|
||||||
which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc"
|
which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc"
|
||||||
which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc"
|
which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[*.cs]
|
[*.cs]
|
||||||
charset = utf-8-bom
|
charset = utf-8
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
csharp_new_line_before_else = true
|
csharp_new_line_before_else = true
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-arm64'">
|
|
||||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
|
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
<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-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-x64
vendored
Normal file
1
src/Misc/contentHash/externals/win-x64
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
f75a671e5a188c76680739689aa75331a2c09d483dce9c80023518c48fd67a18
|
||||||
@@ -1,19 +1,11 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"bracketSpacing": false,
|
"bracketSpacing": false,
|
||||||
"arrowParens": "avoid",
|
"arrowParens": "avoid",
|
||||||
"overrides": [
|
"parser": "typescript"
|
||||||
{
|
}
|
||||||
"files": "*.{js,ts,json}",
|
|
||||||
"options": {
|
|
||||||
"tabWidth": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,3 +1 @@
|
|||||||
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run prepare && npm run all`.
|
To update hashFiles under `Misc/layoutbin` run `npm install && npm run all`
|
||||||
|
|
||||||
When you commit changes to the JSON or Typescript file, the javascript binary will be automatically re-compiled and added to the latest commit.
|
|
||||||
4641
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
4641
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,9 +9,7 @@
|
|||||||
"format-check": "prettier --check **/*.ts",
|
"format-check": "prettier --check **/*.ts",
|
||||||
"lint": "eslint src/**/*.ts",
|
"lint": "eslint src/**/*.ts",
|
||||||
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
||||||
"all": "npm run format && npm run lint && npm run build && npm run pack",
|
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||||
"prepare": "cd ../../../../ && husky install"
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -20,32 +18,18 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"actions"
|
"actions"
|
||||||
],
|
],
|
||||||
"lint-staged": {
|
|
||||||
"*.md": [
|
|
||||||
"prettier --write",
|
|
||||||
"git add ."
|
|
||||||
],
|
|
||||||
"*.{ts,json}": [
|
|
||||||
"sh -c 'npm run all'",
|
|
||||||
"git add ."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"author": "GitHub Actions",
|
"author": "GitHub Actions",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/glob": "^0.4.0"
|
"@actions/glob": "^0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.6.2",
|
"@types/node": "^12.7.12",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
"@typescript-eslint/parser": "^5.15.0",
|
||||||
"@typescript-eslint/parser": "^6.7.2",
|
"@zeit/ncc": "^0.20.5",
|
||||||
"@vercel/ncc": "^0.38.0",
|
"eslint": "^8.11.0",
|
||||||
"eslint": "^8.47.0",
|
"eslint-plugin-github": "^4.3.5",
|
||||||
"eslint-plugin-github": "^4.10.0",
|
"prettier": "^1.19.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"typescript": "^3.6.4"
|
||||||
"prettier": "^3.0.3",
|
|
||||||
"typescript": "^5.2.2",
|
|
||||||
"husky": "^8.0.3",
|
|
||||||
"lint-staged": "^14.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,13 +52,12 @@ async function run(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
run()
|
||||||
try {
|
.then(out => {
|
||||||
const out = await run()
|
|
||||||
console.log(out)
|
console.log(out)
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
} catch (err) {
|
})
|
||||||
|
.catch(err => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
})
|
||||||
})()
|
|
||||||
|
|||||||
@@ -3,13 +3,8 @@ PACKAGERUNTIME=$1
|
|||||||
PRECACHE=$2
|
PRECACHE=$2
|
||||||
|
|
||||||
NODE_URL=https://nodejs.org/dist
|
NODE_URL=https://nodejs.org/dist
|
||||||
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
|
NODE12_VERSION="12.22.7"
|
||||||
NODE_ALPINE_URL=https://github.com/actions/alpine_nodejs/releases/download
|
NODE16_VERSION="16.13.0"
|
||||||
# When you update Node versions you must also create a new release of alpine_nodejs at that updated version.
|
|
||||||
# Follow the instructions here: https://github.com/actions/alpine_nodejs?tab=readme-ov-file#getting-started
|
|
||||||
NODE16_VERSION="16.20.2"
|
|
||||||
NODE20_VERSION="20.13.1"
|
|
||||||
NODE16_UNOFFICIAL_VERSION="16.20.0" # used only for win-arm64, remove node16 unofficial version when official version is available
|
|
||||||
|
|
||||||
get_abs_path() {
|
get_abs_path() {
|
||||||
# exploits the fact that pwd will print abs path when no args
|
# exploits the fact that pwd will print abs path when no args
|
||||||
@@ -59,22 +54,12 @@ function acquireExternalTool() {
|
|||||||
# Download from source to the partial file.
|
# Download from source to the partial file.
|
||||||
echo "Downloading $download_source"
|
echo "Downloading $download_source"
|
||||||
mkdir -p "$(dirname "$download_target")" || checkRC 'mkdir'
|
mkdir -p "$(dirname "$download_target")" || checkRC 'mkdir'
|
||||||
|
|
||||||
CURL_VERSION=$(curl --version | awk 'NR==1{print $2}')
|
|
||||||
echo "Curl version: $CURL_VERSION"
|
|
||||||
|
|
||||||
# curl -f Fail silently (no output at all) on HTTP errors (H)
|
# curl -f Fail silently (no output at all) on HTTP errors (H)
|
||||||
|
# -k Allow connections to SSL sites without certs (H)
|
||||||
# -S Show error. With -s, make curl show errors when they occur
|
# -S Show error. With -s, make curl show errors when they occur
|
||||||
# -L Follow redirects (H)
|
# -L Follow redirects (H)
|
||||||
# -o FILE Write to FILE instead of stdout
|
# -o FILE Write to FILE instead of stdout
|
||||||
# --retry 3 Retries transient errors 3 times (timeouts, 5xx)
|
curl -fkSL -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
||||||
if [[ "$(printf '%s\n' "7.71.0" "$CURL_VERSION" | sort -V | head -n1)" != "7.71.0" ]]; then
|
|
||||||
# Curl version is less than or equal to 7.71.0, skipping retry-all-errors flag
|
|
||||||
curl -fSL --retry 3 -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
|
||||||
else
|
|
||||||
# Curl version is greater than 7.71.0, running curl with --retry-all-errors flag
|
|
||||||
curl -fSL --retry 3 --retry-all-errors -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Move the partial file to the download target.
|
# Move the partial file to the download target.
|
||||||
mv "$partial_target" "$download_target" || checkRC 'mv'
|
mv "$partial_target" "$download_target" || checkRC 'mv'
|
||||||
@@ -140,22 +125,10 @@ function acquireExternalTool() {
|
|||||||
|
|
||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
|
||||||
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_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
|
|
||||||
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -163,30 +136,29 @@ fi
|
|||||||
|
|
||||||
# Download the external tools only for OSX.
|
# Download the external tools only for OSX.
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-x64.tar.gz" node20 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
||||||
# node.js v12 doesn't support macOS on arm64.
|
# node.js v12 doesn't support macOS on arm64.
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-arm64.tar.gz" node20 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
||||||
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-v${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_ALPINE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-x64.tar.gz" node20 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_ALPINE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-alpine-x64.tar.gz" node20_alpine
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-arm64.tar.gz" node20 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ if (exitServiceAfterNFailures <= 0) {
|
|||||||
exitServiceAfterNFailures = NaN;
|
exitServiceAfterNFailures = NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
var unknownFailureRetryCount = 0;
|
var consecutiveFailureCount = 0;
|
||||||
var retriableFailureRetryCount = 0;
|
|
||||||
|
|
||||||
var gracefulShutdown = function () {
|
var gracefulShutdown = function () {
|
||||||
console.log("Shutting down runner listener");
|
console.log("Shutting down runner listener");
|
||||||
@@ -63,8 +62,7 @@ var runService = function () {
|
|||||||
|
|
||||||
listener.stdout.on("data", (data) => {
|
listener.stdout.on("data", (data) => {
|
||||||
if (data.toString("utf8").includes("Listening for Jobs")) {
|
if (data.toString("utf8").includes("Listening for Jobs")) {
|
||||||
unknownFailureRetryCount = 0;
|
consecutiveFailureCount = 0;
|
||||||
retriableFailureRetryCount = 0;
|
|
||||||
}
|
}
|
||||||
process.stdout.write(data.toString("utf8"));
|
process.stdout.write(data.toString("utf8"));
|
||||||
});
|
});
|
||||||
@@ -94,43 +92,24 @@ var runService = function () {
|
|||||||
console.log(
|
console.log(
|
||||||
"Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
"Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
||||||
);
|
);
|
||||||
unknownFailureRetryCount = 0;
|
consecutiveFailureCount = 0;
|
||||||
retriableFailureRetryCount++;
|
|
||||||
if (retriableFailureRetryCount >= 10) {
|
|
||||||
console.error(
|
|
||||||
"Stopping the runner after 10 consecutive re-tryable failures"
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
}
|
|
||||||
} else if (code === 3 || code === 4) {
|
} else if (code === 3 || code === 4) {
|
||||||
console.log(
|
console.log(
|
||||||
"Runner listener exit because of updating, re-launch runner in 5 seconds."
|
"Runner listener exit because of updating, re-launch runner in 5 seconds."
|
||||||
);
|
);
|
||||||
unknownFailureRetryCount = 0;
|
consecutiveFailureCount = 0;
|
||||||
retriableFailureRetryCount++;
|
|
||||||
if (retriableFailureRetryCount >= 10) {
|
|
||||||
console.error(
|
|
||||||
"Stopping the runner after 10 consecutive re-tryable failures"
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
}
|
|
||||||
} else if (code === 5) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
} else {
|
} else {
|
||||||
var messagePrefix = "Runner listener exit with undefined return code";
|
var messagePrefix = "Runner listener exit with undefined return code";
|
||||||
unknownFailureRetryCount++;
|
consecutiveFailureCount++;
|
||||||
retriableFailureRetryCount = 0;
|
|
||||||
if (
|
if (
|
||||||
!isNaN(exitServiceAfterNFailures) &&
|
!isNaN(exitServiceAfterNFailures) &&
|
||||||
unknownFailureRetryCount >= exitServiceAfterNFailures
|
consecutiveFailureCount >= exitServiceAfterNFailures
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
`${messagePrefix}, exiting service after ${unknownFailureRetryCount} consecutive failures`
|
`${messagePrefix}, exiting service after ${consecutiveFailureCount} consecutive failures`
|
||||||
);
|
);
|
||||||
stopping = true
|
gracefulShutdown();
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
console.log(`${messagePrefix}, re-launch runner in 5 seconds.`);
|
console.log(`${messagePrefix}, re-launch runner in 5 seconds.`);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$apt_get update && $apt_get install -y libkrb5-3 zlib1g
|
$apt_get update && $apt_get install -y liblttng-ust0 libkrb5-3 zlib1g
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'$apt_get' failed with exit code '$?'"
|
echo "'$apt_get' failed with exit code '$?'"
|
||||||
@@ -94,14 +94,6 @@ then
|
|||||||
fi
|
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$
|
apt_get_with_fallbacks libssl1.1$ libssl1.0.2$ libssl1.0.0$
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -120,9 +120,6 @@ if ERRORLEVEL 1 (
|
|||||||
|
|
||||||
echo [%date% %time%] Update succeed >> "%logfile%" 2>&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 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
|
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
|
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
||||||
|
|||||||
@@ -180,9 +180,6 @@ fi
|
|||||||
|
|
||||||
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
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
|
# 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
|
# 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
|
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@echo off
|
@echo off
|
||||||
SET UPDATEFILE=update.finished
|
|
||||||
"%~dp0\bin\Runner.Listener.exe" run %*
|
"%~dp0\bin\Runner.Listener.exe" run %*
|
||||||
|
|
||||||
rem using `if %ERRORLEVEL% EQU N` instead of `if ERRORLEVEL N`
|
rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
|
||||||
rem `if ERRORLEVEL N` means: error level is N or MORE
|
rem `if ERRORLEVEL N` means: error level is N or MORE
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 0 (
|
if %ERRORLEVEL% EQU 0 (
|
||||||
@@ -22,37 +22,18 @@ if %ERRORLEVEL% EQU 2 (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 3 (
|
if %ERRORLEVEL% EQU 3 (
|
||||||
rem Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
rem Sleep 5 seconds to wait for the runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
||||||
FOR /L %%G IN (1,1,30) DO (
|
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
||||||
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
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 4 (
|
if %ERRORLEVEL% EQU 4 (
|
||||||
rem Wait for 30 seconds or for flag file to exists for the runner update process finish
|
rem Sleep 5 seconds to wait for the ephemeral runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
||||||
FOR /L %%G IN (1,1,30) DO (
|
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
||||||
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
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 5 (
|
|
||||||
echo "Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "Exiting after unknown error code: %ERRORLEVEL%"
|
echo "Exiting after unknown error code: %ERRORLEVEL%"
|
||||||
exit /b 0
|
exit /b 0
|
||||||
@@ -17,22 +17,6 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
|
|||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
|
||||||
# Wait for docker to start
|
|
||||||
if [ ! -z "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" ]; then
|
|
||||||
if [ "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" -gt 0 ]; then
|
|
||||||
echo "Waiting for docker to be ready."
|
|
||||||
for i in $(seq "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS"); do
|
|
||||||
if docker ps > /dev/null 2>&1; then
|
|
||||||
echo "Docker is ready."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
updateFile="update.finished"
|
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
"$DIR"/bin/Runner.Listener run $*
|
||||||
|
|
||||||
returnCode=$?
|
returnCode=$?
|
||||||
@@ -47,32 +31,15 @@ elif [[ $returnCode == 2 ]]; then
|
|||||||
"$DIR"/safe_sleep.sh 5
|
"$DIR"/safe_sleep.sh 5
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $returnCode == 3 ]]; then
|
elif [[ $returnCode == 3 ]]; then
|
||||||
# Wait for 30 seconds or for flag file to exists for the runner update process finish
|
# Sleep 5 seconds to wait for the runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
echo "Runner listener exit because of updating, re-launch runner in 5 seconds"
|
||||||
for i in {0..30}; do
|
"$DIR"/safe_sleep.sh 5
|
||||||
if test -f "$updateFile"; then
|
|
||||||
echo "Update finished successfully."
|
|
||||||
rm "$updateFile"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $returnCode == 4 ]]; then
|
elif [[ $returnCode == 4 ]]; then
|
||||||
# Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
# Sleep 5 seconds to wait for the ephemeral runner update process finish
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds"
|
||||||
for i in {0..30}; do
|
"$DIR"/safe_sleep.sh 5
|
||||||
if test -f "$updateFile"; then
|
|
||||||
echo "Update finished successfully."
|
|
||||||
rm "$updateFile"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $returnCode == 5 ]]; then
|
|
||||||
echo "Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
exit 0
|
|
||||||
else
|
else
|
||||||
echo "Exiting with unknown error code: ${returnCode}"
|
echo "Exiting with unknown error code: ${returnCode}"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -9,79 +9,16 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
|
|||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
||||||
run() {
|
# run the helper process which keep the listener alive
|
||||||
# run the helper process which keep the listener alive
|
while :;
|
||||||
while :;
|
do
|
||||||
do
|
"$DIR"/run-helper.sh $*
|
||||||
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
returnCode=$?
|
||||||
"$DIR"/run-helper.sh $*
|
if [[ $returnCode -eq 2 ]]; then
|
||||||
returnCode=$?
|
echo "Restarting runner..."
|
||||||
if [[ $returnCode -eq 2 ]]; then
|
|
||||||
echo "Restarting runner..."
|
|
||||||
else
|
|
||||||
echo "Exiting runner..."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
runWithManualTrap() {
|
|
||||||
# Set job control
|
|
||||||
set -m
|
|
||||||
|
|
||||||
trap 'kill -INT -$PID' INT TERM
|
|
||||||
|
|
||||||
# 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 $* &
|
|
||||||
PID=$!
|
|
||||||
wait $PID
|
|
||||||
returnCode=$?
|
|
||||||
if [[ $returnCode -eq 2 ]]; then
|
|
||||||
echo "Restarting runner..."
|
|
||||||
else
|
|
||||||
echo "Exiting runner..."
|
|
||||||
# Unregister signal handling before exit
|
|
||||||
trap - INT TERM
|
|
||||||
# wait for last parts to be logged
|
|
||||||
wait $PID
|
|
||||||
exit $returnCode
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCerts() {
|
|
||||||
local sudo_prefix=""
|
|
||||||
local user_id=`id -u`
|
|
||||||
|
|
||||||
if [ $user_id -ne 0 ]; then
|
|
||||||
if [[ ! -x "$(command -v sudo)" ]]; then
|
|
||||||
echo "Warning: failed to update certificate store: sudo is required but not found"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
sudo_prefix="sudo"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x "$(command -v update-ca-certificates)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-certificates"
|
|
||||||
elif [[ -x "$(command -v update-ca-trust)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-trust"
|
|
||||||
else
|
else
|
||||||
echo "Warning: failed to update certificate store: update-ca-certificates or update-ca-trust not found. This can happen if you're using a different runner base image."
|
echo "Exiting runner..."
|
||||||
return 1
|
exit 0
|
||||||
fi
|
fi
|
||||||
}
|
done
|
||||||
|
|
||||||
if [[ ! -z "$RUNNER_UPDATE_CA_CERTS" ]]; then
|
|
||||||
updateCerts
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$RUNNER_MANUALLY_TRAP_SIG" ]]; then
|
|
||||||
run $*
|
|
||||||
else
|
|
||||||
runWithManualTrap $*
|
|
||||||
fi
|
|
||||||
|
|||||||
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
|
||||||
264
src/Misc/runnerdotnetruntimeassets
Normal file
264
src/Misc/runnerdotnetruntimeassets
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
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.VisualBasic.Core.dll
|
||||||
|
Microsoft.VisualBasic.dll
|
||||||
|
Microsoft.Win32.Primitives.dll
|
||||||
|
Microsoft.Win32.Registry.dll
|
||||||
|
mscordaccore.dll
|
||||||
|
mscordaccore_amd64_amd64_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,5 @@
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace GitHub.Runner.Common
|
|||||||
new EscapeMapping(token: "%", replacement: "%25"),
|
new EscapeMapping(token: "%", replacement: "%25"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _properties = new(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, string> _properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
public const string Prefix = "##[";
|
public const string Prefix = "##[";
|
||||||
public const string _commandKey = "::";
|
public const string _commandKey = "::";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace GitHub.Runner.Common
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
public enum ActionResult
|
public enum ActionResult
|
||||||
{
|
{
|
||||||
@@ -10,4 +12,4 @@
|
|||||||
|
|
||||||
Skipped = 3
|
Skipped = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(ActionsRunServer))]
|
|
||||||
public interface IActionsRunServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ActionsRunServer : RunnerService, IActionsRunServer
|
|
||||||
{
|
|
||||||
private bool _hasConnection;
|
|
||||||
private VssConnection _connection;
|
|
||||||
private ActionsRunServerHttpClient _actionsRunServerClient;
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
|
||||||
_actionsRunServerClient = _connection.GetClient<ActionsRunServerHttpClient>();
|
|
||||||
_hasConnection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 _actionsRunServerClient.GetJobMessageAsync(id, cancellationToken);
|
|
||||||
}, cancellationToken);
|
|
||||||
|
|
||||||
return jobMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Actions.RunService.WebApi;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using Sdk.RSWebApi.Contracts;
|
|
||||||
using Sdk.WebApi.WebApi.RawClient;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(BrokerServer))]
|
|
||||||
public interface IBrokerServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task<TaskAgentSession> CreateSessionAsync(TaskAgentSession session, CancellationToken cancellationToken);
|
|
||||||
Task DeleteSessionAsync(CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken token);
|
|
||||||
|
|
||||||
Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task ForceRefreshConnection(VssCredentials credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BrokerServer : RunnerService, IBrokerServer
|
|
||||||
{
|
|
||||||
private bool _hasConnection;
|
|
||||||
private Uri _brokerUri;
|
|
||||||
private RawConnection _connection;
|
|
||||||
private BrokerHttpClient _brokerHttpClient;
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUri, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
_brokerUri = serverUri;
|
|
||||||
|
|
||||||
_connection = VssUtil.CreateRawConnection(serverUri, credentials);
|
|
||||||
_brokerHttpClient = await _connection.GetClientAsync<BrokerHttpClient>();
|
|
||||||
_hasConnection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckConnection()
|
|
||||||
{
|
|
||||||
if (!_hasConnection)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"SetConnection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<TaskAgentSession> CreateSessionAsync(TaskAgentSession session, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
var jobMessage = await _brokerHttpClient.CreateSessionAsync(session, cancellationToken);
|
|
||||||
|
|
||||||
return jobMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
var brokerSession = RetryRequest<TaskAgentMessage>(
|
|
||||||
async () => await _brokerHttpClient.GetRunnerMessageAsync(sessionId, version, status, os, architecture, disableUpdate, cancellationToken), cancellationToken, shouldRetry: ShouldRetryException);
|
|
||||||
|
|
||||||
|
|
||||||
return brokerSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteSessionAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
await _brokerHttpClient.DeleteSessionAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
if (_brokerUri != serverUri || !_hasConnection)
|
|
||||||
{
|
|
||||||
return ConnectAsync(serverUri, credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ForceRefreshConnection(VssCredentials credentials)
|
|
||||||
{
|
|
||||||
return ConnectAsync(_brokerUri, credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShouldRetryException(Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is AccessDeniedException ade && ade.ErrorCode == 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using GitHub.DistributedTask.Logging;
|
using GitHub.DistributedTask.Logging;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -18,7 +19,7 @@ namespace GitHub.Runner.Common
|
|||||||
private bool? _isHostedServer;
|
private bool? _isHostedServer;
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public ulong AgentId { get; set; }
|
public int AgentId { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
@@ -50,12 +51,6 @@ namespace GitHub.Runner.Common
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string MonitorSocketAddress { get; set; }
|
public string MonitorSocketAddress { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool UseV2Flow { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string ServerUrlV2 { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsHostedServer
|
public bool IsHostedServer
|
||||||
{
|
{
|
||||||
@@ -80,18 +75,17 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
Uri accountUri = new(this.ServerUrl);
|
Uri accountUri = new Uri(this.ServerUrl);
|
||||||
string repoOrOrgName = string.Empty;
|
string repoOrOrgName = string.Empty;
|
||||||
|
|
||||||
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(this.GitHubUrl))
|
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Uri gitHubUrl = new(this.GitHubUrl);
|
Uri gitHubUrl = new Uri(this.GitHubUrl);
|
||||||
|
|
||||||
// Use the "NWO part" from the GitHub URL path
|
// Use the "NWO part" from the GitHub URL path
|
||||||
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
|
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (string.IsNullOrEmpty(repoOrOrgName))
|
|
||||||
{
|
{
|
||||||
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,6 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly OSPlatform Platform = OSPlatform.OSX;
|
public static readonly OSPlatform Platform = OSPlatform.OSX;
|
||||||
#elif OS_WINDOWS
|
#elif OS_WINDOWS
|
||||||
public static readonly OSPlatform Platform = OSPlatform.Windows;
|
public static readonly OSPlatform Platform = OSPlatform.Windows;
|
||||||
#else
|
|
||||||
public static readonly OSPlatform Platform = OSPlatform.Linux;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if X86
|
#if X86
|
||||||
@@ -79,10 +77,8 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly Architecture PlatformArchitecture = Architecture.X64;
|
public static readonly Architecture PlatformArchitecture = Architecture.X64;
|
||||||
#elif ARM
|
#elif ARM
|
||||||
public static readonly Architecture PlatformArchitecture = Architecture.Arm;
|
public static readonly Architecture PlatformArchitecture = Architecture.Arm;
|
||||||
#elif ARM64
|
#elif ARM64
|
||||||
public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
|
public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
|
||||||
#else
|
|
||||||
public static readonly Architecture PlatformArchitecture = Architecture.X64;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static readonly TimeSpan ExitOnUnloadTimeout = TimeSpan.FromSeconds(30);
|
public static readonly TimeSpan ExitOnUnloadTimeout = TimeSpan.FromSeconds(30);
|
||||||
@@ -108,13 +104,11 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string Token = "token";
|
public static readonly string Token = "token";
|
||||||
public static readonly string PAT = "pat";
|
public static readonly string PAT = "pat";
|
||||||
public static readonly string WindowsLogonPassword = "windowslogonpassword";
|
public static readonly string WindowsLogonPassword = "windowslogonpassword";
|
||||||
public static readonly string JitConfig = "jitconfig";
|
|
||||||
public static string[] Secrets => new[]
|
public static string[] Secrets => new[]
|
||||||
{
|
{
|
||||||
PAT,
|
PAT,
|
||||||
Token,
|
Token,
|
||||||
WindowsLogonPassword,
|
WindowsLogonPassword,
|
||||||
JitConfig,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +127,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string Check = "check";
|
public static readonly string Check = "check";
|
||||||
public static readonly string Commit = "commit";
|
public static readonly string Commit = "commit";
|
||||||
public static readonly string Ephemeral = "ephemeral";
|
public static readonly string Ephemeral = "ephemeral";
|
||||||
public static readonly string GenerateServiceConfig = "generateServiceConfig";
|
|
||||||
public static readonly string Help = "help";
|
public static readonly string Help = "help";
|
||||||
public static readonly string Local = "local";
|
|
||||||
public static readonly string NoDefaultLabels = "no-default-labels";
|
|
||||||
public static readonly string Replace = "replace";
|
public static readonly string Replace = "replace";
|
||||||
public static readonly string DisableUpdate = "disableupdate";
|
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 Once = "once"; // Keep this around since customers still relies on it
|
||||||
@@ -153,37 +144,24 @@ namespace GitHub.Runner.Common
|
|||||||
public const int RetryableError = 2;
|
public const int RetryableError = 2;
|
||||||
public const int RunnerUpdating = 3;
|
public const int RunnerUpdating = 3;
|
||||||
public const int RunOnceRunnerUpdating = 4;
|
public const int RunOnceRunnerUpdating = 4;
|
||||||
public const int SessionConflict = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Features
|
public static class Features
|
||||||
{
|
{
|
||||||
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
||||||
public static readonly string Node16Warning = "DistributedTask.AddWarningToNode16Action";
|
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
|
||||||
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages";
|
|
||||||
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
||||||
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
|
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
||||||
public static readonly Guid TelemetryRecordId = new Guid("11111111-1111-1111-1111-111111111111");
|
|
||||||
public static readonly string WorkerCrash = "WORKER_CRASH";
|
public static readonly string WorkerCrash = "WORKER_CRASH";
|
||||||
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
||||||
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
||||||
public static readonly string ResultsUploadFailure = "RESULTS_UPLOAD_FAILURE";
|
|
||||||
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 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/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
||||||
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
||||||
public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
|
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: {0}";
|
||||||
public static readonly string DetectedNodeAfterEndOfLifeMessage = "Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: {0}. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.";
|
|
||||||
public static readonly string DeprecatedNodeDetectedAfterEndOfLifeActions = "DeprecatedNodeActionsMessageWarnings";
|
|
||||||
public static readonly string DeprecatedNodeVersion = "node16";
|
|
||||||
public static readonly string EnforcedNode12DetectedAfterEndOfLife = "The following actions uses node12 which is deprecated and will be forced to run on node16: {0}. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/";
|
|
||||||
public static readonly string EnforcedNode12DetectedAfterEndOfLifeEnvVariable = "Node16ForceActionsWarnings";
|
|
||||||
public static readonly string EnforcedNode16DetectedAfterEndOfLife = "The following actions use a deprecated Node.js version and will be forced to run on node20: {0}. For more info: https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/";
|
|
||||||
public static readonly string EnforcedNode16DetectedAfterEndOfLifeEnvVariable = "Node20ForceActionsWarnings";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RunnerEvent
|
public static class RunnerEvent
|
||||||
@@ -255,7 +233,6 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
|
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
|
||||||
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
||||||
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";
|
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";
|
||||||
public static readonly string ManualForceActionsToNode20 = "FORCE_JAVASCRIPT_ACTIONS_TO_NODE20";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Agent
|
public static class Agent
|
||||||
@@ -263,11 +240,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string ToolsDirectory = "agent.ToolsDirectory";
|
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.
|
// 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 ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION";
|
||||||
public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION";
|
|
||||||
public static readonly string PrintLogToStdout = "ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT";
|
|
||||||
public static readonly string ActionArchiveCacheDirectory = "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE";
|
|
||||||
public static readonly string ManualForceActionsToNode20 = "FORCE_JAVASCRIPT_ACTIONS_TO_NODE20";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class System
|
public static class System
|
||||||
@@ -278,20 +251,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string AccessToken = "system.accessToken";
|
public static readonly string AccessToken = "system.accessToken";
|
||||||
public static readonly string Culture = "system.culture";
|
public static readonly string Culture = "system.culture";
|
||||||
public static readonly string PhaseDisplayName = "system.phaseDisplayName";
|
public static readonly string PhaseDisplayName = "system.phaseDisplayName";
|
||||||
public static readonly string JobRequestType = "system.jobRequestType";
|
|
||||||
public static readonly string OrchestrationId = "system.orchestrationId";
|
|
||||||
public static readonly string TestDotNet8Compatibility = "system.testDotNet8Compatibility";
|
|
||||||
public static readonly string DotNet8CompatibilityOutputLength = "system.dotNet8CompatibilityOutputLength";
|
|
||||||
public static readonly string DotNet8CompatibilityOutputPattern = "system.dotNet8CompatibilityOutputPattern";
|
|
||||||
public static readonly string DotNet8CompatibilityWarning = "system.dotNet8CompatibilityWarning";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,5 @@
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -14,7 +15,7 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public sealed class ExtensionManager : RunnerService, IExtensionManager
|
public sealed class ExtensionManager : RunnerService, IExtensionManager
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<Type, List<IExtension>> _cache = new();
|
private readonly ConcurrentDictionary<Type, List<IExtension>> _cache = new ConcurrentDictionary<Type, List<IExtension>>();
|
||||||
|
|
||||||
public List<T> GetExtensions<T>() where T : class, IExtension
|
public List<T> GetExtensions<T>() where T : class, IExtension
|
||||||
{
|
{
|
||||||
@@ -60,8 +61,6 @@ namespace GitHub.Runner.Common
|
|||||||
Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker");
|
Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, 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.CreateStepSummaryCommand, Runner.Worker");
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateFileCommand, Runner.Worker");
|
|
||||||
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputFileCommand, Runner.Worker");
|
|
||||||
break;
|
break;
|
||||||
case "GitHub.Runner.Listener.Check.ICheckExtension":
|
case "GitHub.Runner.Listener.Check.ICheckExtension":
|
||||||
Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener");
|
Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener");
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ namespace GitHub.Runner.Common
|
|||||||
private static int _defaultLogRetentionDays = 30;
|
private static int _defaultLogRetentionDays = 30;
|
||||||
private static int[] _vssHttpMethodEventIds = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 24 };
|
private static int[] _vssHttpMethodEventIds = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 24 };
|
||||||
private static int[] _vssHttpCredentialEventIds = new int[] { 11, 13, 14, 15, 16, 17, 18, 20, 21, 22, 27, 29 };
|
private static int[] _vssHttpCredentialEventIds = new int[] { 11, 13, 14, 15, 16, 17, 18, 20, 21, 22, 27, 29 };
|
||||||
private readonly ConcurrentDictionary<Type, object> _serviceInstances = new();
|
private readonly ConcurrentDictionary<Type, object> _serviceInstances = new ConcurrentDictionary<Type, object>();
|
||||||
private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new();
|
private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new ConcurrentDictionary<Type, Type>();
|
||||||
private readonly ISecretMasker _secretMasker = new SecretMasker();
|
private readonly ISecretMasker _secretMasker = new SecretMasker();
|
||||||
private readonly List<ProductInfoHeaderValue> _userAgents = new() { new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version) };
|
private readonly List<ProductInfoHeaderValue> _userAgents = new List<ProductInfoHeaderValue>() { new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version) };
|
||||||
private CancellationTokenSource _runnerShutdownTokenSource = new();
|
private CancellationTokenSource _runnerShutdownTokenSource = new CancellationTokenSource();
|
||||||
private object _perfLock = new();
|
private object _perfLock = new object();
|
||||||
private Tracing _trace;
|
private Tracing _trace;
|
||||||
private Tracing _actionsHttpTrace;
|
private Tracing _actionsHttpTrace;
|
||||||
private Tracing _netcoreHttpTrace;
|
private Tracing _netcoreHttpTrace;
|
||||||
@@ -66,7 +66,7 @@ namespace GitHub.Runner.Common
|
|||||||
private IDisposable _diagListenerSubscription;
|
private IDisposable _diagListenerSubscription;
|
||||||
private StartupType _startupType;
|
private StartupType _startupType;
|
||||||
private string _perfFile;
|
private string _perfFile;
|
||||||
private RunnerWebProxy _webProxy = new();
|
private RunnerWebProxy _webProxy = new RunnerWebProxy();
|
||||||
|
|
||||||
public event EventHandler Unloading;
|
public event EventHandler Unloading;
|
||||||
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
|
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
|
||||||
@@ -94,13 +94,6 @@ namespace GitHub.Runner.Common
|
|||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPreAmpersandEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPreAmpersandEscape);
|
||||||
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPostAmpersandEscape);
|
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPostAmpersandEscape);
|
||||||
|
|
||||||
// Create StdoutTraceListener if ENV is set
|
|
||||||
StdoutTraceListener stdoutTraceListener = null;
|
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Agent.PrintLogToStdout)))
|
|
||||||
{
|
|
||||||
stdoutTraceListener = new StdoutTraceListener(hostType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the trace manager.
|
// Create the trace manager.
|
||||||
if (string.IsNullOrEmpty(logFile))
|
if (string.IsNullOrEmpty(logFile))
|
||||||
{
|
{
|
||||||
@@ -120,11 +113,11 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
// this should give us _diag folder under runner root directory
|
// this should give us _diag folder under runner root directory
|
||||||
string diagLogDirectory = Path.Combine(new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).Parent.FullName, Constants.Path.DiagDirectory);
|
string diagLogDirectory = Path.Combine(new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).Parent.FullName, Constants.Path.DiagDirectory);
|
||||||
_traceManager = new TraceManager(new HostTraceListener(diagLogDirectory, hostType, logPageSize, logRetentionDays), stdoutTraceListener, this.SecretMasker);
|
_traceManager = new TraceManager(new HostTraceListener(diagLogDirectory, hostType, logPageSize, logRetentionDays), this.SecretMasker);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_traceManager = new TraceManager(new HostTraceListener(logFile), stdoutTraceListener, this.SecretMasker);
|
_traceManager = new TraceManager(new HostTraceListener(logFile), this.SecretMasker);
|
||||||
}
|
}
|
||||||
|
|
||||||
_trace = GetTrace(nameof(HostContext));
|
_trace = GetTrace(nameof(HostContext));
|
||||||
@@ -200,14 +193,10 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("HttpProxyConfigured", bool.TrueString));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
||||||
{
|
{
|
||||||
_trace.Warning($"Runner is running under insecure mode: HTTPS server certificate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable.");
|
_trace.Warning($"Runner is running under insecure mode: HTTPS server certifcate validation has been turned off by GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY environment variable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
var credFile = GetConfigFile(WellKnownConfigFile.Credentials);
|
||||||
@@ -224,30 +213,12 @@ namespace GitHub.Runner.Common
|
|||||||
var runnerFile = GetConfigFile(WellKnownConfigFile.Runner);
|
var runnerFile = GetConfigFile(WellKnownConfigFile.Runner);
|
||||||
if (File.Exists(runnerFile))
|
if (File.Exists(runnerFile))
|
||||||
{
|
{
|
||||||
var runnerSettings = IOUtil.LoadObject<RunnerSettings>(runnerFile, true);
|
var runnerSettings = IOUtil.LoadObject<RunnerSettings>(runnerFile);
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("RunnerId", runnerSettings.AgentId.ToString(CultureInfo.InvariantCulture)));
|
_userAgents.Add(new ProductInfoHeaderValue("RunnerId", runnerSettings.AgentId.ToString(CultureInfo.InvariantCulture)));
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("GroupId", runnerSettings.PoolId.ToString(CultureInfo.InvariantCulture)));
|
_userAgents.Add(new ProductInfoHeaderValue("GroupId", runnerSettings.PoolId.ToString(CultureInfo.InvariantCulture)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("CommitSHA", BuildConstants.Source.CommitHash));
|
_userAgents.Add(new ProductInfoHeaderValue("CommitSHA", BuildConstants.Source.CommitHash));
|
||||||
|
|
||||||
var extraUserAgent = Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT");
|
|
||||||
if (!string.IsNullOrEmpty(extraUserAgent))
|
|
||||||
{
|
|
||||||
var extraUserAgentSplit = extraUserAgent.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (extraUserAgentSplit.Length != 2)
|
|
||||||
{
|
|
||||||
_trace.Error($"GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT is not in the format of 'name/version'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var extraUserAgentHeader = new ProductInfoHeaderValue(extraUserAgentSplit[0], extraUserAgentSplit[1]);
|
|
||||||
_trace.Info($"Adding extra user agent '{extraUserAgentHeader}' to all HTTP requests.");
|
|
||||||
_userAgents.Add(extraUserAgentHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentProcess = Process.GetCurrentProcess();
|
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("Pid", currentProcess.Id.ToString()));
|
|
||||||
_userAgents.Add(new ProductInfoHeaderValue("CreationTime", Uri.EscapeDataString(DateTime.UtcNow.ToString("O"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDirectory(WellKnownDirectory directory)
|
public string GetDirectory(WellKnownDirectory directory)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -164,7 +165,7 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
if (_enableLogRetention)
|
if (_enableLogRetention)
|
||||||
{
|
{
|
||||||
DirectoryInfo diags = new(_logFileDirectory);
|
DirectoryInfo diags = new DirectoryInfo(_logFileDirectory);
|
||||||
var logs = diags.GetFiles($"{_logFilePrefix}*.log");
|
var logs = diags.GetFiles($"{_logFilePrefix}*.log");
|
||||||
foreach (var log in logs)
|
foreach (var log in logs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
@@ -24,4 +24,4 @@ namespace GitHub.Runner.Common
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Pipes;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
@@ -37,10 +40,10 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
ConnectMonitor(monitorSocketAddress);
|
ConnectMonitor(monitorSocketAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartMonitor(Guid jobId, string accessToken, Uri serverUri)
|
private void StartMonitor(Guid jobId, string accessToken, Uri serverUri)
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(accessToken))
|
if(String.IsNullOrEmpty(accessToken))
|
||||||
{
|
{
|
||||||
Trace.Info("No access token could be retrieved to start the monitor.");
|
Trace.Info("No access token could be retrieved to start the monitor.");
|
||||||
return;
|
return;
|
||||||
@@ -82,7 +85,7 @@ namespace GitHub.Runner.Common
|
|||||||
_monitorSocket.Send(Encoding.UTF8.GetBytes(message));
|
_monitorSocket.Send(Encoding.UTF8.GetBytes(message));
|
||||||
Trace.Info("Finished EndMonitor writing to socket");
|
Trace.Info("Finished EndMonitor writing to socket");
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(2));
|
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Security;
|
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -12,10 +11,9 @@ using System.Threading.Tasks;
|
|||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using GitHub.Services.OAuth;
|
|
||||||
using GitHub.Services.Results.Client;
|
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
using GitHub.Services.WebApi.Utilities.Internal;
|
using GitHub.Services.WebApi.Utilities.Internal;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -180,10 +178,6 @@ namespace GitHub.Runner.Common
|
|||||||
userAgentValues.AddRange(UserAgentUtility.GetDefaultRestUserAgent());
|
userAgentValues.AddRange(UserAgentUtility.GetDefaultRestUserAgent());
|
||||||
userAgentValues.AddRange(HostContext.UserAgents);
|
userAgentValues.AddRange(HostContext.UserAgents);
|
||||||
this._websocketClient.Options.SetRequestHeader("User-Agent", string.Join(" ", userAgentValues.Select(x => x.ToString())));
|
this._websocketClient.Options.SetRequestHeader("User-Agent", string.Join(" ", userAgentValues.Select(x => x.ToString())));
|
||||||
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY")))
|
|
||||||
{
|
|
||||||
this._websocketClient.Options.RemoteCertificateValidationCallback = (_, _, _, _) => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._websocketConnectTask = ConnectWebSocketClient(feedStreamUrl, delay);
|
this._websocketConnectTask = ConnectWebSocketClient(feedStreamUrl, delay);
|
||||||
}
|
}
|
||||||
@@ -204,15 +198,13 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
Trace.Info($"Attempting to start websocket client with delay {delay}.");
|
Trace.Info($"Attempting to start websocket client with delay {delay}.");
|
||||||
await Task.Delay(delay);
|
await Task.Delay(delay);
|
||||||
using var connectTimeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), default(CancellationToken));
|
||||||
await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), connectTimeoutTokenSource.Token);
|
|
||||||
Trace.Info($"Successfully started websocket client.");
|
Trace.Info($"Successfully started websocket client.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Trace.Info("Exception caught during websocket client connect, fallback of HTTP would be used now instead of websocket.");
|
Trace.Info("Exception caught during websocket client connect, fallback of HTTP would be used now instead of websocket.");
|
||||||
Trace.Error(ex);
|
Trace.Error(ex);
|
||||||
this._websocketClient = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +251,7 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
failedAttemptsToPostBatchedLinesByWebsocket++;
|
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.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.Verbose(ex.ToString());
|
Trace.Error(ex);
|
||||||
if (totalBatchedLinesAttemptedByWebsocket > _minWebsocketBatchedLinesCountToConsider)
|
if (totalBatchedLinesAttemptedByWebsocket > _minWebsocketBatchedLinesCountToConsider)
|
||||||
{
|
{
|
||||||
// let's consider failure percentage
|
// let's consider failure percentage
|
||||||
@@ -314,7 +306,6 @@ namespace GitHub.Runner.Common
|
|||||||
return _taskClient.CreateAttachmentAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, type, name, uploadStream, cancellationToken: cancellationToken);
|
return _taskClient.CreateAttachmentAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, type, name, uploadStream, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken)
|
public Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection();
|
CheckConnection();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -15,14 +14,12 @@ namespace GitHub.Runner.Common
|
|||||||
[ServiceLocator(Default = typeof(JobServerQueue))]
|
[ServiceLocator(Default = typeof(JobServerQueue))]
|
||||||
public interface IJobServerQueue : IRunnerService, IThrottlingReporter
|
public interface IJobServerQueue : IRunnerService, IThrottlingReporter
|
||||||
{
|
{
|
||||||
IList<JobTelemetry> JobTelemetries { get; }
|
|
||||||
TaskCompletionSource<int> JobRecordUpdated { get; }
|
TaskCompletionSource<int> JobRecordUpdated { get; }
|
||||||
event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
|
event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
|
||||||
Task ShutdownAsync();
|
Task ShutdownAsync();
|
||||||
void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultsServiceOnly = false);
|
void Start(Pipelines.AgentJobRequestMessage jobRequest);
|
||||||
void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null);
|
void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null);
|
||||||
void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource);
|
void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource);
|
||||||
void QueueResultsUpload(Guid timelineRecordId, string name, string path, string type, bool deleteSource, bool finalize, bool firstBlock, long totalLines);
|
|
||||||
void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord);
|
void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +30,6 @@ namespace GitHub.Runner.Common
|
|||||||
private static readonly TimeSpan _delayForWebConsoleLineDequeue = TimeSpan.FromMilliseconds(500);
|
private static readonly TimeSpan _delayForWebConsoleLineDequeue = TimeSpan.FromMilliseconds(500);
|
||||||
private static readonly TimeSpan _delayForTimelineUpdateDequeue = TimeSpan.FromMilliseconds(500);
|
private static readonly TimeSpan _delayForTimelineUpdateDequeue = TimeSpan.FromMilliseconds(500);
|
||||||
private static readonly TimeSpan _delayForFileUploadDequeue = TimeSpan.FromMilliseconds(1000);
|
private static readonly TimeSpan _delayForFileUploadDequeue = TimeSpan.FromMilliseconds(1000);
|
||||||
private static readonly TimeSpan _delayForResultsUploadDequeue = TimeSpan.FromMilliseconds(1000);
|
|
||||||
|
|
||||||
// Job message information
|
// Job message information
|
||||||
private Guid _scopeIdentifier;
|
private Guid _scopeIdentifier;
|
||||||
@@ -43,47 +39,36 @@ namespace GitHub.Runner.Common
|
|||||||
private Guid _jobTimelineRecordId;
|
private Guid _jobTimelineRecordId;
|
||||||
|
|
||||||
// queue for web console line
|
// queue for web console line
|
||||||
private readonly ConcurrentQueue<ConsoleLineInfo> _webConsoleLineQueue = new();
|
private readonly ConcurrentQueue<ConsoleLineInfo> _webConsoleLineQueue = new ConcurrentQueue<ConsoleLineInfo>();
|
||||||
|
|
||||||
// queue for file upload (log file or attachment)
|
// queue for file upload (log file or attachment)
|
||||||
private readonly ConcurrentQueue<UploadFileInfo> _fileUploadQueue = new();
|
private readonly ConcurrentQueue<UploadFileInfo> _fileUploadQueue = new ConcurrentQueue<UploadFileInfo>();
|
||||||
|
|
||||||
private readonly ConcurrentQueue<ResultsUploadFileInfo> _resultsFileUploadQueue = new();
|
|
||||||
|
|
||||||
// queue for timeline or timeline record update (one queue per timeline)
|
// queue for timeline or timeline record update (one queue per timeline)
|
||||||
private readonly ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>> _timelineUpdateQueue = new();
|
private readonly ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>> _timelineUpdateQueue = new ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>>();
|
||||||
|
|
||||||
// indicate how many timelines we have, we will process _timelineUpdateQueue base on the order of timeline in this list
|
// indicate how many timelines we have, we will process _timelineUpdateQueue base on the order of timeline in this list
|
||||||
private readonly List<Guid> _allTimelines = new();
|
private readonly List<Guid> _allTimelines = new List<Guid>();
|
||||||
|
|
||||||
// bufferd timeline records that fail to update
|
// bufferd timeline records that fail to update
|
||||||
private readonly Dictionary<Guid, List<TimelineRecord>> _bufferedRetryRecords = new();
|
private readonly Dictionary<Guid, List<TimelineRecord>> _bufferedRetryRecords = new Dictionary<Guid, List<TimelineRecord>>();
|
||||||
|
|
||||||
// Task for each queue's dequeue process
|
// Task for each queue's dequeue process
|
||||||
private Task _webConsoleLineDequeueTask;
|
private Task _webConsoleLineDequeueTask;
|
||||||
private Task _fileUploadDequeueTask;
|
private Task _fileUploadDequeueTask;
|
||||||
private Task _resultsUploadDequeueTask;
|
|
||||||
private Task _timelineUpdateDequeueTask;
|
private Task _timelineUpdateDequeueTask;
|
||||||
|
|
||||||
// common
|
// common
|
||||||
private IJobServer _jobServer;
|
private IJobServer _jobServer;
|
||||||
private IResultsServer _resultsServer;
|
|
||||||
private Task[] _allDequeueTasks;
|
private Task[] _allDequeueTasks;
|
||||||
private readonly TaskCompletionSource<int> _jobCompletionSource = new();
|
private readonly TaskCompletionSource<int> _jobCompletionSource = new TaskCompletionSource<int>();
|
||||||
private readonly TaskCompletionSource<int> _jobRecordUpdated = new();
|
private readonly TaskCompletionSource<int> _jobRecordUpdated = new TaskCompletionSource<int>();
|
||||||
private readonly List<JobTelemetry> _jobTelemetries = new();
|
|
||||||
private bool _queueInProcess = false;
|
private bool _queueInProcess = false;
|
||||||
private bool _resultsServiceOnly = false;
|
|
||||||
private int _resultsServiceExceptionsCount = 0;
|
|
||||||
private Stopwatch _resultsUploadTimer = new();
|
|
||||||
private Stopwatch _actionsUploadTimer = new();
|
|
||||||
|
|
||||||
public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated;
|
public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated;
|
||||||
|
|
||||||
public event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
|
public event EventHandler<ThrottlingEventArgs> JobServerQueueThrottling;
|
||||||
|
|
||||||
public IList<JobTelemetry> JobTelemetries => _jobTelemetries;
|
|
||||||
|
|
||||||
// Web console dequeue will start with process queue every 250ms for the first 60*4 times (~60 seconds).
|
// Web console dequeue will start with process queue every 250ms for the first 60*4 times (~60 seconds).
|
||||||
// Then the dequeue will happen every 500ms.
|
// Then the dequeue will happen every 500ms.
|
||||||
// In this way, customer still can get instance live console output on job start,
|
// In this way, customer still can get instance live console output on job start,
|
||||||
@@ -94,56 +79,19 @@ namespace GitHub.Runner.Common
|
|||||||
private bool _webConsoleLineAggressiveDequeue = true;
|
private bool _webConsoleLineAggressiveDequeue = true;
|
||||||
private bool _firstConsoleOutputs = true;
|
private bool _firstConsoleOutputs = true;
|
||||||
|
|
||||||
private bool _resultsClientInitiated = false;
|
|
||||||
private bool _enableTelemetry = false;
|
|
||||||
private delegate Task ResultsFileUploadHandler(ResultsUploadFileInfo file);
|
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
_jobServer = hostContext.GetService<IJobServer>();
|
_jobServer = hostContext.GetService<IJobServer>();
|
||||||
_resultsServer = hostContext.GetService<IResultsServer>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(Pipelines.AgentJobRequestMessage jobRequest, bool resultsServiceOnly = false)
|
public void Start(Pipelines.AgentJobRequestMessage jobRequest)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
_resultsServiceOnly = resultsServiceOnly;
|
|
||||||
|
|
||||||
var serviceEndPoint = jobRequest.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
var serviceEndPoint = jobRequest.Resources.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (!resultsServiceOnly)
|
_jobServer.InitializeWebsocketClient(serviceEndPoint);
|
||||||
{
|
|
||||||
_jobServer.InitializeWebsocketClient(serviceEndPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This code is usually wrapped by an instance of IExecutionContext which isn't available here.
|
|
||||||
jobRequest.Variables.TryGetValue("system.github.results_endpoint", out VariableValue resultsEndpointVariable);
|
|
||||||
var resultsReceiverEndpoint = resultsEndpointVariable?.Value;
|
|
||||||
|
|
||||||
if (serviceEndPoint?.Authorization != null &&
|
|
||||||
serviceEndPoint.Authorization.Parameters.TryGetValue("AccessToken", out var accessToken) &&
|
|
||||||
!string.IsNullOrEmpty(accessToken) &&
|
|
||||||
!string.IsNullOrEmpty(resultsReceiverEndpoint))
|
|
||||||
{
|
|
||||||
string liveConsoleFeedUrl = null;
|
|
||||||
Trace.Info("Initializing results client");
|
|
||||||
if (resultsServiceOnly
|
|
||||||
&& serviceEndPoint.Data.TryGetValue("FeedStreamUrl", out var feedStreamUrl)
|
|
||||||
&& !string.IsNullOrEmpty(feedStreamUrl))
|
|
||||||
{
|
|
||||||
liveConsoleFeedUrl = feedStreamUrl;
|
|
||||||
}
|
|
||||||
jobRequest.Variables.TryGetValue("system.github.results_upload_with_sdk", out VariableValue resultsUseSdkVariable);
|
|
||||||
_resultsServer.InitializeResultsClient(new Uri(resultsReceiverEndpoint), liveConsoleFeedUrl, accessToken, StringUtil.ConvertToBoolean(resultsUseSdkVariable?.Value));
|
|
||||||
_resultsClientInitiated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable telemetry if we have both results service and actions service
|
|
||||||
if (_resultsClientInitiated && !_resultsServiceOnly)
|
|
||||||
{
|
|
||||||
_enableTelemetry = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_queueInProcess)
|
if (_queueInProcess)
|
||||||
{
|
{
|
||||||
@@ -172,13 +120,10 @@ namespace GitHub.Runner.Common
|
|||||||
Trace.Info("Start process file upload queue.");
|
Trace.Info("Start process file upload queue.");
|
||||||
_fileUploadDequeueTask = ProcessFilesUploadQueueAsync();
|
_fileUploadDequeueTask = ProcessFilesUploadQueueAsync();
|
||||||
|
|
||||||
Trace.Info("Start results file upload queue.");
|
|
||||||
_resultsUploadDequeueTask = ProcessResultsUploadQueueAsync();
|
|
||||||
|
|
||||||
Trace.Info("Start process timeline update queue.");
|
Trace.Info("Start process timeline update queue.");
|
||||||
_timelineUpdateDequeueTask = ProcessTimelinesUpdateQueueAsync();
|
_timelineUpdateDequeueTask = ProcessTimelinesUpdateQueueAsync();
|
||||||
|
|
||||||
_allDequeueTasks = new Task[] { _webConsoleLineDequeueTask, _fileUploadDequeueTask, _timelineUpdateDequeueTask, _resultsUploadDequeueTask };
|
_allDequeueTasks = new Task[] { _webConsoleLineDequeueTask, _fileUploadDequeueTask, _timelineUpdateDequeueTask };
|
||||||
_queueInProcess = true;
|
_queueInProcess = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,10 +154,6 @@ namespace GitHub.Runner.Common
|
|||||||
await ProcessFilesUploadQueueAsync(runOnce: true);
|
await ProcessFilesUploadQueueAsync(runOnce: true);
|
||||||
Trace.Info("File upload queue drained.");
|
Trace.Info("File upload queue drained.");
|
||||||
|
|
||||||
Trace.Verbose("Draining results upload queue.");
|
|
||||||
await ProcessResultsUploadQueueAsync(runOnce: true);
|
|
||||||
Trace.Info("Results upload queue drained.");
|
|
||||||
|
|
||||||
// ProcessTimelinesUpdateQueueAsync() will throw exception during shutdown
|
// ProcessTimelinesUpdateQueueAsync() will throw exception during shutdown
|
||||||
// if there is any timeline records that failed to update contains output variabls.
|
// if there is any timeline records that failed to update contains output variabls.
|
||||||
Trace.Verbose("Draining timeline update queue.");
|
Trace.Verbose("Draining timeline update queue.");
|
||||||
@@ -222,16 +163,7 @@ namespace GitHub.Runner.Common
|
|||||||
Trace.Info($"Disposing job server ...");
|
Trace.Info($"Disposing job server ...");
|
||||||
await _jobServer.DisposeAsync();
|
await _jobServer.DisposeAsync();
|
||||||
|
|
||||||
Trace.Info($"Disposing results server ...");
|
|
||||||
await _resultsServer.DisposeAsync();
|
|
||||||
|
|
||||||
Trace.Info("All queue process tasks have been stopped, and all queues are drained.");
|
Trace.Info("All queue process tasks have been stopped, and all queues are drained.");
|
||||||
if (_enableTelemetry)
|
|
||||||
{
|
|
||||||
var uploadTimeComparison = $"Actions upload time: {_actionsUploadTimer.ElapsedMilliseconds} ms, Result upload time: {_resultsUploadTimer.ElapsedMilliseconds} ms";
|
|
||||||
Trace.Info(uploadTimeComparison);
|
|
||||||
_jobTelemetries.Add(new JobTelemetry() { Type = JobTelemetryType.General, Message = uploadTimeComparison });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
|
public void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber)
|
||||||
@@ -272,45 +204,6 @@ namespace GitHub.Runner.Common
|
|||||||
_fileUploadQueue.Enqueue(newFile);
|
_fileUploadQueue.Enqueue(newFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueResultsUpload(Guid timelineRecordId, string name, string path, string type, bool deleteSource, bool finalize, bool firstBlock, long totalLines)
|
|
||||||
{
|
|
||||||
if (!_resultsClientInitiated)
|
|
||||||
{
|
|
||||||
Trace.Verbose("Skipping results upload");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (deleteSource)
|
|
||||||
{
|
|
||||||
File.Delete(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Info("Catch exception during delete skipped results upload file.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// all parameter not null, file path exist.
|
|
||||||
var newFile = new ResultsUploadFileInfo()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Path = path,
|
|
||||||
Type = type,
|
|
||||||
PlanId = _planId.ToString(),
|
|
||||||
JobId = _jobTimelineRecordId.ToString(),
|
|
||||||
RecordId = timelineRecordId,
|
|
||||||
DeleteSource = deleteSource,
|
|
||||||
Finalize = finalize,
|
|
||||||
FirstBlock = firstBlock,
|
|
||||||
TotalLines = totalLines,
|
|
||||||
};
|
|
||||||
|
|
||||||
Trace.Verbose("Enqueue results file upload queue: file '{0}' attach to job {1} step {2}", newFile.Path, _jobTimelineRecordId, timelineRecordId);
|
|
||||||
_resultsFileUploadQueue.Enqueue(newFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord)
|
public void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord)
|
||||||
{
|
{
|
||||||
ArgUtil.NotEmpty(timelineId, nameof(timelineId));
|
ArgUtil.NotEmpty(timelineId, nameof(timelineId));
|
||||||
@@ -344,8 +237,8 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Group consolelines by timeline record of each step
|
// Group consolelines by timeline record of each step
|
||||||
Dictionary<Guid, List<TimelineRecordLogLine>> stepsConsoleLines = new();
|
Dictionary<Guid, List<TimelineRecordLogLine>> stepsConsoleLines = new Dictionary<Guid, List<TimelineRecordLogLine>>();
|
||||||
List<Guid> stepRecordIds = new(); // We need to keep lines in order
|
List<Guid> stepRecordIds = new List<Guid>(); // We need to keep lines in order
|
||||||
int linesCounter = 0;
|
int linesCounter = 0;
|
||||||
ConsoleLineInfo lineInfo;
|
ConsoleLineInfo lineInfo;
|
||||||
while (_webConsoleLineQueue.TryDequeue(out lineInfo))
|
while (_webConsoleLineQueue.TryDequeue(out lineInfo))
|
||||||
@@ -371,7 +264,7 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
// Split consolelines into batch, each batch will container at most 100 lines.
|
// Split consolelines into batch, each batch will container at most 100 lines.
|
||||||
int batchCounter = 0;
|
int batchCounter = 0;
|
||||||
List<List<TimelineRecordLogLine>> batchedLines = new();
|
List<List<TimelineRecordLogLine>> batchedLines = new List<List<TimelineRecordLogLine>>();
|
||||||
foreach (var line in stepsConsoleLines[stepRecordId])
|
foreach (var line in stepsConsoleLines[stepRecordId])
|
||||||
{
|
{
|
||||||
var currentBatch = batchedLines.ElementAtOrDefault(batchCounter);
|
var currentBatch = batchedLines.ElementAtOrDefault(batchCounter);
|
||||||
@@ -406,17 +299,10 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Give at most 60s for each request.
|
// Give at most 60s for each request.
|
||||||
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
|
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
|
||||||
{
|
{
|
||||||
if (_resultsServiceOnly)
|
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
|
||||||
{
|
|
||||||
await _resultsServer.AppendLiveConsoleFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_firstConsoleOutputs)
|
if (_firstConsoleOutputs)
|
||||||
@@ -452,7 +338,7 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
|
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
|
||||||
{
|
{
|
||||||
List<UploadFileInfo> filesToUpload = new();
|
List<UploadFileInfo> filesToUpload = new List<UploadFileInfo>();
|
||||||
UploadFileInfo dequeueFile;
|
UploadFileInfo dequeueFile;
|
||||||
while (_fileUploadQueue.TryDequeue(out dequeueFile))
|
while (_fileUploadQueue.TryDequeue(out dequeueFile))
|
||||||
{
|
{
|
||||||
@@ -477,10 +363,6 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_enableTelemetry)
|
|
||||||
{
|
|
||||||
_actionsUploadTimer.Start();
|
|
||||||
}
|
|
||||||
await UploadFile(file);
|
await UploadFile(file);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -496,13 +378,6 @@ namespace GitHub.Runner.Common
|
|||||||
// _fileUploadQueue.Enqueue(file);
|
// _fileUploadQueue.Enqueue(file);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_enableTelemetry)
|
|
||||||
{
|
|
||||||
_actionsUploadTimer.Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Info("Try to upload {0} log files or attachments, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount);
|
Trace.Info("Try to upload {0} log files or attachments, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount);
|
||||||
@@ -519,122 +394,17 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessResultsUploadQueueAsync(bool runOnce = false)
|
|
||||||
{
|
|
||||||
Trace.Info("Starting results-based upload queue...");
|
|
||||||
|
|
||||||
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
|
|
||||||
{
|
|
||||||
List<ResultsUploadFileInfo> filesToUpload = new();
|
|
||||||
ResultsUploadFileInfo dequeueFile;
|
|
||||||
while (_resultsFileUploadQueue.TryDequeue(out dequeueFile))
|
|
||||||
{
|
|
||||||
filesToUpload.Add(dequeueFile);
|
|
||||||
// process at most 10 file uploads.
|
|
||||||
if (!runOnce && filesToUpload.Count > 10)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filesToUpload.Count > 0)
|
|
||||||
{
|
|
||||||
if (runOnce)
|
|
||||||
{
|
|
||||||
Trace.Info($"Uploading {filesToUpload.Count} file(s) in one shot through results service.");
|
|
||||||
}
|
|
||||||
|
|
||||||
int errorCount = 0;
|
|
||||||
foreach (var file in filesToUpload)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_enableTelemetry)
|
|
||||||
{
|
|
||||||
_resultsUploadTimer.Start();
|
|
||||||
}
|
|
||||||
if (String.Equals(file.Type, ChecksAttachmentType.StepSummary, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
await UploadSummaryFile(file);
|
|
||||||
}
|
|
||||||
if (string.Equals(file.Type, CoreAttachmentType.ResultsDiagnosticLog, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
await UploadResultsDiagnosticLogsFile(file);
|
|
||||||
}
|
|
||||||
else if (String.Equals(file.Type, CoreAttachmentType.ResultsLog, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (file.RecordId != _jobTimelineRecordId)
|
|
||||||
{
|
|
||||||
Trace.Info($"Got a step log file to send to results service.");
|
|
||||||
await UploadResultsStepLogFile(file);
|
|
||||||
}
|
|
||||||
else if (file.RecordId == _jobTimelineRecordId)
|
|
||||||
{
|
|
||||||
Trace.Info($"Got a job log file to send to results service.");
|
|
||||||
await UploadResultsJobLogFile(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Info("Catch exception during file upload to results, keep going since the process is best effort.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
errorCount++;
|
|
||||||
_resultsServiceExceptionsCount++;
|
|
||||||
// If we hit any exceptions uploading to Results, let's skip any additional uploads to Results unless Results is serving logs
|
|
||||||
if (!_resultsServiceOnly && _resultsServiceExceptionsCount > 3)
|
|
||||||
{
|
|
||||||
_resultsClientInitiated = false;
|
|
||||||
SendResultsTelemetry(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_enableTelemetry)
|
|
||||||
{
|
|
||||||
_resultsUploadTimer.Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Trace.Info("Tried to upload {0} file(s) to results, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runOnce)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.Delay(_delayForResultsUploadDequeue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SendResultsTelemetry(Exception ex)
|
|
||||||
{
|
|
||||||
var issue = new Issue() { Type = IssueType.Warning, Message = $"Caught exception with results. {HostContext.SecretMasker.MaskSecrets(ex.Message)}" };
|
|
||||||
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.ResultsUploadFailure;
|
|
||||||
|
|
||||||
var telemetryRecord = new TimelineRecord()
|
|
||||||
{
|
|
||||||
Id = Constants.Runner.TelemetryRecordId,
|
|
||||||
};
|
|
||||||
telemetryRecord.Issues.Add(issue);
|
|
||||||
QueueTimelineRecordUpdate(_jobTimelineId, telemetryRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ProcessTimelinesUpdateQueueAsync(bool runOnce = false)
|
private async Task ProcessTimelinesUpdateQueueAsync(bool runOnce = false)
|
||||||
{
|
{
|
||||||
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
|
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
|
||||||
{
|
{
|
||||||
List<PendingTimelineRecord> pendingUpdates = new();
|
List<PendingTimelineRecord> pendingUpdates = new List<PendingTimelineRecord>();
|
||||||
foreach (var timeline in _allTimelines)
|
foreach (var timeline in _allTimelines)
|
||||||
{
|
{
|
||||||
ConcurrentQueue<TimelineRecord> recordQueue;
|
ConcurrentQueue<TimelineRecord> recordQueue;
|
||||||
if (_timelineUpdateQueue.TryGetValue(timeline, out recordQueue))
|
if (_timelineUpdateQueue.TryGetValue(timeline, out recordQueue))
|
||||||
{
|
{
|
||||||
List<TimelineRecord> records = new();
|
List<TimelineRecord> records = new List<TimelineRecord>();
|
||||||
TimelineRecord record;
|
TimelineRecord record;
|
||||||
while (recordQueue.TryDequeue(out record))
|
while (recordQueue.TryDequeue(out record))
|
||||||
{
|
{
|
||||||
@@ -656,7 +426,7 @@ namespace GitHub.Runner.Common
|
|||||||
// we need track whether we have new sub-timeline been created on the last run.
|
// we need track whether we have new sub-timeline been created on the last run.
|
||||||
// if so, we need continue update timeline record even we on the last run.
|
// if so, we need continue update timeline record even we on the last run.
|
||||||
bool pendingSubtimelineUpdate = false;
|
bool pendingSubtimelineUpdate = false;
|
||||||
List<Exception> mainTimelineRecordsUpdateErrors = new();
|
List<Exception> mainTimelineRecordsUpdateErrors = new List<Exception>();
|
||||||
if (pendingUpdates.Count > 0)
|
if (pendingUpdates.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var update in pendingUpdates)
|
foreach (var update in pendingUpdates)
|
||||||
@@ -671,7 +441,7 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
foreach (var detailTimeline in update.PendingRecords.Where(r => r.Details != null))
|
foreach (var detailTimeline in update.PendingRecords.Where(r => r.Details != null))
|
||||||
{
|
{
|
||||||
if (!_resultsServiceOnly && !_allTimelines.Contains(detailTimeline.Details.Id))
|
if (!_allTimelines.Contains(detailTimeline.Details.Id))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -693,31 +463,7 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_resultsServiceOnly)
|
await _jobServer.UpdateTimelineRecordsAsync(_scopeIdentifier, _hubName, _planId, update.TimelineId, update.PendingRecords, default(CancellationToken));
|
||||||
{
|
|
||||||
await _jobServer.UpdateTimelineRecordsAsync(_scopeIdentifier, _hubName, _planId, update.TimelineId, update.PendingRecords, default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_resultsClientInitiated)
|
|
||||||
{
|
|
||||||
await _resultsServer.UpdateResultsWorkflowStepsAsync(_scopeIdentifier, _hubName, _planId, update.TimelineId, update.PendingRecords, default(CancellationToken));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Trace.Info("Catch exception during update steps, skip update Results.");
|
|
||||||
Trace.Error(e);
|
|
||||||
_resultsServiceExceptionsCount++;
|
|
||||||
// If we hit any exceptions uploading to Results, let's skip any additional uploads to Results unless Results is serving logs
|
|
||||||
if (!_resultsServiceOnly && _resultsServiceExceptionsCount > 3)
|
|
||||||
{
|
|
||||||
_resultsClientInitiated = false;
|
|
||||||
SendResultsTelemetry(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_bufferedRetryRecords.Remove(update.TimelineId))
|
if (_bufferedRetryRecords.Remove(update.TimelineId))
|
||||||
{
|
{
|
||||||
Trace.Verbose("Cleanup buffered timeline record for timeline: {0}.", update.TimelineId);
|
Trace.Verbose("Cleanup buffered timeline record for timeline: {0}.", update.TimelineId);
|
||||||
@@ -783,7 +529,7 @@ namespace GitHub.Runner.Common
|
|||||||
return timelineRecords;
|
return timelineRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<Guid, TimelineRecord> dict = new();
|
Dictionary<Guid, TimelineRecord> dict = new Dictionary<Guid, TimelineRecord>();
|
||||||
foreach (TimelineRecord rec in timelineRecords)
|
foreach (TimelineRecord rec in timelineRecords)
|
||||||
{
|
{
|
||||||
if (rec == null)
|
if (rec == null)
|
||||||
@@ -809,17 +555,17 @@ namespace GitHub.Runner.Common
|
|||||||
timelineRecord.State = rec.State ?? timelineRecord.State;
|
timelineRecord.State = rec.State ?? timelineRecord.State;
|
||||||
timelineRecord.WorkerName = rec.WorkerName ?? timelineRecord.WorkerName;
|
timelineRecord.WorkerName = rec.WorkerName ?? timelineRecord.WorkerName;
|
||||||
|
|
||||||
if (rec.ErrorCount > 0)
|
if (rec.ErrorCount != null && rec.ErrorCount > 0)
|
||||||
{
|
{
|
||||||
timelineRecord.ErrorCount = rec.ErrorCount;
|
timelineRecord.ErrorCount = rec.ErrorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec.WarningCount > 0)
|
if (rec.WarningCount != null && rec.WarningCount > 0)
|
||||||
{
|
{
|
||||||
timelineRecord.WarningCount = rec.WarningCount;
|
timelineRecord.WarningCount = rec.WarningCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec.NoticeCount > 0)
|
if (rec.NoticeCount != null && rec.NoticeCount > 0)
|
||||||
{
|
{
|
||||||
timelineRecord.NoticeCount = rec.NoticeCount;
|
timelineRecord.NoticeCount = rec.NoticeCount;
|
||||||
}
|
}
|
||||||
@@ -850,7 +596,7 @@ namespace GitHub.Runner.Common
|
|||||||
foreach (var record in mergedRecords)
|
foreach (var record in mergedRecords)
|
||||||
{
|
{
|
||||||
Trace.Verbose($" Record: t={record.RecordType}, n={record.Name}, s={record.State}, st={record.StartTime}, {record.PercentComplete}%, ft={record.FinishTime}, r={record.Result}: {record.CurrentOperation}");
|
Trace.Verbose($" Record: t={record.RecordType}, n={record.Name}, s={record.State}, st={record.StartTime}, {record.PercentComplete}%, ft={record.FinishTime}, r={record.Result}: {record.CurrentOperation}");
|
||||||
if (record.Issues != null)
|
if (record.Issues != null && record.Issues.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var issue in record.Issues)
|
foreach (var issue in record.Issues)
|
||||||
{
|
{
|
||||||
@@ -860,7 +606,7 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record.Variables != null)
|
if (record.Variables != null && record.Variables.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var variable in record.Variables)
|
foreach (var variable in record.Variables)
|
||||||
{
|
{
|
||||||
@@ -877,30 +623,27 @@ namespace GitHub.Runner.Common
|
|||||||
bool uploadSucceed = false;
|
bool uploadSucceed = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_resultsServiceOnly)
|
if (String.Equals(file.Type, CoreAttachmentType.Log, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (String.Equals(file.Type, CoreAttachmentType.Log, StringComparison.OrdinalIgnoreCase))
|
// Create the log
|
||||||
|
var taskLog = await _jobServer.CreateLogAsync(_scopeIdentifier, _hubName, _planId, new TaskLog(String.Format(@"logs\{0:D}", file.TimelineRecordId)), default(CancellationToken));
|
||||||
|
|
||||||
|
// Upload the contents
|
||||||
|
using (FileStream fs = File.Open(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
{
|
{
|
||||||
// Create the log
|
var logUploaded = await _jobServer.AppendLogContentAsync(_scopeIdentifier, _hubName, _planId, taskLog.Id, fs, default(CancellationToken));
|
||||||
var taskLog = await _jobServer.CreateLogAsync(_scopeIdentifier, _hubName, _planId, new TaskLog(String.Format(@"logs\{0:D}", file.TimelineRecordId)), default(CancellationToken));
|
|
||||||
|
|
||||||
// Upload the contents
|
|
||||||
using (FileStream fs = File.Open(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
{
|
|
||||||
var logUploaded = await _jobServer.AppendLogContentAsync(_scopeIdentifier, _hubName, _planId, taskLog.Id, fs, default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new record and only set the Log field
|
|
||||||
var attachmentUpdataRecord = new TimelineRecord() { Id = file.TimelineRecordId, Log = taskLog };
|
|
||||||
QueueTimelineRecordUpdate(file.TimelineId, attachmentUpdataRecord);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// Create a new record and only set the Log field
|
||||||
|
var attachmentUpdataRecord = new TimelineRecord() { Id = file.TimelineRecordId, Log = taskLog };
|
||||||
|
QueueTimelineRecordUpdate(file.TimelineId, attachmentUpdataRecord);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create attachment
|
||||||
|
using (FileStream fs = File.Open(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
{
|
{
|
||||||
// Create attachment
|
var result = await _jobServer.CreateAttachmentAsync(_scopeIdentifier, _hubName, _planId, file.TimelineId, file.TimelineRecordId, file.Type, file.Name, fs, default(CancellationToken));
|
||||||
using (FileStream fs = File.Open(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
{
|
|
||||||
var result = await _jobServer.CreateAttachmentAsync(_scopeIdentifier, _hubName, _planId, file.TimelineId, file.TimelineRecordId, file.Type, file.Name, fs, default(CancellationToken));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,80 +665,6 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UploadSummaryFile(ResultsUploadFileInfo file)
|
|
||||||
{
|
|
||||||
Trace.Info($"Starting to upload summary file to results service {file.Name}, {file.Path}");
|
|
||||||
ResultsFileUploadHandler summaryHandler = async (file) =>
|
|
||||||
{
|
|
||||||
await _resultsServer.CreateResultsStepSummaryAsync(file.PlanId, file.JobId, file.RecordId, file.Path, CancellationToken.None);
|
|
||||||
};
|
|
||||||
|
|
||||||
await UploadResultsFile(file, summaryHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadResultsDiagnosticLogsFile(ResultsUploadFileInfo file)
|
|
||||||
{
|
|
||||||
Trace.Info($"Starting to upload diagnostic logs file to results service {file.Name}, {file.Path}");
|
|
||||||
ResultsFileUploadHandler diagnosticLogsHandler = async (file) =>
|
|
||||||
{
|
|
||||||
await _resultsServer.CreateResultsDiagnosticLogsAsync(file.PlanId, file.JobId, file.Path, CancellationToken.None);
|
|
||||||
};
|
|
||||||
|
|
||||||
await UploadResultsFile(file, diagnosticLogsHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadResultsStepLogFile(ResultsUploadFileInfo file)
|
|
||||||
{
|
|
||||||
Trace.Info($"Starting upload of step log file to results service {file.Name}, {file.Path}");
|
|
||||||
ResultsFileUploadHandler stepLogHandler = async (file) =>
|
|
||||||
{
|
|
||||||
await _resultsServer.CreateResultsStepLogAsync(file.PlanId, file.JobId, file.RecordId, file.Path, file.Finalize, file.FirstBlock, file.TotalLines, CancellationToken.None);
|
|
||||||
};
|
|
||||||
|
|
||||||
await UploadResultsFile(file, stepLogHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadResultsJobLogFile(ResultsUploadFileInfo file)
|
|
||||||
{
|
|
||||||
Trace.Info($"Starting upload of job log file to results service {file.Name}, {file.Path}");
|
|
||||||
ResultsFileUploadHandler jobLogHandler = async (file) =>
|
|
||||||
{
|
|
||||||
await _resultsServer.CreateResultsJobLogAsync(file.PlanId, file.JobId, file.Path, file.Finalize, file.FirstBlock, file.TotalLines, CancellationToken.None);
|
|
||||||
};
|
|
||||||
|
|
||||||
await UploadResultsFile(file, jobLogHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadResultsFile(ResultsUploadFileInfo file, ResultsFileUploadHandler uploadHandler)
|
|
||||||
{
|
|
||||||
if (!_resultsClientInitiated)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool uploadSucceed = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await uploadHandler(file);
|
|
||||||
uploadSucceed = true;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (uploadSucceed && file.DeleteSource)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.Delete(file.Path);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Info("Exception encountered during deletion of a temporary file that was already successfully uploaded to results.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class PendingTimelineRecord
|
internal class PendingTimelineRecord
|
||||||
@@ -1014,19 +683,6 @@ namespace GitHub.Runner.Common
|
|||||||
public bool DeleteSource { get; set; }
|
public bool DeleteSource { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ResultsUploadFileInfo
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string Path { get; set; }
|
|
||||||
public string PlanId { get; set; }
|
|
||||||
public string JobId { get; set; }
|
|
||||||
public Guid RecordId { get; set; }
|
|
||||||
public bool DeleteSource { get; set; }
|
|
||||||
public bool Finalize { get; set; }
|
|
||||||
public bool FirstBlock { get; set; }
|
|
||||||
public long TotalLines { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ConsoleLineInfo
|
internal class ConsoleLineInfo
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
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,42 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Services.Launch.Client;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(LaunchServer))]
|
|
||||||
public interface ILaunchServer : IRunnerService
|
|
||||||
{
|
|
||||||
void InitializeLaunchClient(Uri uri, string token);
|
|
||||||
|
|
||||||
Task<ActionDownloadInfoCollection> ResolveActionsDownloadInfoAsync(Guid planId, Guid jobId, ActionReferenceList actionReferenceList, CancellationToken cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class LaunchServer : RunnerService, ILaunchServer
|
|
||||||
{
|
|
||||||
private LaunchHttpClient _launchClient;
|
|
||||||
|
|
||||||
public void InitializeLaunchClient(Uri uri, string token)
|
|
||||||
{
|
|
||||||
var httpMessageHandler = HostContext.CreateHttpClientHandler();
|
|
||||||
this._launchClient = new LaunchHttpClient(uri, httpMessageHandler, token, disposeHandler: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<ActionDownloadInfoCollection> ResolveActionsDownloadInfoAsync(Guid planId, Guid jobId, ActionReferenceList actionReferenceList,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_launchClient != null)
|
|
||||||
{
|
|
||||||
return _launchClient.GetResolveActionsDownloadInfoAsync(planId, jobId, actionReferenceList,
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Launch client is not initialized.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
@@ -21,12 +22,6 @@ namespace GitHub.Runner.Common
|
|||||||
// 8 MB
|
// 8 MB
|
||||||
public const int PageSize = 8 * 1024 * 1024;
|
public const int PageSize = 8 * 1024 * 1024;
|
||||||
|
|
||||||
// For Results
|
|
||||||
public static string BlocksFolder = "blocks";
|
|
||||||
|
|
||||||
// 2 MB
|
|
||||||
public const int BlockSize = 2 * 1024 * 1024;
|
|
||||||
|
|
||||||
private Guid _timelineId;
|
private Guid _timelineId;
|
||||||
private Guid _timelineRecordId;
|
private Guid _timelineRecordId;
|
||||||
private FileStream _pageData;
|
private FileStream _pageData;
|
||||||
@@ -38,13 +33,6 @@ namespace GitHub.Runner.Common
|
|||||||
private string _pagesFolder;
|
private string _pagesFolder;
|
||||||
private IJobServerQueue _jobServerQueue;
|
private IJobServerQueue _jobServerQueue;
|
||||||
|
|
||||||
private string _resultsDataFileName;
|
|
||||||
private FileStream _resultsBlockData;
|
|
||||||
private StreamWriter _resultsBlockWriter;
|
|
||||||
private string _resultsBlockFolder;
|
|
||||||
private int _blockByteCount;
|
|
||||||
private int _blockCount;
|
|
||||||
|
|
||||||
public long TotalLines => _totalLines;
|
public long TotalLines => _totalLines;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
@@ -52,10 +40,8 @@ namespace GitHub.Runner.Common
|
|||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
_totalLines = 0;
|
_totalLines = 0;
|
||||||
_pagesFolder = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Diag), PagingFolder);
|
_pagesFolder = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Diag), PagingFolder);
|
||||||
Directory.CreateDirectory(_pagesFolder);
|
|
||||||
_resultsBlockFolder = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Diag), BlocksFolder);
|
|
||||||
Directory.CreateDirectory(_resultsBlockFolder);
|
|
||||||
_jobServerQueue = HostContext.GetService<IJobServerQueue>();
|
_jobServerQueue = HostContext.GetService<IJobServerQueue>();
|
||||||
|
Directory.CreateDirectory(_pagesFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Setup(Guid timelineId, Guid timelineRecordId)
|
public void Setup(Guid timelineId, Guid timelineRecordId)
|
||||||
@@ -75,17 +61,11 @@ namespace GitHub.Runner.Common
|
|||||||
// lazy creation on write
|
// lazy creation on write
|
||||||
if (_pageWriter == null)
|
if (_pageWriter == null)
|
||||||
{
|
{
|
||||||
NewPage();
|
Create();
|
||||||
}
|
|
||||||
|
|
||||||
if (_resultsBlockWriter == null)
|
|
||||||
{
|
|
||||||
NewBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string line = $"{DateTime.UtcNow.ToString("O")} {message}";
|
string line = $"{DateTime.UtcNow.ToString("O")} {message}";
|
||||||
_pageWriter.WriteLine(line);
|
_pageWriter.WriteLine(line);
|
||||||
_resultsBlockWriter.WriteLine(line);
|
|
||||||
|
|
||||||
_totalLines++;
|
_totalLines++;
|
||||||
if (line.IndexOf('\n') != -1)
|
if (line.IndexOf('\n') != -1)
|
||||||
@@ -99,25 +79,21 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var bytes = System.Text.Encoding.UTF8.GetByteCount(line);
|
_byteCount += System.Text.Encoding.UTF8.GetByteCount(line);
|
||||||
_byteCount += bytes;
|
|
||||||
_blockByteCount += bytes;
|
|
||||||
if (_byteCount >= PageSize)
|
if (_byteCount >= PageSize)
|
||||||
{
|
{
|
||||||
NewPage();
|
NewPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_blockByteCount >= BlockSize)
|
|
||||||
{
|
|
||||||
NewBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void End()
|
public void End()
|
||||||
{
|
{
|
||||||
EndPage();
|
EndPage();
|
||||||
EndBlock(true);
|
}
|
||||||
|
|
||||||
|
private void Create()
|
||||||
|
{
|
||||||
|
NewPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NewPage()
|
private void NewPage()
|
||||||
@@ -142,27 +118,5 @@ namespace GitHub.Runner.Common
|
|||||||
_jobServerQueue.QueueFileUpload(_timelineId, _timelineRecordId, "DistributedTask.Core.Log", "CustomToolLog", _dataFileName, true);
|
_jobServerQueue.QueueFileUpload(_timelineId, _timelineRecordId, "DistributedTask.Core.Log", "CustomToolLog", _dataFileName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NewBlock()
|
|
||||||
{
|
|
||||||
EndBlock(false);
|
|
||||||
_blockByteCount = 0;
|
|
||||||
_resultsDataFileName = Path.Combine(_resultsBlockFolder, $"{_timelineId}_{_timelineRecordId}.{++_blockCount}");
|
|
||||||
_resultsBlockData = new FileStream(_resultsDataFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite);
|
|
||||||
_resultsBlockWriter = new StreamWriter(_resultsBlockData, System.Text.Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EndBlock(bool finalize)
|
|
||||||
{
|
|
||||||
if (_resultsBlockWriter != null)
|
|
||||||
{
|
|
||||||
_resultsBlockWriter.Flush();
|
|
||||||
_resultsBlockData.Flush();
|
|
||||||
_resultsBlockWriter.Dispose();
|
|
||||||
_resultsBlockWriter = null;
|
|
||||||
_resultsBlockData = null;
|
|
||||||
_jobServerQueue.QueueResultsUpload(_timelineRecordId, "ResultsLog", _resultsDataFileName, "Results.Core.Log", deleteSource: true, finalize, firstBlock: _resultsDataFileName.EndsWith(".1"), totalLines: _totalLines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public async Task<WorkerMessage> ReceiveAsync(CancellationToken cancellationToken)
|
public async Task<WorkerMessage> ReceiveAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
WorkerMessage result = new(MessageType.NotInitialized, string.Empty);
|
WorkerMessage result = new WorkerMessage(MessageType.NotInitialized, string.Empty);
|
||||||
result.MessageType = (MessageType)await _readStream.ReadInt32Async(cancellationToken);
|
result.MessageType = (MessageType)await _readStream.ReadInt32Async(cancellationToken);
|
||||||
result.Body = await _readStream.ReadStringAsync(cancellationToken);
|
result.Body = await _readStream.ReadStringAsync(cancellationToken);
|
||||||
Trace.Info($"Receiving message of length {result.Body.Length}, with hash '{IOUtil.GetSha256Hash(result.Body)}'");
|
Trace.Info($"Receiving message of length {result.Body.Length}, with hash '{IOUtil.GetSha256Hash(result.Body)}'");
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static string GetEnvironmentVariable(this Process process, IHostContext hostContext, string variable)
|
public static string GetEnvironmentVariable(this Process process, IHostContext hostContext, string variable)
|
||||||
{
|
{
|
||||||
var trace = hostContext.GetTrace(nameof(LinuxProcessExtensions));
|
var trace = hostContext.GetTrace(nameof(LinuxProcessExtensions));
|
||||||
Dictionary<string, string> env = new();
|
Dictionary<string, string> env = new Dictionary<string, string>();
|
||||||
|
|
||||||
if (Directory.Exists("/proc"))
|
if (Directory.Exists("/proc"))
|
||||||
{
|
{
|
||||||
@@ -322,8 +322,8 @@ namespace GitHub.Runner.Common
|
|||||||
// It doesn't escape '=' or ' ', so we can't parse the output into a dictionary of all envs.
|
// It doesn't escape '=' or ' ', so we can't parse the output into a dictionary of all envs.
|
||||||
// So we only look for the env you request, in the format of variable=value. (it won't work if you variable contains = or space)
|
// So we only look for the env you request, in the format of variable=value. (it won't work if you variable contains = or space)
|
||||||
trace.Info($"Read env from output of `ps e -p {process.Id} -o command`");
|
trace.Info($"Read env from output of `ps e -p {process.Id} -o command`");
|
||||||
List<string> psOut = new();
|
List<string> psOut = new List<string>();
|
||||||
object outputLock = new();
|
object outputLock = new object();
|
||||||
using (var p = hostContext.CreateService<IProcessInvoker>())
|
using (var p = hostContext.CreateService<IProcessInvoker>())
|
||||||
{
|
{
|
||||||
p.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs stdout)
|
p.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs stdout)
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Handles redirects for Http requests
|
|
||||||
/// </summary>
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
||||||
public class RedirectMessageHandler : DelegatingHandler
|
|
||||||
{
|
|
||||||
public RedirectMessageHandler(ITraceWriter trace)
|
|
||||||
{
|
|
||||||
Trace = trace;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(
|
|
||||||
HttpRequestMessage request,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (response != null &&
|
|
||||||
IsRedirect(response.StatusCode) &&
|
|
||||||
response.Headers.Location != null)
|
|
||||||
{
|
|
||||||
Trace.Info($"Redirecting to '{response.Headers.Location}'.");
|
|
||||||
|
|
||||||
request = await CloneAsync(request, response.Headers.Location).ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.Dispose();
|
|
||||||
|
|
||||||
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsRedirect(HttpStatusCode statusCode)
|
|
||||||
{
|
|
||||||
return (int)statusCode >= 300 && (int)statusCode < 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<HttpRequestMessage> CloneAsync(HttpRequestMessage request, Uri requestUri)
|
|
||||||
{
|
|
||||||
var clone = new HttpRequestMessage(request.Method, requestUri)
|
|
||||||
{
|
|
||||||
Version = request.Version
|
|
||||||
};
|
|
||||||
|
|
||||||
request.Headers.ForEach(header => clone.Headers.TryAddWithoutValidation(header.Key, header.Value));
|
|
||||||
|
|
||||||
request.Options.ForEach(option => clone.Options.Set(new HttpRequestOptionsKey<object>(option.Key), option.Value));
|
|
||||||
|
|
||||||
if (request.Content != null)
|
|
||||||
{
|
|
||||||
clone.Content = new ByteArrayContent(await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
|
||||||
|
|
||||||
request.Content.Headers.ForEach(header => clone.Content.Headers.TryAddWithoutValidation(header.Key, header.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly ITraceWriter Trace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,297 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Security;
|
|
||||||
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.Results.Client;
|
|
||||||
using GitHub.Services.WebApi.Utilities.Internal;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(ResultServer))]
|
|
||||||
public interface IResultsServer : IRunnerService, IAsyncDisposable
|
|
||||||
{
|
|
||||||
void InitializeResultsClient(Uri uri, string liveConsoleFeedUrl, string token, bool useSdk);
|
|
||||||
|
|
||||||
Task<bool> AppendLiveConsoleFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
// logging and console
|
|
||||||
Task CreateResultsStepSummaryAsync(string planId, string jobId, Guid stepId, string file,
|
|
||||||
CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task CreateResultsStepLogAsync(string planId, string jobId, Guid stepId, string file, bool finalize,
|
|
||||||
bool firstBlock, long lineCount, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task CreateResultsJobLogAsync(string planId, string jobId, string file, bool finalize, bool firstBlock,
|
|
||||||
long lineCount, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task UpdateResultsWorkflowStepsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId,
|
|
||||||
IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task CreateResultsDiagnosticLogsAsync(string planId, string jobId, string file, CancellationToken cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ResultServer : RunnerService, IResultsServer
|
|
||||||
{
|
|
||||||
private ResultsHttpClient _resultsClient;
|
|
||||||
|
|
||||||
private ClientWebSocket _websocketClient;
|
|
||||||
private DateTime? _lastConnectionFailure;
|
|
||||||
|
|
||||||
private static readonly TimeSpan MinDelayForWebsocketReconnect = TimeSpan.FromMilliseconds(100);
|
|
||||||
private static readonly TimeSpan MaxDelayForWebsocketReconnect = TimeSpan.FromMilliseconds(500);
|
|
||||||
|
|
||||||
private Task _websocketConnectTask;
|
|
||||||
private String _liveConsoleFeedUrl;
|
|
||||||
private string _token;
|
|
||||||
|
|
||||||
public void InitializeResultsClient(Uri uri, string liveConsoleFeedUrl, string token, bool useSdk)
|
|
||||||
{
|
|
||||||
this._resultsClient = CreateHttpClient(uri, token, useSdk);
|
|
||||||
|
|
||||||
_token = token;
|
|
||||||
if (!string.IsNullOrEmpty(liveConsoleFeedUrl))
|
|
||||||
{
|
|
||||||
_liveConsoleFeedUrl = liveConsoleFeedUrl;
|
|
||||||
InitializeWebsocketClient(liveConsoleFeedUrl, token, TimeSpan.Zero, retryConnection: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultsHttpClient CreateHttpClient(Uri uri, string token, bool useSdk)
|
|
||||||
{
|
|
||||||
// Using default 100 timeout
|
|
||||||
RawClientHttpRequestSettings settings = VssUtil.GetHttpRequestSettings(null);
|
|
||||||
|
|
||||||
// Create retry handler
|
|
||||||
IEnumerable<DelegatingHandler> delegatingHandlers = new List<DelegatingHandler>();
|
|
||||||
if (settings.MaxRetryRequest > 0)
|
|
||||||
{
|
|
||||||
delegatingHandlers = new DelegatingHandler[] { new VssHttpRetryMessageHandler(settings.MaxRetryRequest) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup RawHttpMessageHandler without credentials
|
|
||||||
var httpMessageHandler = new RawHttpMessageHandler(new NoOpCredentials(null), settings);
|
|
||||||
|
|
||||||
var pipeline = HttpClientFactory.CreatePipeline(httpMessageHandler, delegatingHandlers);
|
|
||||||
|
|
||||||
return new ResultsHttpClient(uri, pipeline, token, disposeHandler: true, useSdk: useSdk);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task CreateResultsStepSummaryAsync(string planId, string jobId, Guid stepId, string file,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_resultsClient != null)
|
|
||||||
{
|
|
||||||
return _resultsClient.UploadStepSummaryAsync(planId, jobId, stepId, file,
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Results client is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task CreateResultsStepLogAsync(string planId, string jobId, Guid stepId, string file, bool finalize,
|
|
||||||
bool firstBlock, long lineCount, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_resultsClient != null)
|
|
||||||
{
|
|
||||||
return _resultsClient.UploadResultsStepLogAsync(planId, jobId, stepId, file, finalize, firstBlock,
|
|
||||||
lineCount, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Results client is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task CreateResultsJobLogAsync(string planId, string jobId, string file, bool finalize, bool firstBlock,
|
|
||||||
long lineCount, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_resultsClient != null)
|
|
||||||
{
|
|
||||||
return _resultsClient.UploadResultsJobLogAsync(planId, jobId, file, finalize, firstBlock, lineCount,
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Results client is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task UpdateResultsWorkflowStepsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId,
|
|
||||||
IEnumerable<TimelineRecord> records, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_resultsClient != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var timelineRecords = records.ToList();
|
|
||||||
return _resultsClient.UpdateWorkflowStepsAsync(planId, new List<TimelineRecord>(timelineRecords),
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Log error, but continue as this call is best-effort
|
|
||||||
Trace.Info($"Failed to update steps status due to {ex.GetType().Name}");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Results client is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task CreateResultsDiagnosticLogsAsync(string planId, string jobId, string file,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_resultsClient != null)
|
|
||||||
{
|
|
||||||
return _resultsClient.UploadResultsDiagnosticLogsAsync(planId, jobId, file,
|
|
||||||
cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Results client is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None);
|
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
|
|
||||||
return ValueTask.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeWebsocketClient(string liveConsoleFeedUrl, string accessToken, TimeSpan delay, bool retryConnection = false)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(accessToken))
|
|
||||||
{
|
|
||||||
Trace.Info($"No access token from server");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(liveConsoleFeedUrl))
|
|
||||||
{
|
|
||||||
Trace.Info($"No live console feed url from server");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Trace.Info($"Creating websocket client ..." + liveConsoleFeedUrl);
|
|
||||||
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())));
|
|
||||||
|
|
||||||
// during initialization, retry upto 3 times to setup connection
|
|
||||||
this._websocketConnectTask = ConnectWebSocketClient(liveConsoleFeedUrl, delay, retryConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ConnectWebSocketClient(string feedStreamUrl, TimeSpan delay, bool retryConnection = false)
|
|
||||||
{
|
|
||||||
bool connected = false;
|
|
||||||
int retries = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Trace.Info($"Attempting to start websocket client with delay {delay}.");
|
|
||||||
await Task.Delay(delay);
|
|
||||||
using var connectTimeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
|
||||||
await this._websocketClient.ConnectAsync(new Uri(feedStreamUrl), connectTimeoutTokenSource.Token);
|
|
||||||
Trace.Info($"Successfully started websocket client.");
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Info("Exception caught during websocket client connect, retry connection.");
|
|
||||||
Trace.Error(ex);
|
|
||||||
retries++;
|
|
||||||
this._websocketClient = null;
|
|
||||||
_lastConnectionFailure = DateTime.Now;
|
|
||||||
}
|
|
||||||
} while (retryConnection && !connected && retries < 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> AppendLiveConsoleFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_websocketConnectTask != null)
|
|
||||||
{
|
|
||||||
await _websocketConnectTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool delivered = false;
|
|
||||||
int retries = 0;
|
|
||||||
|
|
||||||
// "_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
|
|
||||||
if (_websocketClient != null)
|
|
||||||
{
|
|
||||||
var linesWrapper = startLine.HasValue
|
|
||||||
? new TimelineRecordFeedLinesWrapper(stepId, lines, startLine.Value)
|
|
||||||
: new TimelineRecordFeedLinesWrapper(stepId, lines);
|
|
||||||
var jsonData = StringUtil.ConvertToJson(linesWrapper);
|
|
||||||
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));
|
|
||||||
|
|
||||||
delivered = false;
|
|
||||||
while (!delivered && retries < 3)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_websocketClient != null)
|
|
||||||
{
|
|
||||||
await _websocketClient.SendAsync(chunk, WebSocketMessageType.Text, endOfMessage: lastChunk, cancellationToken);
|
|
||||||
delivered = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var delay = BackoffTimerHelper.GetRandomBackoff(MinDelayForWebsocketReconnect, MaxDelayForWebsocketReconnect);
|
|
||||||
Trace.Info($"Websocket is not open, let's attempt to connect back again with random backoff {delay} ms.");
|
|
||||||
Trace.Verbose(ex.ToString());
|
|
||||||
retries++;
|
|
||||||
InitializeWebsocketClient(_liveConsoleFeedUrl, _token, delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!delivered)
|
|
||||||
{
|
|
||||||
// Giving up for now, so next invocation of this method won't attempt to reconnect
|
|
||||||
_websocketClient = null;
|
|
||||||
|
|
||||||
// however if 10 minutes have already passed, let's try reestablish connection again
|
|
||||||
if (_lastConnectionFailure.HasValue && DateTime.Now > _lastConnectionFailure.Value.AddMinutes(10))
|
|
||||||
{
|
|
||||||
// Some minutes passed since we retried last time, try connection again
|
|
||||||
InitializeWebsocketClient(_liveConsoleFeedUrl, _token, TimeSpan.Zero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return delivered;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CloseWebSocket(WebSocketCloseStatus closeStatus, 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}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.Actions.RunService.WebApi;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using Sdk.RSWebApi.Contracts;
|
using GitHub.Services.WebApi;
|
||||||
using Sdk.WebApi.WebApi.RawClient;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -18,37 +17,48 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
||||||
|
|
||||||
Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken token);
|
Task<AgentJobRequestMessage> GetJobMessageAsync(string id);
|
||||||
|
|
||||||
Task CompleteJobAsync(
|
|
||||||
Guid planId,
|
|
||||||
Guid jobId,
|
|
||||||
TaskResult result,
|
|
||||||
Dictionary<String, VariableValue> outputs,
|
|
||||||
IList<StepResult> stepResults,
|
|
||||||
IList<Annotation> jobAnnotations,
|
|
||||||
string environmentUrl,
|
|
||||||
CancellationToken token);
|
|
||||||
|
|
||||||
Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RunServer : RunnerService, IRunServer
|
public sealed class RunServer : RunnerService, IRunServer
|
||||||
{
|
{
|
||||||
private bool _hasConnection;
|
private bool _hasConnection;
|
||||||
private Uri requestUri;
|
private VssConnection _connection;
|
||||||
private RawConnection _connection;
|
private TaskAgentHttpClient _taskAgentClient;
|
||||||
private RunServiceHttpClient _runServiceHttpClient;
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUri, VssCredentials credentials)
|
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
||||||
{
|
{
|
||||||
requestUri = serverUri;
|
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
||||||
|
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
|
||||||
_connection = VssUtil.CreateRawConnection(serverUri, credentials);
|
|
||||||
_runServiceHttpClient = await _connection.GetClientAsync<RunServiceHttpClient>();
|
|
||||||
_hasConnection = true;
|
_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()
|
private void CheckConnection()
|
||||||
{
|
{
|
||||||
if (!_hasConnection)
|
if (!_hasConnection)
|
||||||
@@ -57,37 +67,10 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken)
|
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id)
|
||||||
{
|
{
|
||||||
CheckConnection();
|
CheckConnection();
|
||||||
return RetryRequest<AgentJobRequestMessage>(
|
return _taskAgentClient.GetJobMessageAsync(id);
|
||||||
async () => await _runServiceHttpClient.GetJobMessageAsync(requestUri, id, VarUtil.OS, cancellationToken), cancellationToken,
|
|
||||||
shouldRetry: ex =>
|
|
||||||
ex is not TaskOrchestrationJobNotFoundException && // HTTP status 404
|
|
||||||
ex is not TaskOrchestrationJobAlreadyAcquiredException && // HTTP status 409
|
|
||||||
ex is not TaskOrchestrationJobUnprocessableException); // HTTP status 422
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task CompleteJobAsync(
|
|
||||||
Guid planId,
|
|
||||||
Guid jobId,
|
|
||||||
TaskResult result,
|
|
||||||
Dictionary<String, VariableValue> outputs,
|
|
||||||
IList<StepResult> stepResults,
|
|
||||||
IList<Annotation> jobAnnotations,
|
|
||||||
string environmentUrl,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
return RetryRequest(
|
|
||||||
async () => await _runServiceHttpClient.CompleteJobAsync(requestUri, planId, jobId, result, outputs, stepResults, jobAnnotations, environmentUrl, cancellationToken), cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<RenewJobResponse> RenewJobAsync(Guid planId, Guid jobId, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
return RetryRequest<RenewJobResponse>(
|
|
||||||
async () => await _runServiceHttpClient.RenewJobAsync(requestUri, planId, jobId, cancellationToken), cancellationToken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Threading.Channels" Version="4.4.0" />
|
<PackageReference Include="System.Threading.Channels" Version="4.4.0" />
|
||||||
|
|||||||
@@ -1,237 +0,0 @@
|
|||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(RunnerDotcomServer))]
|
|
||||||
public interface IRunnerDotcomServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName);
|
|
||||||
|
|
||||||
Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey);
|
|
||||||
Task<DistributedTask.WebApi.Runner> ReplaceRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey);
|
|
||||||
Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum RequestType
|
|
||||||
{
|
|
||||||
Get,
|
|
||||||
Post,
|
|
||||||
Patch,
|
|
||||||
Delete
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RunnerDotcomServer : RunnerService, IRunnerDotcomServer
|
|
||||||
{
|
|
||||||
private ITerminal _term;
|
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
|
||||||
{
|
|
||||||
base.Initialize(hostContext);
|
|
||||||
_term = hostContext.GetService<ITerminal>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<List<TaskAgent>> GetRunnerByNameAsync(string githubUrl, string githubToken, string agentName)
|
|
||||||
{
|
|
||||||
var githubApiUrl = "";
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (path.Length == 1)
|
|
||||||
{
|
|
||||||
// org runner
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.Length == 2)
|
|
||||||
{
|
|
||||||
// repo or enterprise runner.
|
|
||||||
if (!string.Equals(path[0], "enterprises", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runners?name={Uri.EscapeDataString(agentName)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"'{githubUrl}' should point to an org or enterprise.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var runnersList = await RetryRequest<ListRunnersResponse>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
|
||||||
|
|
||||||
return runnersList.ToTaskAgents();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken)
|
|
||||||
{
|
|
||||||
var githubApiUrl = "";
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (path.Length == 1)
|
|
||||||
{
|
|
||||||
// org runner
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.Length == 2)
|
|
||||||
{
|
|
||||||
// repo or enterprise runner.
|
|
||||||
if (!string.Equals(path[0], "enterprises", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"'{githubUrl}' should point to an org or enterprise.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var agentPools = await RetryRequest<RunnerGroupList>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
|
||||||
|
|
||||||
return agentPools?.ToAgentPoolList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<DistributedTask.WebApi.Runner> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey)
|
|
||||||
{
|
|
||||||
return await AddOrReplaceRunner(runnerGroupId, agent, githubUrl, githubToken, publicKey, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<DistributedTask.WebApi.Runner> ReplaceRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey)
|
|
||||||
{
|
|
||||||
return await AddOrReplaceRunner(runnerGroupId, agent, githubUrl, githubToken, publicKey, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<DistributedTask.WebApi.Runner> AddOrReplaceRunner(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey, bool replace)
|
|
||||||
{
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
string githubApiUrl;
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/actions/runners/register";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/actions/runners/register";
|
|
||||||
}
|
|
||||||
|
|
||||||
var bodyObject = new Dictionary<string, Object>()
|
|
||||||
{
|
|
||||||
{"url", githubUrl},
|
|
||||||
{"group_id", runnerGroupId},
|
|
||||||
{"name", agent.Name},
|
|
||||||
{"version", agent.Version},
|
|
||||||
{"updates_disabled", agent.DisableUpdate},
|
|
||||||
{"ephemeral", agent.Ephemeral},
|
|
||||||
{"labels", agent.Labels},
|
|
||||||
{"public_key", publicKey},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (replace)
|
|
||||||
{
|
|
||||||
bodyObject.Add("runner_id", agent.Id);
|
|
||||||
bodyObject.Add("replace", replace);
|
|
||||||
}
|
|
||||||
|
|
||||||
var body = new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json");
|
|
||||||
|
|
||||||
return await RetryRequest<DistributedTask.WebApi.Runner>(githubApiUrl, githubToken, RequestType.Post, 3, "Failed to add agent", body);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<T> RetryRequest<T>(string githubApiUrl, string githubToken, RequestType requestType, int maxRetryAttemptsCount = 5, string errorMessage = null, StringContent body = null)
|
|
||||||
{
|
|
||||||
int retry = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
retry++;
|
|
||||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
|
||||||
using (var httpClient = new HttpClient(httpClientHandler))
|
|
||||||
{
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
|
|
||||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
|
||||||
|
|
||||||
var responseStatus = System.Net.HttpStatusCode.OK;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = null;
|
|
||||||
if (requestType == RequestType.Get)
|
|
||||||
{
|
|
||||||
response = await httpClient.GetAsync(githubApiUrl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response = await httpClient.PostAsync(githubApiUrl, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
responseStatus = response.StatusCode;
|
|
||||||
var githubRequestId = UrlUtil.GetGitHubRequestId(response.Headers);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Trace.Info($"Http response code: {response.StatusCode} from '{requestType.ToString()} {githubApiUrl}' ({githubRequestId})");
|
|
||||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
|
||||||
return StringUtil.ConvertFromJson<T>(jsonResponse);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_term.WriteError($"Http response code: {response.StatusCode} from '{requestType.ToString()} {githubApiUrl}' (Request Id: {githubRequestId})");
|
|
||||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
|
||||||
_term.WriteError(errorResponse);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (retry < maxRetryAttemptsCount && responseStatus != System.Net.HttpStatusCode.NotFound)
|
|
||||||
{
|
|
||||||
Trace.Error($"{errorMessage} -- Attempt: {retry}");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
|
|
||||||
Trace.Info($"Retrying in {backOff.Seconds} seconds");
|
|
||||||
await Task.Delay(backOff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
@@ -27,8 +28,8 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent);
|
||||||
Task DeleteAgentAsync(int agentPoolId, ulong agentId);
|
Task DeleteAgentAsync(int agentPoolId, int agentId);
|
||||||
Task DeleteAgentAsync(ulong agentId);
|
Task DeleteAgentAsync(int agentId);
|
||||||
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
||||||
@@ -38,7 +39,7 @@ namespace GitHub.Runner.Common
|
|||||||
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
|
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
|
||||||
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
|
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
|
||||||
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
|
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
|
||||||
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, string os, string architecture, bool disableUpdate, CancellationToken cancellationToken);
|
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// job request
|
// job request
|
||||||
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
||||||
@@ -50,7 +51,7 @@ namespace GitHub.Runner.Common
|
|||||||
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent update
|
// agent update
|
||||||
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, ulong agentId, string currentState, string trace);
|
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RunnerServer : RunnerService, IRunnerServer
|
public sealed class RunnerServer : RunnerService, IRunnerServer
|
||||||
@@ -179,6 +180,31 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
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(RunnerConnectionType connectionType)
|
private void CheckConnection(RunnerConnectionType connectionType)
|
||||||
{
|
{
|
||||||
switch (connectionType)
|
switch (connectionType)
|
||||||
@@ -239,13 +265,13 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentPoolId, ulong agentId)
|
public Task DeleteAgentAsync(int agentPoolId, int agentId)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(ulong agentId)
|
public Task DeleteAgentAsync(int agentId)
|
||||||
{
|
{
|
||||||
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
||||||
}
|
}
|
||||||
@@ -272,10 +298,10 @@ namespace GitHub.Runner.Common
|
|||||||
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, string os, string architecture, bool disableUpdate, CancellationToken cancellationToken)
|
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, runnerVersion, os, architecture, disableUpdate, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
@@ -315,7 +341,7 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, ulong agentId, string currentState, string trace)
|
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using Sdk.WebApi.WebApi.RawClient;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -27,9 +21,9 @@ namespace GitHub.Runner.Common
|
|||||||
protected IHostContext HostContext { get; private set; }
|
protected IHostContext HostContext { get; private set; }
|
||||||
protected Tracing Trace { get; private set; }
|
protected Tracing Trace { get; private set; }
|
||||||
|
|
||||||
public string TraceName
|
public string TraceName
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetType().Name;
|
return GetType().Name;
|
||||||
}
|
}
|
||||||
@@ -41,71 +35,5 @@ namespace GitHub.Runner.Common
|
|||||||
Trace = HostContext.GetTrace(TraceName);
|
Trace = HostContext.GetTrace(TraceName);
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task RetryRequest(Func<Task> func,
|
|
||||||
CancellationToken cancellationToken,
|
|
||||||
int maxRetryAttemptsCount = 5
|
|
||||||
)
|
|
||||||
{
|
|
||||||
async Task<Unit> wrappedFunc()
|
|
||||||
{
|
|
||||||
await func();
|
|
||||||
return Unit.Value;
|
|
||||||
}
|
|
||||||
await RetryRequest<Unit>(wrappedFunc, cancellationToken, maxRetryAttemptsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task<T> RetryRequest<T>(Func<Task<T>> func,
|
|
||||||
CancellationToken cancellationToken,
|
|
||||||
int maxRetryAttemptsCount = 5,
|
|
||||||
Func<Exception, bool> shouldRetry = null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
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 && (shouldRetry == null || shouldRetry(ex)))
|
|
||||||
{
|
|
||||||
Trace.Error("Catch exception during request");
|
|
||||||
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,96 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
public sealed class StdoutTraceListener : ConsoleTraceListener
|
|
||||||
{
|
|
||||||
private readonly string _hostType;
|
|
||||||
|
|
||||||
public StdoutTraceListener(string hostType)
|
|
||||||
{
|
|
||||||
this._hostType = hostType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied and modified slightly from .Net Core source code. Modification was required to make it compile.
|
|
||||||
// There must be some TraceFilter extension class that is missing in this source code.
|
|
||||||
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
|
|
||||||
{
|
|
||||||
if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(message))
|
|
||||||
{
|
|
||||||
var messageLines = message.Split(Environment.NewLine);
|
|
||||||
foreach (var messageLine in messageLines)
|
|
||||||
{
|
|
||||||
WriteHeader(source, eventType, id);
|
|
||||||
WriteLine(messageLine);
|
|
||||||
WriteFooter(eventCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool IsEnabled(TraceOptions opts)
|
|
||||||
{
|
|
||||||
return (opts & TraceOutputOptions) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Altered from the original .Net Core implementation.
|
|
||||||
private void WriteHeader(string source, TraceEventType eventType, int id)
|
|
||||||
{
|
|
||||||
string type = null;
|
|
||||||
switch (eventType)
|
|
||||||
{
|
|
||||||
case TraceEventType.Critical:
|
|
||||||
type = "CRIT";
|
|
||||||
break;
|
|
||||||
case TraceEventType.Error:
|
|
||||||
type = "ERR ";
|
|
||||||
break;
|
|
||||||
case TraceEventType.Warning:
|
|
||||||
type = "WARN";
|
|
||||||
break;
|
|
||||||
case TraceEventType.Information:
|
|
||||||
type = "INFO";
|
|
||||||
break;
|
|
||||||
case TraceEventType.Verbose:
|
|
||||||
type = "VERB";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type = eventType.ToString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Write(StringUtil.Format("[{0} {1:u} {2} {3}] ", _hostType.ToUpperInvariant(), DateTime.UtcNow, type, source));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied and modified slightly from .Net Core source code to make it compile. The original code
|
|
||||||
// accesses a private indentLevel field. In this code it has been modified to use the getter/setter.
|
|
||||||
private void WriteFooter(TraceEventCache eventCache)
|
|
||||||
{
|
|
||||||
if (eventCache == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IndentLevel++;
|
|
||||||
if (IsEnabled(TraceOptions.ProcessId))
|
|
||||||
WriteLine("ProcessId=" + eventCache.ProcessId);
|
|
||||||
|
|
||||||
if (IsEnabled(TraceOptions.ThreadId))
|
|
||||||
WriteLine("ThreadId=" + eventCache.ThreadId);
|
|
||||||
|
|
||||||
if (IsEnabled(TraceOptions.DateTime))
|
|
||||||
WriteLine("DateTime=" + eventCache.DateTime.ToString("o", CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
if (IsEnabled(TraceOptions.Timestamp))
|
|
||||||
WriteLine("Timestamp=" + eventCache.Timestamp);
|
|
||||||
|
|
||||||
IndentLevel--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ namespace GitHub.Runner.Common
|
|||||||
string ReadSecret();
|
string ReadSecret();
|
||||||
void Write(string message, ConsoleColor? colorCode = null);
|
void Write(string message, ConsoleColor? colorCode = null);
|
||||||
void WriteLine();
|
void WriteLine();
|
||||||
void WriteLine(string line, ConsoleColor? colorCode = null, bool skipTracing = false);
|
void WriteLine(string line, ConsoleColor? colorCode = null);
|
||||||
void WriteError(Exception ex);
|
void WriteError(Exception ex);
|
||||||
void WriteError(string line);
|
void WriteError(string line);
|
||||||
void WriteSection(string message);
|
void WriteSection(string message);
|
||||||
@@ -81,7 +81,7 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Trace whether a value was entered.
|
// Trace whether a value was entered.
|
||||||
string val = new(chars.ToArray());
|
string val = new String(chars.ToArray());
|
||||||
if (!string.IsNullOrEmpty(val))
|
if (!string.IsNullOrEmpty(val))
|
||||||
{
|
{
|
||||||
HostContext.SecretMasker.AddValue(val);
|
HostContext.SecretMasker.AddValue(val);
|
||||||
@@ -116,12 +116,9 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
// Do not add a format string overload. Terminal messages are user facing and therefore
|
// Do not add a format string overload. Terminal messages are user facing and therefore
|
||||||
// should be localized. Use the Loc method in the StringUtil class.
|
// should be localized. Use the Loc method in the StringUtil class.
|
||||||
public void WriteLine(string line, ConsoleColor? colorCode = null, bool skipTracing = false)
|
public void WriteLine(string line, ConsoleColor? colorCode = null)
|
||||||
{
|
{
|
||||||
if (!skipTracing)
|
Trace.Info($"WRITE LINE: {line}");
|
||||||
{
|
|
||||||
Trace.Info($"WRITE LINE: {line}");
|
|
||||||
}
|
|
||||||
if (!Silent)
|
if (!Silent)
|
||||||
{
|
{
|
||||||
if (colorCode != null)
|
if (colorCode != null)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Services.Common.Internal;
|
using GitHub.Services.Common.Internal;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using GitHub.DistributedTask.Logging;
|
using GitHub.DistributedTask.Logging;
|
||||||
@@ -14,25 +15,23 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public sealed class TraceManager : ITraceManager
|
public sealed class TraceManager : ITraceManager
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, Tracing> _sources = new(StringComparer.OrdinalIgnoreCase);
|
private readonly ConcurrentDictionary<string, Tracing> _sources = new ConcurrentDictionary<string, Tracing>(StringComparer.OrdinalIgnoreCase);
|
||||||
private readonly HostTraceListener _hostTraceListener;
|
private readonly HostTraceListener _hostTraceListener;
|
||||||
private readonly StdoutTraceListener _stdoutTraceListener;
|
|
||||||
private TraceSetting _traceSetting;
|
private TraceSetting _traceSetting;
|
||||||
private ISecretMasker _secretMasker;
|
private ISecretMasker _secretMasker;
|
||||||
|
|
||||||
public TraceManager(HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener, ISecretMasker secretMasker)
|
public TraceManager(HostTraceListener traceListener, ISecretMasker secretMasker)
|
||||||
: this(traceListener, stdoutTraceListener, new TraceSetting(), secretMasker)
|
: this(traceListener, new TraceSetting(), secretMasker)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceManager(HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener, TraceSetting traceSetting, ISecretMasker secretMasker)
|
public TraceManager(HostTraceListener traceListener, TraceSetting traceSetting, ISecretMasker secretMasker)
|
||||||
{
|
{
|
||||||
// Validate and store params.
|
// Validate and store params.
|
||||||
ArgUtil.NotNull(traceListener, nameof(traceListener));
|
ArgUtil.NotNull(traceListener, nameof(traceListener));
|
||||||
ArgUtil.NotNull(traceSetting, nameof(traceSetting));
|
ArgUtil.NotNull(traceSetting, nameof(traceSetting));
|
||||||
ArgUtil.NotNull(secretMasker, nameof(secretMasker));
|
ArgUtil.NotNull(secretMasker, nameof(secretMasker));
|
||||||
_hostTraceListener = traceListener;
|
_hostTraceListener = traceListener;
|
||||||
_stdoutTraceListener = stdoutTraceListener;
|
|
||||||
_traceSetting = traceSetting;
|
_traceSetting = traceSetting;
|
||||||
_secretMasker = secretMasker;
|
_secretMasker = secretMasker;
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ namespace GitHub.Runner.Common
|
|||||||
Level = sourceTraceLevel.ToSourceLevels()
|
Level = sourceTraceLevel.ToSourceLevels()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return new Tracing(name, _secretMasker, sourceSwitch, _hostTraceListener, _stdoutTraceListener);
|
return new Tracing(name, _secretMasker, sourceSwitch, _hostTraceListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -12,7 +14,7 @@ namespace GitHub.Runner.Common
|
|||||||
private ISecretMasker _secretMasker;
|
private ISecretMasker _secretMasker;
|
||||||
private TraceSource _traceSource;
|
private TraceSource _traceSource;
|
||||||
|
|
||||||
public Tracing(string name, ISecretMasker secretMasker, SourceSwitch sourceSwitch, HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener = null)
|
public Tracing(string name, ISecretMasker secretMasker, SourceSwitch sourceSwitch, HostTraceListener traceListener)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNull(secretMasker, nameof(secretMasker));
|
ArgUtil.NotNull(secretMasker, nameof(secretMasker));
|
||||||
_secretMasker = secretMasker;
|
_secretMasker = secretMasker;
|
||||||
@@ -27,10 +29,6 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
_traceSource.Listeners.Add(traceListener);
|
_traceSource.Listeners.Add(traceListener);
|
||||||
if (stdoutTraceListener != null)
|
|
||||||
{
|
|
||||||
_traceSource.Listeners.Add(stdoutTraceListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Info(string message)
|
public void Info(string message)
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
// Represents absence of value.
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
public readonly struct Unit
|
|
||||||
{
|
|
||||||
public static readonly Unit Value = default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
public static class EnumUtil
|
public static class EnumUtil
|
||||||
{
|
{
|
||||||
public static T? TryParse<T>(string value) where T : struct
|
public static T? TryParse<T>(string value) where T: struct
|
||||||
{
|
{
|
||||||
T val;
|
T val;
|
||||||
if (Enum.TryParse(value ?? string.Empty, ignoreCase: true, result: out val))
|
if (Enum.TryParse(value ?? string.Empty, ignoreCase: true, result: out val))
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
namespace GitHub.Runner.Common.Util
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
|
|
||||||
public static class MessageUtil
|
|
||||||
{
|
|
||||||
public static bool IsRunServiceJob(string messageType)
|
|
||||||
{
|
|
||||||
return string.Equals(messageType, JobRequestMessageTypes.RunnerJobRequest, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -6,17 +6,17 @@ namespace GitHub.Runner.Common.Util
|
|||||||
public static class NodeUtil
|
public static class NodeUtil
|
||||||
{
|
{
|
||||||
private const string _defaultNodeVersion = "node16";
|
private const string _defaultNodeVersion = "node16";
|
||||||
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16", "node20" });
|
|
||||||
|
#if OS_OSX && ARM64
|
||||||
|
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" });
|
||||||
|
#else
|
||||||
|
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node12", "node16" });
|
||||||
|
#endif
|
||||||
|
|
||||||
public static string GetInternalNodeVersion()
|
public static string GetInternalNodeVersion()
|
||||||
{
|
{
|
||||||
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
|
var forcedNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
|
||||||
var isForcedInternalNodeVersion = !string.IsNullOrEmpty(forcedInternalNodeVersion) && BuiltInNodeVersions.Contains(forcedInternalNodeVersion);
|
return !string.IsNullOrEmpty(forcedNodeVersion) && BuiltInNodeVersions.Contains(forcedNodeVersion) ? forcedNodeVersion : _defaultNodeVersion;
|
||||||
|
|
||||||
if (isForcedInternalNodeVersion)
|
|
||||||
{
|
|
||||||
return forcedInternalNodeVersion;
|
|
||||||
}
|
|
||||||
return _defaultNodeVersion;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Util
|
namespace GitHub.Runner.Common.Util
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user