mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9ce10da6d | ||
|
|
c3649406e8 | ||
|
|
f954835f54 | ||
|
|
512cd2b4f8 |
@@ -1,8 +0,0 @@
|
|||||||
# 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>`
|
|
||||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
# these files as binary and thus will always conflict and require user
|
# these files as binary and thus will always conflict and require user
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
@@ -70,9 +70,9 @@
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# diff behavior for common document formats
|
# diff behavior for common document formats
|
||||||
#
|
#
|
||||||
# Convert binary document formats to text before diffing them. This feature
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
# is only available from the command line. Turn it on by uncommenting the
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
# entries below.
|
# entries below.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
*.doc diff=astextplain
|
*.doc diff=astextplain
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ If applicable, add a code snippet.
|
|||||||
**Additional information**
|
**Additional information**
|
||||||
Add any other context about the feature here.
|
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
|
NOTE: if the feature request has been agreed upon then the assignee will create an ADR. See docs/adrs/README.md
|
||||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -7,12 +7,12 @@ on:
|
|||||||
- main
|
- main
|
||||||
- releases/*
|
- releases/*
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
|||||||
# languages: go, javascript, csharp, python, cpp, java
|
# languages: go, javascript, csharp, python, cpp, java
|
||||||
|
|
||||||
- name: Manual build
|
- name: Manual build
|
||||||
run : |
|
run : |
|
||||||
./dev.sh layout Release linux-x64
|
./dev.sh layout Release linux-x64
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
|
|||||||
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -5,7 +5,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- releaseVersion
|
- releaseVersion
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
|
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
|
||||||
@@ -13,8 +13,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
# Make sure ./releaseVersion match ./src/runnerversion
|
# Make sure ./releaseVersion match ./src/runnerversion
|
||||||
# Query GitHub release ensure version is not used
|
# Query GitHub release ensure version is not used
|
||||||
- name: Check version
|
- name: Check version
|
||||||
uses: actions/github-script@0.3.0
|
uses: actions/github-script@0.3.0
|
||||||
with:
|
with:
|
||||||
@@ -42,7 +42,7 @@ jobs:
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: check
|
needs: check
|
||||||
outputs:
|
outputs:
|
||||||
@@ -152,7 +152,7 @@ jobs:
|
|||||||
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}}')
|
||||||
console.log(releaseNote)
|
console.log(releaseNote)
|
||||||
core.setOutput('version', runnerVersion);
|
core.setOutput('version', runnerVersion);
|
||||||
core.setOutput('note', releaseNote);
|
core.setOutput('note', releaseNote);
|
||||||
# Create GitHub release
|
# Create GitHub release
|
||||||
- uses: actions/create-release@master
|
- uses: actions/create-release@master
|
||||||
id: createRelease
|
id: createRelease
|
||||||
|
|||||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -54,4 +54,4 @@
|
|||||||
"requireExactSource": false,
|
"requireExactSource": false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ export RUNNER_CFG_PAT=yourPAT
|
|||||||
|
|
||||||
:point_right: [Sample script here](../scripts/create-latest-svc.sh) :point_left:
|
:point_right: [Sample script here](../scripts/create-latest-svc.sh) :point_left:
|
||||||
|
|
||||||
Run as a one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
Run as a one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
||||||
```bash
|
```bash
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-latest-svc.sh | bash -s yourorg/yourrepo
|
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-latest-svc.sh | bash -s yourorg/yourrepo
|
||||||
```
|
```
|
||||||
@@ -47,7 +47,7 @@ curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-lat
|
|||||||
|
|
||||||
The runner is installed as a service using `systemd` and `systemctl`. Docker does not support `systemd` for service configuration on a container.
|
The runner is installed as a service using `systemd` and `systemctl`. Docker does not support `systemd` for service configuration on a container.
|
||||||
|
|
||||||
## Uninstall running as service
|
## Uninstall running as service
|
||||||
|
|
||||||
**Scenario**: Run on a machine or VM ([not container](#why-cant-i-use-a-container)) which automates:
|
**Scenario**: Run on a machine or VM ([not container](#why-cant-i-use-a-container)) which automates:
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ The runner is installed as a service using `systemd` and `systemctl`. Docker doe
|
|||||||
|
|
||||||
:point_right: [Sample script here](../scripts/remove-svc.sh) :point_left:
|
:point_right: [Sample script here](../scripts/remove-svc.sh) :point_left:
|
||||||
|
|
||||||
Repo level one liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
Repo level one liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
||||||
```bash
|
```bash
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/remove-svc.sh | bash -s yourorg/yourrepo
|
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/remove-svc.sh | bash -s yourorg/yourrepo
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,16 +18,16 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
|
|
||||||
- DNS lookup for api.github.com or myGHES.com using dotnet
|
- DNS lookup for api.github.com or myGHES.com using dotnet
|
||||||
- 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 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`
|
||||||
---
|
---
|
||||||
- DNS lookup for pipelines.actions.githubusercontent.com using dotnet
|
- DNS lookup for pipelines.actions.githubusercontent.com using dotnet
|
||||||
- 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`
|
||||||
|
|
||||||
## How to fix the issue?
|
## How to fix the issue?
|
||||||
|
|
||||||
@@ -42,4 +42,4 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
|
|||||||
|
|
||||||
## Still not working?
|
## Still not working?
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||||
@@ -31,4 +31,4 @@ The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` be
|
|||||||
|
|
||||||
## Still not working?
|
## Still not working?
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||||
@@ -13,7 +13,7 @@ Even the runner is configured to GitHub Enterprise Server, the runner can still
|
|||||||
|
|
||||||
- DNS lookup for api.github.com using dotnet
|
- DNS lookup for api.github.com using dotnet
|
||||||
- Ping api.github.com using dotnet
|
- Ping api.github.com using dotnet
|
||||||
- Make HTTP GET to https://api.github.com using dotnet, check response headers contains `X-GitHub-Request-Id`
|
- Make HTTP GET to https://api.github.com using dotnet, check response headers contains `X-GitHub-Request-Id`
|
||||||
|
|
||||||
## How to fix the issue?
|
## How to fix the issue?
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@ Even the runner is configured to GitHub Enterprise Server, the runner can still
|
|||||||
|
|
||||||
## Still not working?
|
## Still not working?
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||||
@@ -25,7 +25,7 @@ Use a 3rd party tool to make the same requests as the runner did would be a good
|
|||||||
|
|
||||||
- Use `nslookup` to check DNS
|
- Use `nslookup` to check DNS
|
||||||
- Use `ping` to check Ping
|
- Use `ping` to check Ping
|
||||||
- Use `traceroute`, `tracepath`, or `tracert` to check the network route between the runner and the Actions service
|
- Use `traceroute`, `tracepath`, or `tracert` to check the network route between the runner and the Actions service
|
||||||
- Use `curl -v` to check the network stack, good for verifying default certificate/proxy settings.
|
- Use `curl -v` to check the network stack, good for verifying default certificate/proxy settings.
|
||||||
- Use `Invoke-WebRequest` from `pwsh` (`PowerShell Core`) to check the dotnet network stack, good for verifying bugs in the dotnet framework.
|
- Use `Invoke-WebRequest` from `pwsh` (`PowerShell Core`) to check the dotnet network stack, good for verifying bugs in the dotnet framework.
|
||||||
|
|
||||||
@@ -50,12 +50,11 @@ If you are having trouble connecting, try these steps:
|
|||||||
- The runner runs on .net core, lets validate the local settings for that stack
|
- The runner runs on .net core, lets validate the local settings for that stack
|
||||||
- Open up `pwsh`
|
- Open up `pwsh`
|
||||||
- Run the command using the urls above `Invoke-WebRequest {url}`
|
- Run the command using the urls above `Invoke-WebRequest {url}`
|
||||||
3. If not, get a packet trace using a tool like wireshark and start looking at the TLS handshake.
|
3. If not, get a packet trace using a tool like wireshark and start looking at the TLS handshake.
|
||||||
- If you see a Client Hello followed by a Server RST:
|
- If you see a Client Hello followed by a Server RST:
|
||||||
- You may need to configure your TLS settings to use the correct version
|
- You may need to configure your TLS settings to use the correct version
|
||||||
- You should support TLS version 1.2 or later
|
- You should support TLS version 1.2 or later
|
||||||
- You may need to configure your TLS settings to have up to date cipher suites, this may be solved by system updates and patches.
|
- You may need to configure your TLS settings to have up to date cipher suites, this may be solved by system updates and patches.
|
||||||
- Most notably, on windows server 2012 make sure [the tls cipher suite update](https://support.microsoft.com/en-us/topic/update-adds-new-tls-cipher-suites-and-changes-cipher-suite-priorities-in-windows-8-1-and-windows-server-2012-r2-8e395e43-c8ef-27d8-b60c-0fc57d526d94) is installed
|
|
||||||
- Your firewall, proxy or network configuration may be blocking the connection
|
- Your firewall, proxy or network configuration may be blocking the connection
|
||||||
- You will want to reach out to whoever is in charge of your network with these pcap files to further troubleshoot
|
- You will want to reach out to whoever is in charge of your network with these pcap files to further troubleshoot
|
||||||
- If you see a failure later in the handshake:
|
- If you see a failure later in the handshake:
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ All javascript base Actions will get executed by the built-in `node` at `<runner
|
|||||||
|
|
||||||
## Still not working?
|
## Still not working?
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
||||||
@@ -12,7 +12,7 @@ As long as your certificate is generated properly, most of the issues should be
|
|||||||
> !!! DO NOT SKIP SSL CERT VALIDATION !!!
|
> !!! DO NOT SKIP SSL CERT VALIDATION !!!
|
||||||
> !!! IT IS A BAD SECURITY PRACTICE !!!
|
> !!! IT IS A BAD SECURITY PRACTICE !!!
|
||||||
|
|
||||||
### Download SSL certificate chain
|
### Download SSL certificate chain
|
||||||
|
|
||||||
Depends on how your SSL server certificate gets configured, you might need to download the whole certificate chain from a machine that has trusted the SSL certificate's CA.
|
Depends on how your SSL server certificate gets configured, you might need to download the whole certificate chain from a machine that has trusted the SSL certificate's CA.
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ The actions runner is a dotnet core application which will follow how dotnet loa
|
|||||||
|
|
||||||
You can get full details documentation at [here](https://docs.microsoft.com/en-us/dotnet/standard/security/cross-platform-cryptography#x509store)
|
You can get full details documentation at [here](https://docs.microsoft.com/en-us/dotnet/standard/security/cross-platform-cryptography#x509store)
|
||||||
|
|
||||||
In short:
|
In short:
|
||||||
- Windows: Load from Windows certificate store.
|
- Windows: Load from Windows certificate store.
|
||||||
- Linux: Load from OpenSSL CA cert bundle.
|
- Linux: Load from OpenSSL CA cert bundle.
|
||||||
- macOS: Load from macOS KeyChain.
|
- macOS: Load from macOS KeyChain.
|
||||||
@@ -43,13 +43,13 @@ To let the runner trusts your CA certificate, you will need to:
|
|||||||
1. RedHat: https://www.redhat.com/sysadmin/ca-certificates-cli
|
1. RedHat: https://www.redhat.com/sysadmin/ca-certificates-cli
|
||||||
2. Ubuntu: http://manpages.ubuntu.com/manpages/focal/man8/update-ca-certificates.8.html
|
2. Ubuntu: http://manpages.ubuntu.com/manpages/focal/man8/update-ca-certificates.8.html
|
||||||
3. Google search: "trust ca certificate on [linux distribution]"
|
3. Google search: "trust ca certificate on [linux distribution]"
|
||||||
4. If all approaches failed, set environment variable `SSL_CERT_FILE` to the CA bundle `.pem` file we get.
|
4. If all approaches failed, set environment variable `SSL_CERT_FILE` to the CA bundle `.pem` file we get.
|
||||||
> To verify cert gets installed properly on Linux, you can try use `curl -v https://sitewithsslissue.com` and `pwsh -Command \"Invoke-WebRequest -Uri https://sitewithsslissue.com\"`
|
> To verify cert gets installed properly on Linux, you can try use `curl -v https://sitewithsslissue.com` and `pwsh -Command \"Invoke-WebRequest -Uri https://sitewithsslissue.com\"`
|
||||||
|
|
||||||
### Trust CA certificate for Git CLI
|
### Trust CA certificate for Git CLI
|
||||||
|
|
||||||
Git uses various CA bundle file depends on your operation system.
|
Git uses various CA bundle file depends on your operation system.
|
||||||
- Git packaged the CA bundle file within the Git installation on Windows
|
- Git packaged the CA bundle file within the Git installation on Windows
|
||||||
- Git use OpenSSL certificate CA bundle file on Linux and macOS
|
- Git use OpenSSL certificate CA bundle file on Linux and macOS
|
||||||
|
|
||||||
You can check where Git check CA file by running:
|
You can check where Git check CA file by running:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Issues in this repository should be for the runner application. Note that the V
|
|||||||
|
|
||||||
## Enhancements and Feature Requests
|
## Enhancements and Feature Requests
|
||||||
|
|
||||||
We ask that before significant effort is put into code changes, that we have agreement on taking the change before time is invested in code changes.
|
We ask that before significant effort is put into code changes, that we have agreement on taking the change before time is invested in code changes.
|
||||||
|
|
||||||
1. Create a feature request. Once agreed we will take the enhancement
|
1. Create a feature request. Once agreed we will take the enhancement
|
||||||
2. Create an ADR to agree on the details of the change.
|
2. Create an ADR to agree on the details of the change.
|
||||||
@@ -46,9 +46,9 @@ Tip: Make sure your job can run on this runner. The easiest way is to set `runs-
|
|||||||
|
|
||||||
|
|
||||||
## Development Life Cycle
|
## Development Life Cycle
|
||||||
If you're using VS Code, you can follow [these](contribute/vscode.md) steps instead.
|
If you're using VS Code, you can follow [these](contribute/vscode.md) steps instead.
|
||||||
|
|
||||||
### To Build, Test, Layout
|
### To Build, Test, Layout
|
||||||
|
|
||||||
Navigate to the `src` directory and run the following command:
|
Navigate to the `src` directory and run the following command:
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ These examples use VS Code, but the idea should be similar across all IDEs as lo
|
|||||||
## Configure
|
## Configure
|
||||||
|
|
||||||
To successfully start the runner, you need to register it using a repository and a runner registration token.
|
To successfully start the runner, you need to register it using a repository and a runner registration token.
|
||||||
Run `Configure` first to build the source code and set up the runner in `_layout`.
|
Run `Configure` first to build the source code and set up the runner in `_layout`.
|
||||||
Once it's done creating `_layout`, it asks for the url of your repository and your token in the terminal.
|
Once it's done creating `_layout`, it asks for the url of your repository and your token in the terminal.
|
||||||
|
|
||||||
Check [Quickstart](../contribute.md#quickstart-run-a-job-from-a-real-repository) if you don't know how to get this token.
|
Check [Quickstart](../contribute.md#quickstart-run-a-job-from-a-real-repository) if you don't know how to get this token.
|
||||||
@@ -34,7 +34,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 diferent 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.
|
||||||
@@ -45,7 +45,7 @@ Because the worker process is usually started by the listener instead of an IDE,
|
|||||||
For this reason, `Runner.Worker` can be configured to wait for a debugger to be attached before it begins any actual work.
|
For this reason, `Runner.Worker` can be configured to wait for a debugger to be attached before it begins any actual work.
|
||||||
|
|
||||||
Set the environment variable `GITHUB_ACTIONS_RUNNER_ATTACH_DEBUGGER` to `true` or `1` to enable this wait.
|
Set the environment variable `GITHUB_ACTIONS_RUNNER_ATTACH_DEBUGGER` to `true` or `1` to enable this wait.
|
||||||
All worker processes now will wait 20 seconds before they start working on their task.
|
All worker processes now will wait 20 seconds before they start working on their task.
|
||||||
|
|
||||||
This gives enough time to attach a debugger by running `Debug Worker`.
|
This gives enough time to attach a debugger by running `Debug Worker`.
|
||||||
If for some reason you have multiple workers running, run the launch config `Attach` instead.
|
If for some reason you have multiple workers running, run the launch config `Attach` instead.
|
||||||
|
|||||||
@@ -58,4 +58,4 @@ Authentication in a workflow run to github.com can be accomplished by using the
|
|||||||
|
|
||||||
Hosted runner authentication differs from self-hosted authentication in that runners do not undergo a registration process, but instead, the hosted runners get the OAuth token directly by reading the `.credentials` file. The scope of this particular token is limited for a given workflow job execution, and the token is revoked as soon as the job is finished.
|
Hosted runner authentication differs from self-hosted authentication in that runners do not undergo a registration process, but instead, the hosted runners get the OAuth token directly by reading the `.credentials` file. The scope of this particular token is limited for a given workflow job execution, and the token is revoked as soon as the job is finished.
|
||||||
|
|
||||||

|

|
||||||
@@ -27,7 +27,7 @@ Dependencies is missing for Dotnet Core 3.0
|
|||||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
||||||
```
|
```
|
||||||
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
||||||
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
||||||
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`).
|
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`).
|
||||||
|
|
||||||
### Full dependencies list
|
### Full dependencies list
|
||||||
@@ -35,15 +35,15 @@ 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-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
|
||||||
- libicu63, libicu60, libicu57 or libicu55
|
- libicu63, libicu60, libicu57 or libicu55
|
||||||
|
|
||||||
Fedora based OS (Fedora, Red Hat Enterprise Linux, CentOS, Oracle Linux 7)
|
Fedora based OS (Fedora, Red Hat Enterprise Linux, CentOS, Oracle Linux 7)
|
||||||
|
|
||||||
- lttng-ust
|
- lttng-ust
|
||||||
- openssl-libs
|
- openssl-libs
|
||||||
- krb5-libs
|
- krb5-libs
|
||||||
- zlib
|
- zlib
|
||||||
- libicu
|
- libicu
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
- macOS High Sierra (10.13) and later versions
|
- macOS High Sierra (10.13) and later versions
|
||||||
|
|
||||||
## Apple Silicon M1
|
## Apple Silicon M1
|
||||||
|
|
||||||
The runner is currently not supported on devices with an Apple M1 chip.
|
The runner is currently not supported on devices with an Apple M1 chip.
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
- Fixed an issue where ephemeral runners deregistered themselves when jobs were not successful (#1384)
|
- Revert "More resilient VssConnection client retries in JobServer" (#1343)
|
||||||
- Fixed an issue where you were not able to un-configure a runner that changed groups (#1359)
|
|
||||||
- Disable `stop-commands` command using well known keywords as a token (#1371)
|
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
- Don't retry 422 error codes when downloading actions (#1352)
|
N/A
|
||||||
- Handle upgrade more smoothly on OSX (#1381)
|
|
||||||
|
|
||||||
## 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.
|
||||||
@@ -21,7 +20,7 @@ mkdir \actions-runner ; cd \actions-runner
|
|||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
|
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
|
||||||
# Extract the installer
|
# Extract the installer
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
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")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.283.2
|
2.282.1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Sample scripts for self-hosted runners
|
# Sample scripts for self-hosted runners
|
||||||
|
|
||||||
Here are some examples to work from if you'd like to automate your use of self-hosted runners.
|
Here are some examples to work from if you'd like to automate your use of self-hosted runners.
|
||||||
See the docs [here](../docs/automate.md).
|
See the docs [here](../docs/automate.md).
|
||||||
@@ -18,8 +18,6 @@ downloadrunnerversion=_DOWNLOAD_RUNNER_VERSION_
|
|||||||
logfile="_UPDATE_LOG_"
|
logfile="_UPDATE_LOG_"
|
||||||
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
||||||
|
|
||||||
telemetryfile="$rootfolder/_diag/.telemetry"
|
|
||||||
|
|
||||||
# log user who run the script
|
# log user who run the script
|
||||||
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
||||||
whoami >> "$logfile" 2>&1
|
whoami >> "$logfile" 2>&1
|
||||||
@@ -120,101 +118,40 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# fix upgrade issue with macOS when running as a service
|
# fix upgrade issue with macOS
|
||||||
attemptedtargetedfix=0
|
|
||||||
currentplatform=$(uname | awk '{print tolower($0)}')
|
currentplatform=$(uname | awk '{print tolower($0)}')
|
||||||
if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
|
if [[ "$currentplatform" == 'darwin' ]]; then
|
||||||
# We needed a fix for https://github.com/actions/runner/issues/743
|
# need a short-term fix for https://github.com/actions/runner/issues/743
|
||||||
# We will recreate the ./externals/node12/bin/node of the past runner version that launched the runnerlistener service
|
# we will recreate all the ./externals/node12/bin/node of the past 5 versions
|
||||||
# Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file
|
# v2.280.3 v2.280.2 v2.280.1 v2.279.0 v2.278.0
|
||||||
|
if [[ ! -e "$rootfolder/externals.2.280.3/node12/bin/node" ]]
|
||||||
# We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid
|
|
||||||
# assumption here is only one process is invoking rootfolder/runsvc.sh
|
|
||||||
procgroup=$(ps x -o pgid,command | grep "$rootfolder/runsvc.sh" | grep -v grep | awk '{print $1}')
|
|
||||||
if [[ $? -eq 0 && -n "$procgroup" ]]
|
|
||||||
then
|
then
|
||||||
# inspect the open file handles to find the node process
|
mkdir -p "$rootfolder/externals.2.280.3/node12/bin"
|
||||||
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks
|
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.3/node12/bin/node"
|
||||||
path=$(lsof -a -g "$procgroup" -F n | grep node12/bin/node | grep externals | tail -1 | cut -c2-)
|
|
||||||
if [[ $? -eq 0 && -n "$path" ]]
|
|
||||||
then
|
|
||||||
# trim the last 5 characters of the path '/node'
|
|
||||||
trimmedpath=$(dirname "$path")
|
|
||||||
if [[ $? -eq 0 && -n "$trimmedpath" ]]
|
|
||||||
then
|
|
||||||
attemptedtargetedfix=1
|
|
||||||
# Create the path if it does not exist
|
|
||||||
if [[ ! -e "$path" ]]
|
|
||||||
then
|
|
||||||
date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1
|
|
||||||
mkdir -p "$trimmedpath"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$path"
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $attemptedtargetedfix -eq 0 ]
|
if [[ ! -e "$rootfolder/externals.2.280.2/node12/bin/node" ]]
|
||||||
then
|
then
|
||||||
|
mkdir -p "$rootfolder/externals.2.280.2/node12/bin"
|
||||||
|
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.2/node12/bin/node"
|
||||||
|
fi
|
||||||
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Defaulting to old macOS service fix" >> "$logfile" 2>&1
|
if [[ ! -e "$rootfolder/externals.2.280.1/node12/bin/node" ]]
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Defaulting to old macOS service fix" >> "$telemetryfile" 2>&1
|
then
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.3/node12/bin/node" ]]
|
mkdir -p "$rootfolder/externals.2.280.1/node12/bin"
|
||||||
then
|
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.1/node12/bin/node"
|
||||||
mkdir -p "$rootfolder/externals.2.280.3/node12/bin"
|
fi
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.3/node12/bin/node"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.2/node12/bin/node" ]]
|
if [[ ! -e "$rootfolder/externals.2.279.0/node12/bin/node" ]]
|
||||||
then
|
then
|
||||||
mkdir -p "$rootfolder/externals.2.280.2/node12/bin"
|
mkdir -p "$rootfolder/externals.2.279.0/node12/bin"
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.2/node12/bin/node"
|
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.279.0/node12/bin/node"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.280.1/node12/bin/node" ]]
|
if [[ ! -e "$rootfolder/externals.2.278.0/node12/bin/node" ]]
|
||||||
then
|
then
|
||||||
mkdir -p "$rootfolder/externals.2.280.1/node12/bin"
|
mkdir -p "$rootfolder/externals.2.278.0/node12/bin"
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.280.1/node12/bin/node"
|
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.278.0/node12/bin/node"
|
||||||
fi
|
|
||||||
|
|
||||||
# GHES 3.2
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.279.0/node12/bin/node" ]]
|
|
||||||
then
|
|
||||||
mkdir -p "$rootfolder/externals.2.279.0/node12/bin"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.279.0/node12/bin/node"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# GHES 3.1.2 or later
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.278.0/node12/bin/node" ]]
|
|
||||||
then
|
|
||||||
mkdir -p "$rootfolder/externals.2.278.0/node12/bin"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.278.0/node12/bin/node"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# GHES 3.1.0
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.276.1/node12/bin/node" ]]
|
|
||||||
then
|
|
||||||
mkdir -p "$rootfolder/externals.2.276.1/node12/bin"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.276.1/node12/bin/node"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# GHES 3.0
|
|
||||||
if [[ ! -e "$rootfolder/externals.2.273.5/node12/bin/node" ]]
|
|
||||||
then
|
|
||||||
mkdir -p "$rootfolder/externals.2.273.5/node12/bin"
|
|
||||||
cp "$rootfolder/externals/node12/bin/node" "$rootfolder/externals.2.273.5/node12/bin/node"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ namespace GitHub.Runner.Common
|
|||||||
Certificates,
|
Certificates,
|
||||||
Options,
|
Options,
|
||||||
SetupInfo,
|
SetupInfo,
|
||||||
Telemetry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Constants
|
public static class Constants
|
||||||
@@ -129,7 +128,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string Ephemeral = "ephemeral";
|
public static readonly string Ephemeral = "ephemeral";
|
||||||
public static readonly string Help = "help";
|
public static readonly string Help = "help";
|
||||||
public static readonly string Replace = "replace";
|
public static readonly string Replace = "replace";
|
||||||
public static readonly string Once = "once"; // Keep this around since customers still relies on it
|
public static readonly string Once = "once"; // TODO: Remove in 10/2021
|
||||||
public static readonly string RunAsService = "runasservice";
|
public static readonly string RunAsService = "runasservice";
|
||||||
public static readonly string Unattended = "unattended";
|
public static readonly string Unattended = "unattended";
|
||||||
public static readonly string Version = "version";
|
public static readonly string Version = "version";
|
||||||
@@ -155,7 +154,6 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
|
||||||
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
|
||||||
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
|
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
|
||||||
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RunnerEvent
|
public static class RunnerEvent
|
||||||
@@ -215,7 +213,6 @@ namespace GitHub.Runner.Common
|
|||||||
// Keep alphabetical
|
// Keep alphabetical
|
||||||
//
|
//
|
||||||
public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS";
|
public static readonly string AllowUnsupportedCommands = "ACTIONS_ALLOW_UNSECURE_COMMANDS";
|
||||||
public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS";
|
|
||||||
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
|
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
|
||||||
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,12 +342,6 @@ namespace GitHub.Runner.Common
|
|||||||
GetDirectory(WellKnownDirectory.Root),
|
GetDirectory(WellKnownDirectory.Root),
|
||||||
".setup_info");
|
".setup_info");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WellKnownConfigFile.Telemetry:
|
|
||||||
path = Path.Combine(
|
|
||||||
GetDirectory(WellKnownDirectory.Diag),
|
|
||||||
".telemetry");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Unexpected well known config file: '{configFile}'");
|
throw new NotSupportedException($"Unexpected well known config file: '{configFile}'");
|
||||||
|
|||||||
@@ -29,10 +29,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, int agentId);
|
Task DeleteAgentAsync(int agentPoolId, int agentId);
|
||||||
Task DeleteAgentAsync(int agentId);
|
|
||||||
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null);
|
||||||
Task<List<TaskAgent>> GetAgentsAsync(string agentName);
|
|
||||||
Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent);
|
Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent);
|
||||||
|
|
||||||
// messagequeue
|
// messagequeue
|
||||||
@@ -254,11 +252,6 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
|
|
||||||
{
|
|
||||||
return GetAgentsAsync(0, agentName); // search in all all agentPools
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
|
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
|
||||||
{
|
{
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
@@ -271,11 +264,6 @@ namespace GitHub.Runner.Common
|
|||||||
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentId)
|
|
||||||
{
|
|
||||||
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// MessageQueue
|
// MessageQueue
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ namespace GitHub.Runner.Listener
|
|||||||
Constants.Runner.CommandLine.Flags.Commit,
|
Constants.Runner.CommandLine.Flags.Commit,
|
||||||
Constants.Runner.CommandLine.Flags.Ephemeral,
|
Constants.Runner.CommandLine.Flags.Ephemeral,
|
||||||
Constants.Runner.CommandLine.Flags.Help,
|
Constants.Runner.CommandLine.Flags.Help,
|
||||||
Constants.Runner.CommandLine.Flags.Once,
|
|
||||||
Constants.Runner.CommandLine.Flags.Replace,
|
Constants.Runner.CommandLine.Flags.Replace,
|
||||||
Constants.Runner.CommandLine.Flags.RunAsService,
|
Constants.Runner.CommandLine.Flags.RunAsService,
|
||||||
Constants.Runner.CommandLine.Flags.Unattended,
|
Constants.Runner.CommandLine.Flags.Unattended,
|
||||||
@@ -69,7 +68,7 @@ namespace GitHub.Runner.Listener
|
|||||||
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
|
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
|
||||||
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
|
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
|
||||||
|
|
||||||
// Keep this around since customers still relies on it
|
// TODO: Remove in 10/2021
|
||||||
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
|
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
bool IsConfigured();
|
bool IsConfigured();
|
||||||
Task ConfigureAsync(CommandSettings command);
|
Task ConfigureAsync(CommandSettings command);
|
||||||
Task UnconfigureAsync(CommandSettings command);
|
Task UnconfigureAsync(CommandSettings command);
|
||||||
void DeleteLocalRunnerConfig();
|
|
||||||
RunnerSettings LoadSettings();
|
RunnerSettings LoadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,38 +329,6 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete .runner and .credentials files
|
|
||||||
public void DeleteLocalRunnerConfig()
|
|
||||||
{
|
|
||||||
bool isConfigured = _store.IsConfigured();
|
|
||||||
bool hasCredentials = _store.HasCredentials();
|
|
||||||
//delete credential config files
|
|
||||||
var currentAction = "Removing .credentials";
|
|
||||||
if (hasCredentials)
|
|
||||||
{
|
|
||||||
_store.DeleteCredential();
|
|
||||||
var keyManager = HostContext.GetService<IRSAKeyManager>();
|
|
||||||
keyManager.DeleteKey();
|
|
||||||
_term.WriteSuccessMessage("Removed .credentials");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_term.WriteLine("Does not exist. Skipping " + currentAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete settings config file
|
|
||||||
currentAction = "Removing .runner";
|
|
||||||
if (isConfigured)
|
|
||||||
{
|
|
||||||
_store.DeleteSettings();
|
|
||||||
_term.WriteSuccessMessage("Removed .runner");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_term.WriteLine("Does not exist. Skipping " + currentAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UnconfigureAsync(CommandSettings command)
|
public async Task UnconfigureAsync(CommandSettings command)
|
||||||
{
|
{
|
||||||
string currentAction = string.Empty;
|
string currentAction = string.Empty;
|
||||||
@@ -415,7 +382,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// Determine the service deployment type based on connection data. (Hosted/OnPremises)
|
// Determine the service deployment type based on connection data. (Hosted/OnPremises)
|
||||||
await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
|
await _runnerServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
|
||||||
|
|
||||||
var agents = await _runnerServer.GetAgentsAsync(settings.AgentName);
|
var agents = await _runnerServer.GetAgentsAsync(settings.PoolId, settings.AgentName);
|
||||||
Trace.Verbose("Returns {0} agents", agents.Count);
|
Trace.Verbose("Returns {0} agents", agents.Count);
|
||||||
TaskAgent agent = agents.FirstOrDefault();
|
TaskAgent agent = agents.FirstOrDefault();
|
||||||
if (agent == null)
|
if (agent == null)
|
||||||
@@ -424,7 +391,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _runnerServer.DeleteAgentAsync(settings.AgentId);
|
await _runnerServer.DeleteAgentAsync(settings.PoolId, settings.AgentId);
|
||||||
|
|
||||||
_term.WriteLine();
|
_term.WriteLine();
|
||||||
_term.WriteSuccessMessage("Runner removed successfully");
|
_term.WriteSuccessMessage("Runner removed successfully");
|
||||||
@@ -435,7 +402,31 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
_term.WriteLine("Cannot connect to server, because config files are missing. Skipping removing runner from the server.");
|
_term.WriteLine("Cannot connect to server, because config files are missing. Skipping removing runner from the server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteLocalRunnerConfig();
|
//delete credential config files
|
||||||
|
currentAction = "Removing .credentials";
|
||||||
|
if (hasCredentials)
|
||||||
|
{
|
||||||
|
_store.DeleteCredential();
|
||||||
|
var keyManager = HostContext.GetService<IRSAKeyManager>();
|
||||||
|
keyManager.DeleteKey();
|
||||||
|
_term.WriteSuccessMessage("Removed .credentials");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_term.WriteLine("Does not exist. Skipping " + currentAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete settings config file
|
||||||
|
currentAction = "Removing .runner";
|
||||||
|
if (isConfigured)
|
||||||
|
{
|
||||||
|
_store.DeleteSettings();
|
||||||
|
_term.WriteSuccessMessage("Removed .runner");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_term.WriteLine("Does not exist. Skipping " + currentAction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,10 +36,7 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>();
|
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>();
|
||||||
private int _poolId;
|
private int _poolId;
|
||||||
|
RunnerSettings _runnerSetting;
|
||||||
IConfigurationStore _configurationStore;
|
|
||||||
|
|
||||||
RunnerSettings _runnerSettings;
|
|
||||||
private static readonly string _workerProcessName = $"Runner.Worker{IOUtil.ExeExtension}";
|
private static readonly string _workerProcessName = $"Runner.Worker{IOUtil.ExeExtension}";
|
||||||
|
|
||||||
// this is not thread-safe
|
// this is not thread-safe
|
||||||
@@ -57,9 +54,9 @@ namespace GitHub.Runner.Listener
|
|||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
|
|
||||||
// get pool id from config
|
// get pool id from config
|
||||||
_configurationStore = hostContext.GetService<IConfigurationStore>();
|
var configurationStore = hostContext.GetService<IConfigurationStore>();
|
||||||
_runnerSettings = _configurationStore.GetSettings();
|
_runnerSetting = configurationStore.GetSettings();
|
||||||
_poolId = _runnerSettings.PoolId;
|
_poolId = _runnerSetting.PoolId;
|
||||||
|
|
||||||
int channelTimeoutSeconds;
|
int channelTimeoutSeconds;
|
||||||
if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT") ?? string.Empty, out channelTimeoutSeconds))
|
if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT") ?? string.Empty, out channelTimeoutSeconds))
|
||||||
@@ -664,15 +661,13 @@ namespace GitHub.Runner.Listener
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
|
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
|
||||||
|
|
||||||
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
|
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
|
||||||
|
|
||||||
if (!firstJobRequestRenewed.Task.IsCompleted)
|
if (!firstJobRequestRenewed.Task.IsCompleted)
|
||||||
{
|
{
|
||||||
// fire first renew succeed event.
|
// fire first renew succeed event.
|
||||||
firstJobRequestRenewed.TrySetResult(0);
|
firstJobRequestRenewed.TrySetResult(0);
|
||||||
|
|
||||||
// Update settings if the runner name has been changed server-side
|
|
||||||
UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encounteringError > 0)
|
if (encounteringError > 0)
|
||||||
@@ -772,27 +767,6 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAgentNameIfNeeded(string agentName)
|
|
||||||
{
|
|
||||||
var isNewAgentName = !string.Equals(_runnerSettings.AgentName, agentName, StringComparison.Ordinal);
|
|
||||||
if (!isNewAgentName || string.IsNullOrEmpty(agentName))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_runnerSettings.AgentName = agentName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_configurationStore.SaveSettings(_runnerSettings);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.Error("Cannot update the settings file:");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Best effort upload any logs for this job.
|
// Best effort upload any logs for this job.
|
||||||
private async Task TryUploadUnfinishedLogs(Pipelines.AgentJobRequestMessage message)
|
private async Task TryUploadUnfinishedLogs(Pipelines.AgentJobRequestMessage message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ namespace GitHub.Runner.Listener
|
|||||||
var startupTypeAsString = command.GetStartupType();
|
var startupTypeAsString = command.GetStartupType();
|
||||||
if (string.IsNullOrEmpty(startupTypeAsString) && configuredAsService)
|
if (string.IsNullOrEmpty(startupTypeAsString) && configuredAsService)
|
||||||
{
|
{
|
||||||
// We need try our best to make the startup type accurate
|
// We need try our best to make the startup type accurate
|
||||||
// The problem is coming from runner autoupgrade, which result an old version service host binary but a newer version runner binary
|
// The problem is coming from runner autoupgrade, which result an old version service host binary but a newer version runner binary
|
||||||
// At that time the servicehost won't pass --startuptype to Runner.Listener while the runner is actually running as service.
|
// At that time the servicehost won't pass --startuptype to Runner.Listener while the runner is actually running as service.
|
||||||
// We will guess the startup type only when the runner is configured as service and the guess will based on whether STDOUT/STDERR/STDIN been redirect or not
|
// We will guess the startup type only when the runner is configured as service and the guess will based on whether STDOUT/STDERR/STDIN been redirect or not
|
||||||
@@ -233,14 +233,8 @@ namespace GitHub.Runner.Listener
|
|||||||
Trace.Info($"Set runner startup type - {startType}");
|
Trace.Info($"Set runner startup type - {startType}");
|
||||||
HostContext.StartupType = startType;
|
HostContext.StartupType = startType;
|
||||||
|
|
||||||
if (command.RunOnce)
|
|
||||||
{
|
|
||||||
_term.WriteLine("Warning: '--once' is going to be deprecated in the future, please consider using '--ephemeral' during runner registration.", ConsoleColor.Yellow);
|
|
||||||
_term.WriteLine("https://docs.github.com/en/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#using-ephemeral-runners-for-autoscaling", ConsoleColor.Yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the runner interactively or as service
|
// Run the runner interactively or as service
|
||||||
return await RunAsync(settings, command.RunOnce || settings.Ephemeral);
|
return await RunAsync(settings, command.RunOnce || settings.Ephemeral); // TODO: Remove RunOnce later.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -316,9 +310,6 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
IJobDispatcher jobDispatcher = null;
|
IJobDispatcher jobDispatcher = null;
|
||||||
CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken);
|
CancellationTokenSource messageQueueLoopTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HostContext.RunnerShutdownToken);
|
||||||
|
|
||||||
// Should we try to cleanup ephemeral runners
|
|
||||||
bool runOnceJobCompleted = false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var notification = HostContext.GetService<IJobNotification>();
|
var notification = HostContext.GetService<IJobNotification>();
|
||||||
@@ -380,7 +371,6 @@ namespace GitHub.Runner.Listener
|
|||||||
Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task);
|
Task completeTask = await Task.WhenAny(getNextMessage, jobDispatcher.RunOnceJobCompleted.Task);
|
||||||
if (completeTask == jobDispatcher.RunOnceJobCompleted.Task)
|
if (completeTask == jobDispatcher.RunOnceJobCompleted.Task)
|
||||||
{
|
{
|
||||||
runOnceJobCompleted = true;
|
|
||||||
Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode.");
|
Trace.Info("Job has finished at backend, the runner will exit since it is running under onetime use mode.");
|
||||||
Trace.Info("Stop message queue looping.");
|
Trace.Info("Stop message queue looping.");
|
||||||
messageQueueLoopTokenSource.Cancel();
|
messageQueueLoopTokenSource.Cancel();
|
||||||
@@ -488,12 +478,6 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
messageQueueLoopTokenSource.Dispose();
|
messageQueueLoopTokenSource.Dispose();
|
||||||
|
|
||||||
if (settings.Ephemeral && runOnceJobCompleted)
|
|
||||||
{
|
|
||||||
var configManager = HostContext.GetService<IConfigurationManager>();
|
|
||||||
configManager.DeleteLocalRunnerConfig();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (TaskAgentAccessTokenExpiredException)
|
catch (TaskAgentAccessTokenExpiredException)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -108,18 +110,11 @@ namespace GitHub.Runner.Worker
|
|||||||
// Stop command
|
// Stop command
|
||||||
if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(actionCommand.Command, _stopCommand, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ValidateStopToken(context, actionCommand.Data);
|
context.Output(input);
|
||||||
|
context.Debug("Paused processing commands until '##[{actionCommand.Data}]' is received");
|
||||||
_stopToken = actionCommand.Data;
|
_stopToken = actionCommand.Data;
|
||||||
_stopProcessCommand = true;
|
_stopProcessCommand = true;
|
||||||
_registeredCommands.Add(_stopToken);
|
_registeredCommands.Add(_stopToken);
|
||||||
if (_stopToken.Length > 6)
|
|
||||||
{
|
|
||||||
HostContext.SecretMasker.AddValue(_stopToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Output(input);
|
|
||||||
context.Debug("Paused processing commands until the token you called ::stopCommands:: with is received");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Found command
|
// Found command
|
||||||
@@ -153,42 +148,7 @@ namespace GitHub.Runner.Worker
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateStopToken(IExecutionContext context, string stopToken)
|
internal static bool EnhancedAnnotationsEnabled(IExecutionContext context) {
|
||||||
{
|
|
||||||
#if OS_WINDOWS
|
|
||||||
var envContext = context.ExpressionValues["env"] as DictionaryContextData;
|
|
||||||
#else
|
|
||||||
var envContext = context.ExpressionValues["env"] as CaseSensitiveDictionaryContextData;
|
|
||||||
#endif
|
|
||||||
var allowUnsecureStopCommandTokens = false;
|
|
||||||
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens));
|
|
||||||
if (!allowUnsecureStopCommandTokens && envContext.ContainsKey(Constants.Variables.Actions.AllowUnsupportedStopCommandTokens))
|
|
||||||
{
|
|
||||||
allowUnsecureStopCommandTokens = StringUtil.ConvertToBoolean(envContext[Constants.Variables.Actions.AllowUnsupportedStopCommandTokens].ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTokenInvalid = _registeredCommands.Contains(stopToken)
|
|
||||||
|| string.IsNullOrEmpty(stopToken)
|
|
||||||
|| string.Equals(stopToken, "pause-logging", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (isTokenInvalid)
|
|
||||||
{
|
|
||||||
var telemetry = new JobTelemetry
|
|
||||||
{
|
|
||||||
Message = $"Invoked ::stopCommand:: with token: [{stopToken}]",
|
|
||||||
Type = JobTelemetryType.ActionCommand
|
|
||||||
};
|
|
||||||
context.JobTelemetry.Add(telemetry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTokenInvalid && !allowUnsecureStopCommandTokens)
|
|
||||||
{
|
|
||||||
throw new Exception(Constants.Runner.UnsupportedStopCommandTokenDisabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool EnhancedAnnotationsEnabled(IExecutionContext context)
|
|
||||||
{
|
|
||||||
return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false;
|
return context.Global.Variables.GetBoolean("DistributedTask.EnhancedAnnotations") ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,7 +252,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public const String Name = "name";
|
public const String Name = "name";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] _setEnvBlockList =
|
private string[] _setEnvBlockList =
|
||||||
{
|
{
|
||||||
"NODE_OPTIONS"
|
"NODE_OPTIONS"
|
||||||
};
|
};
|
||||||
@@ -393,7 +353,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
|
||||||
{
|
{
|
||||||
var allowUnsecureCommands = false;
|
var allowUnsecureCommands = false;
|
||||||
bool.TryParse(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedCommands), out allowUnsecureCommands);
|
bool.TryParse(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowUnsupportedCommands), out allowUnsecureCommands);
|
||||||
|
|
||||||
@@ -582,11 +542,11 @@ namespace GitHub.Runner.Worker
|
|||||||
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|
||||||
if (!ActionCommandManager.EnhancedAnnotationsEnabled(context))
|
if (!ActionCommandManager.EnhancedAnnotationsEnabled(context))
|
||||||
{
|
{
|
||||||
context.Debug("Enhanced Annotations not enabled on the server. The 'title', 'end_line', and 'end_column' fields are unsupported.");
|
context.Debug("Enhanced Annotations not enabled on the server. The 'title', 'end_line', and 'end_column' fields are unsupported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Issue issue = new Issue()
|
Issue issue = new Issue()
|
||||||
{
|
{
|
||||||
Category = "General",
|
Category = "General",
|
||||||
@@ -638,7 +598,7 @@ namespace GitHub.Runner.Worker
|
|||||||
context.AddIssue(issue);
|
context.AddIssue(issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context)
|
public static void ValidateLinesAndColumns(ActionCommand command, IExecutionContext context)
|
||||||
{
|
{
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
command.Properties.TryGetValue(IssueCommandProperties.EndLine, out string endLine);
|
command.Properties.TryGetValue(IssueCommandProperties.EndLine, out string endLine);
|
||||||
@@ -667,28 +627,28 @@ namespace GitHub.Runner.Worker
|
|||||||
column = endColumn;
|
column = endColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasStartLine && hasColumn)
|
if (!hasStartLine && hasColumn)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' can only be set if '{IssueCommandProperties.Line}' value is provided.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' can only be set if '{IssueCommandProperties.Line}' value is provided.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasEndLine && line != endLine && hasColumn)
|
if (hasEndLine && line != endLine && hasColumn)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' cannot be set if '{IssueCommandProperties.Line}' and '{IssueCommandProperties.EndLine}' are different values.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.Column}' and '{IssueCommandProperties.EndColumn}' cannot be set if '{IssueCommandProperties.Line}' and '{IssueCommandProperties.EndLine}' are different values.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
command.Properties.Remove(IssueCommandProperties.EndColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasStartLine && hasEndLine && endLineNumber < lineNumber)
|
if (hasStartLine && hasEndLine && endLineNumber < lineNumber)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndLine}' cannot be less than '{IssueCommandProperties.Line}'.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndLine}' cannot be less than '{IssueCommandProperties.Line}'.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Line);
|
command.Properties.Remove(IssueCommandProperties.Line);
|
||||||
command.Properties.Remove(IssueCommandProperties.EndLine);
|
command.Properties.Remove(IssueCommandProperties.EndLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasStartColumn && hasEndColumn && endColumnNumber < columnNumber)
|
if (hasStartColumn && hasEndColumn && endColumnNumber < columnNumber)
|
||||||
{
|
{
|
||||||
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndColumn}' cannot be less than '{IssueCommandProperties.Column}'.");
|
context.Debug($"Invalid {command.Command} command value. '{IssueCommandProperties.EndColumn}' cannot be less than '{IssueCommandProperties.Column}'.");
|
||||||
command.Properties.Remove(IssueCommandProperties.Column);
|
command.Properties.Remove(IssueCommandProperties.Column);
|
||||||
|
|||||||
@@ -633,12 +633,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled.
|
catch (Exception ex) when (!executionContext.CancellationToken.IsCancellationRequested) // Do not retry if the run is canceled.
|
||||||
{
|
{
|
||||||
// UnresolvableActionDownloadInfoException is a 422 client error, don't retry
|
if (attempt < 3)
|
||||||
// Some possible cases are:
|
|
||||||
// * Repo is rate limited
|
|
||||||
// * Repo or tag doesn't exist, or isn't public
|
|
||||||
// * Policy validation failed
|
|
||||||
if (attempt < 3 && !(ex is WebApi.UnresolvableActionDownloadInfoException))
|
|
||||||
{
|
{
|
||||||
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
|
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
|
||||||
executionContext.Debug(ex.ToString());
|
executionContext.Debug(ex.ToString());
|
||||||
@@ -654,7 +649,6 @@ namespace GitHub.Runner.Worker
|
|||||||
// Some possible cases are:
|
// Some possible cases are:
|
||||||
// * Repo is rate limited
|
// * Repo is rate limited
|
||||||
// * Repo or tag doesn't exist, or isn't public
|
// * Repo or tag doesn't exist, or isn't public
|
||||||
// * Policy validation failed
|
|
||||||
if (ex is WebApi.UnresolvableActionDownloadInfoException)
|
if (ex is WebApi.UnresolvableActionDownloadInfoException)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ namespace GitHub.Runner.Worker
|
|||||||
Dictionary<string, VariableValue> JobOutputs { get; }
|
Dictionary<string, VariableValue> JobOutputs { get; }
|
||||||
ActionsEnvironmentReference ActionsEnvironment { get; }
|
ActionsEnvironmentReference ActionsEnvironment { get; }
|
||||||
List<ActionsStepTelemetry> ActionsStepsTelemetry { get; }
|
List<ActionsStepTelemetry> ActionsStepsTelemetry { get; }
|
||||||
List<JobTelemetry> JobTelemetry { get; }
|
|
||||||
DictionaryContextData ExpressionValues { get; }
|
DictionaryContextData ExpressionValues { get; }
|
||||||
IList<IFunctionInfo> ExpressionFunctions { get; }
|
IList<IFunctionInfo> ExpressionFunctions { get; }
|
||||||
JobContext JobContext { get; }
|
JobContext JobContext { get; }
|
||||||
@@ -151,7 +150,6 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public ActionsEnvironmentReference ActionsEnvironment { get; private set; }
|
public ActionsEnvironmentReference ActionsEnvironment { get; private set; }
|
||||||
public List<ActionsStepTelemetry> ActionsStepsTelemetry { get; private set; }
|
public List<ActionsStepTelemetry> ActionsStepsTelemetry { get; private set; }
|
||||||
public List<JobTelemetry> JobTelemetry { get; private set; }
|
|
||||||
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
|
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
|
||||||
public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>();
|
public IList<IFunctionInfo> ExpressionFunctions { get; } = new List<IFunctionInfo>();
|
||||||
|
|
||||||
@@ -296,7 +294,6 @@ namespace GitHub.Runner.Worker
|
|||||||
child.ContextName = contextName;
|
child.ContextName = contextName;
|
||||||
child.EmbeddedId = embeddedId;
|
child.EmbeddedId = embeddedId;
|
||||||
child.SiblingScopeName = siblingScopeName;
|
child.SiblingScopeName = siblingScopeName;
|
||||||
child.JobTelemetry = JobTelemetry;
|
|
||||||
if (intraActionState == null)
|
if (intraActionState == null)
|
||||||
{
|
{
|
||||||
child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -653,8 +650,6 @@ namespace GitHub.Runner.Worker
|
|||||||
// ActionsStepTelemetry
|
// ActionsStepTelemetry
|
||||||
ActionsStepsTelemetry = new List<ActionsStepTelemetry>();
|
ActionsStepsTelemetry = new List<ActionsStepTelemetry>();
|
||||||
|
|
||||||
JobTelemetry = new List<JobTelemetry>();
|
|
||||||
|
|
||||||
// Service container info
|
// Service container info
|
||||||
Global.ServiceContainers = new List<ContainerInfo>();
|
Global.ServiceContainers = new List<ContainerInfo>();
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ namespace GitHub.Runner.Worker
|
|||||||
"repository",
|
"repository",
|
||||||
"repository_owner",
|
"repository_owner",
|
||||||
"retention_days",
|
"retention_days",
|
||||||
"run_attempt",
|
|
||||||
"run_id",
|
"run_id",
|
||||||
"run_number",
|
"run_number",
|
||||||
"server_url",
|
"server_url",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@@ -107,9 +106,6 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
jobContext.SetRunnerContext("os", VarUtil.OS);
|
jobContext.SetRunnerContext("os", VarUtil.OS);
|
||||||
|
|
||||||
var runnerSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
|
|
||||||
jobContext.SetRunnerContext("name", runnerSettings.AgentName);
|
|
||||||
|
|
||||||
string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools);
|
string toolsDirectory = HostContext.GetDirectory(WellKnownDirectory.Tools);
|
||||||
Directory.CreateDirectory(toolsDirectory);
|
Directory.CreateDirectory(toolsDirectory);
|
||||||
jobContext.SetRunnerContext("tool_cache", toolsDirectory);
|
jobContext.SetRunnerContext("tool_cache", toolsDirectory);
|
||||||
@@ -229,15 +225,8 @@ namespace GitHub.Runner.Worker
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load any upgrade telemetry
|
|
||||||
LoadFromTelemetryFile(jobContext.JobTelemetry);
|
|
||||||
|
|
||||||
// Make sure we don't submit secrets as telemetry
|
|
||||||
MaskTelemetrySecrets(jobContext.JobTelemetry);
|
|
||||||
|
|
||||||
Trace.Info("Raising job completed event.");
|
Trace.Info("Raising job completed event.");
|
||||||
var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs, jobContext.ActionsEnvironment, jobContext.ActionsStepsTelemetry, jobContext.JobTelemetry);
|
var jobCompletedEvent = new JobCompletedEvent(message.RequestId, message.JobId, result, jobContext.JobOutputs, jobContext.ActionsEnvironment, jobContext.ActionsStepsTelemetry);
|
||||||
|
|
||||||
|
|
||||||
var completeJobRetryLimit = 5;
|
var completeJobRetryLimit = 5;
|
||||||
var exceptions = new List<Exception>();
|
var exceptions = new List<Exception>();
|
||||||
@@ -281,38 +270,6 @@ namespace GitHub.Runner.Worker
|
|||||||
throw new AggregateException(exceptions);
|
throw new AggregateException(exceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MaskTelemetrySecrets(List<JobTelemetry> jobTelemetry)
|
|
||||||
{
|
|
||||||
foreach (var telemetryItem in jobTelemetry)
|
|
||||||
{
|
|
||||||
telemetryItem.Message = HostContext.SecretMasker.MaskSecrets(telemetryItem.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadFromTelemetryFile(List<JobTelemetry> jobTelemetry)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var telemetryFilePath = HostContext.GetConfigFile(WellKnownConfigFile.Telemetry);
|
|
||||||
if (File.Exists(telemetryFilePath))
|
|
||||||
{
|
|
||||||
var telemetryData = File.ReadAllText(telemetryFilePath, Encoding.UTF8);
|
|
||||||
var telemetry = new JobTelemetry
|
|
||||||
{
|
|
||||||
Message = $"Runner File Telemetry:\n{telemetryData}",
|
|
||||||
Type = JobTelemetryType.General
|
|
||||||
};
|
|
||||||
jobTelemetry.Add(telemetry);
|
|
||||||
IOUtil.DeleteFile(telemetryFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Trace.Error("Error when trying to load telemetry from telemetry file");
|
|
||||||
Trace.Error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ShutdownQueue(bool throwOnFailure)
|
private async Task ShutdownQueue(bool throwOnFailure)
|
||||||
{
|
{
|
||||||
if (_jobServerQueue != null)
|
if (_jobServerQueue != null)
|
||||||
|
|||||||
@@ -153,19 +153,6 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
{
|
{
|
||||||
this.ActionsEnvironment = actionsEnvironment;
|
this.ActionsEnvironment = actionsEnvironment;
|
||||||
this.ActionsStepsTelemetry = actionsStepsTelemetry;
|
this.ActionsStepsTelemetry = actionsStepsTelemetry;
|
||||||
}
|
|
||||||
|
|
||||||
public JobCompletedEvent(
|
|
||||||
Int64 requestId,
|
|
||||||
Guid jobId,
|
|
||||||
TaskResult result,
|
|
||||||
Dictionary<String, VariableValue> outputs,
|
|
||||||
ActionsEnvironmentReference actionsEnvironment,
|
|
||||||
List<ActionsStepTelemetry> actionsStepsTelemetry,
|
|
||||||
List<JobTelemetry> jobTelemetry)
|
|
||||||
: this(requestId, jobId, result, outputs, actionsEnvironment, actionsStepsTelemetry)
|
|
||||||
{
|
|
||||||
this.JobTelemetry = jobTelemetry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
@@ -202,13 +189,6 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public List<JobTelemetry> JobTelemetry
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Information about a job run on the runner
|
|
||||||
/// </summary>
|
|
||||||
[DataContract]
|
|
||||||
public class JobTelemetry
|
|
||||||
{
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string Message { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public JobTelemetryType Type { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
public enum JobTelemetryType
|
|
||||||
{
|
|
||||||
[EnumMember]
|
|
||||||
General = 0,
|
|
||||||
|
|
||||||
[EnumMember]
|
|
||||||
ActionCommand = 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -161,8 +161,7 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
"--work", _expectedWorkFolder,
|
"--work", _expectedWorkFolder,
|
||||||
"--auth", _expectedAuthType,
|
"--auth", _expectedAuthType,
|
||||||
"--token", _expectedToken,
|
"--token", _expectedToken,
|
||||||
"--labels", userLabels,
|
"--labels", userLabels
|
||||||
"--ephemeral",
|
|
||||||
});
|
});
|
||||||
trace.Info("Constructed.");
|
trace.Info("Constructed.");
|
||||||
_store.Setup(x => x.IsConfigured()).Returns(false);
|
_store.Setup(x => x.IsConfigured()).Returns(false);
|
||||||
@@ -180,7 +179,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
Assert.True(s.AgentName.Equals(_expectedAgentName));
|
Assert.True(s.AgentName.Equals(_expectedAgentName));
|
||||||
Assert.True(s.PoolId.Equals(_secondRunnerGroupId));
|
Assert.True(s.PoolId.Equals(_secondRunnerGroupId));
|
||||||
Assert.True(s.WorkFolder.Equals(_expectedWorkFolder));
|
Assert.True(s.WorkFolder.Equals(_expectedWorkFolder));
|
||||||
Assert.True(s.Ephemeral.Equals(true));
|
|
||||||
|
|
||||||
// validate GetAgentPoolsAsync gets called twice with automation pool type
|
// validate GetAgentPoolsAsync gets called twice with automation pool type
|
||||||
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));
|
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));
|
||||||
|
|||||||
@@ -264,170 +264,6 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Runner")]
|
|
||||||
public async void RenewJobRequestNewAgentNameUpdatesSettings()
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
using (var hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
var count = 0;
|
|
||||||
var oldName = "OldName";
|
|
||||||
var newName = "NewName";
|
|
||||||
var oldSettings = new RunnerSettings { AgentName = oldName };
|
|
||||||
var reservedAgent = new TaskAgentReference { Name = newName };
|
|
||||||
|
|
||||||
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
|
|
||||||
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
|
|
||||||
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var request = new Mock<TaskAgentJobRequest>();
|
|
||||||
request.Object.ReservedAgent = reservedAgent;
|
|
||||||
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
||||||
Assert.NotNull(lockUntilProperty);
|
|
||||||
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
|
|
||||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
|
||||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
|
||||||
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
|
|
||||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
||||||
.Returns(() =>
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
if (count < 5)
|
|
||||||
{
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
else if (count == 5 || count == 6 || count == 7)
|
|
||||||
{
|
|
||||||
throw new TimeoutException("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cancellationTokenSource.Cancel();
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var jobDispatcher = new JobDispatcher();
|
|
||||||
jobDispatcher.Initialize(hc);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
_configurationStore.Verify(x => x.SaveSettings(It.Is<RunnerSettings>(settings => settings.AgentName == newName)), Times.Once);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Runner")]
|
|
||||||
public async void RenewJobRequestSameAgentNameIgnored()
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
using (var hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
var count = 0;
|
|
||||||
var oldName = "OldName";
|
|
||||||
var newName = "OldName";
|
|
||||||
var oldSettings = new RunnerSettings { AgentName = oldName };
|
|
||||||
var reservedAgent = new TaskAgentReference { Name = newName };
|
|
||||||
|
|
||||||
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
|
|
||||||
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
|
|
||||||
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var request = new Mock<TaskAgentJobRequest>();
|
|
||||||
request.Object.ReservedAgent = reservedAgent;
|
|
||||||
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
||||||
Assert.NotNull(lockUntilProperty);
|
|
||||||
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
|
|
||||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
|
||||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
|
||||||
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
|
|
||||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
||||||
.Returns(() =>
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
if (count < 5)
|
|
||||||
{
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
else if (count == 5 || count == 6 || count == 7)
|
|
||||||
{
|
|
||||||
throw new TimeoutException("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cancellationTokenSource.Cancel();
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var jobDispatcher = new JobDispatcher();
|
|
||||||
jobDispatcher.Initialize(hc);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
_configurationStore.Verify(x => x.SaveSettings(It.IsAny<RunnerSettings>()), Times.Never);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Runner")]
|
|
||||||
public async void RenewJobRequestNullAgentNameIgnored()
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
using (var hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
var count = 0;
|
|
||||||
var oldName = "OldName";
|
|
||||||
var oldSettings = new RunnerSettings { AgentName = oldName };
|
|
||||||
|
|
||||||
var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnJobTokenExpiredExceptions));
|
|
||||||
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>();
|
|
||||||
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var request = new Mock<TaskAgentJobRequest>();
|
|
||||||
PropertyInfo lockUntilProperty = request.Object.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
||||||
Assert.NotNull(lockUntilProperty);
|
|
||||||
lockUntilProperty.SetValue(request.Object, DateTime.UtcNow.AddMinutes(5));
|
|
||||||
hc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
|
||||||
hc.SetSingleton<IConfigurationStore>(_configurationStore.Object);
|
|
||||||
_configurationStore.Setup(x => x.GetSettings()).Returns(oldSettings);
|
|
||||||
_runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
||||||
.Returns(() =>
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
if (count < 5)
|
|
||||||
{
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
else if (count == 5 || count == 6 || count == 7)
|
|
||||||
{
|
|
||||||
throw new TimeoutException("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cancellationTokenSource.Cancel();
|
|
||||||
return Task.FromResult<TaskAgentJobRequest>(request.Object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var jobDispatcher = new JobDispatcher();
|
|
||||||
jobDispatcher.Initialize(hc);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await jobDispatcher.RenewJobRequestAsync(0, 0, Guid.Empty, Guid.NewGuid().ToString(), firstJobRequestRenewed, cancellationTokenSource.Token);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
_configurationStore.Verify(x => x.SaveSettings(It.IsAny<RunnerSettings>()), Times.Never);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Runner")]
|
[Trait("Category", "Runner")]
|
||||||
|
|||||||
@@ -149,9 +149,6 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
|
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
|
||||||
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
|
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
|
||||||
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
|
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
|
||||||
|
|
||||||
// verify that we didn't try to delete local settings file (since we're not ephemeral)
|
|
||||||
_configurationManager.Verify(x => x.DeleteLocalRunnerConfig(), Times.Never());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,9 +312,6 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
|
_messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once());
|
||||||
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
|
_messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once());
|
||||||
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
|
_messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny<TaskAgentMessage>()), Times.AtLeastOnce());
|
||||||
|
|
||||||
// verify that we did try to delete local settings file (since we're ephemeral)
|
|
||||||
_configurationManager.Verify(x => x.DeleteLocalRunnerConfig(), Times.Once());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
@@ -84,7 +83,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns((string tag, string line) =>
|
.Returns((string tag, string line) =>
|
||||||
{
|
{
|
||||||
@@ -107,88 +105,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("stop-commands", "1")]
|
|
||||||
[InlineData("", "1")]
|
|
||||||
[InlineData("set-env", "1")]
|
|
||||||
[InlineData("stop-commands", "true")]
|
|
||||||
[InlineData("", "true")]
|
|
||||||
[InlineData("set-env", "true")]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void StopProcessCommand__AllowsInvalidStopTokens__IfEnvVarIsSet(string invalidToken, string allowUnsupportedStopCommandTokens)
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
|
|
||||||
var expressionValues = new DictionaryContextData
|
|
||||||
{
|
|
||||||
["env"] =
|
|
||||||
#if OS_WINDOWS
|
|
||||||
new DictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }}
|
|
||||||
#else
|
|
||||||
new CaseSensitiveDictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(expressionValues);
|
|
||||||
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
|
|
||||||
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("stop-commands")]
|
|
||||||
[InlineData("")]
|
|
||||||
[InlineData("set-env")]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void StopProcessCommand__FailOnInvalidStopTokens(string invalidToken)
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
_ec.Object.Global.EnvironmentVariables = new Dictionary<string, string>();
|
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
|
||||||
_ec.Setup(x => x.JobTelemetry).Returns(new List<JobTelemetry>());
|
|
||||||
Assert.Throws<Exception>(() => _commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{invalidToken}", null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void StopProcessCommandAcceptsValidToken()
|
|
||||||
{
|
|
||||||
var validToken = "randomToken";
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
|
|
||||||
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void StopProcessCommandMasksValidTokenForEntireRun()
|
|
||||||
{
|
|
||||||
var validToken = "randomToken";
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(GetExpressionValues());
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::stop-commands::{validToken}", null));
|
|
||||||
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
|
||||||
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
|
|
||||||
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, $"::{validToken}::", null));
|
|
||||||
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null));
|
|
||||||
Assert.Equal("***", hc.SecretMasker.MaskSecrets(validToken));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -286,15 +202,15 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
var registeredCommands = new HashSet<string>(new string[1] { "warning" });
|
var registeredCommands = new HashSet<string>(new string[1]{ "warning" });
|
||||||
ActionCommand command;
|
ActionCommand command;
|
||||||
|
|
||||||
// Columns when lines are different
|
// Columns when lines are different
|
||||||
ActionCommand.TryParseV2("::warning line=1,endLine=2,col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
ActionCommand.TryParseV2("::warning line=1,endLine=2,col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
||||||
Assert.Equal("1", command.Properties["col"]);
|
Assert.Equal("1", command.Properties["col"]);
|
||||||
IssueCommandExtension.ValidateLinesAndColumns(command, _ec.Object);
|
IssueCommandExtension.ValidateLinesAndColumns(command, _ec.Object);
|
||||||
Assert.False(command.Properties.ContainsKey("col"));
|
Assert.False(command.Properties.ContainsKey("col"));
|
||||||
|
|
||||||
// No lines with columns
|
// No lines with columns
|
||||||
ActionCommand.TryParseV2("::warning col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
ActionCommand.TryParseV2("::warning col=1,endColumn=2::this is a warning", registeredCommands, out command);
|
||||||
Assert.Equal("1", command.Properties["col"]);
|
Assert.Equal("1", command.Properties["col"]);
|
||||||
@@ -459,19 +375,5 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
return hostContext;
|
return hostContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DictionaryContextData GetExpressionValues()
|
|
||||||
{
|
|
||||||
return new DictionaryContextData
|
|
||||||
{
|
|
||||||
["env"] =
|
|
||||||
#if OS_WINDOWS
|
|
||||||
new DictionaryContextData()
|
|
||||||
#else
|
|
||||||
new CaseSensitiveDictionaryContextData()
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.283.2
|
2.282.1
|
||||||
|
|||||||
Reference in New Issue
Block a user