Compare commits

...

78 Commits

Author SHA1 Message Date
TingluoHuang
5b39316bae Release 2.300.2 runner. 2022-12-19 14:20:13 -05:00
Tingluo Huang
69c8fab013 Revert "Use VssHttpClient instead of RawHttpClient (#2328)" (#2329)
This reverts commit edb3681ccc.
2022-12-19 12:05:52 -05:00
Yang Cao
edb3681ccc Use VssHttpClient instead of RawHttpClient (#2328) 2022-12-19 17:16:33 +01:00
Ferenc Hammerl
10aafef52f Update releaseVersion 2022-12-19 17:09:57 +01:00
Ferenc Hammerl
2b89a7ffea Release notes for 2.300.1 (#2325)
* Update runnerversion

* Update releaseNote.md
2022-12-19 17:08:26 +01:00
Bethany
ffae5b7a54 Re-add file size check prior to reading file (#2321)
* Re-add file size check prior to reading file

* Remove redundant file size check
2022-12-19 14:44:34 +01:00
Ava Stancu
b3e56206cf Update releaseVersion 2022-12-14 10:43:33 +02:00
Ava Stancu
6b9e8a6be4 prepare release notes for 2.300.0 (#2312)
* Update runner version

* Update releaseNote.md

* Update releaseNote.md

* Update releaseNote.md

Co-authored-by: JoannaaKL <joannaakl@github.com>

* Update releaseNote.md

* Update releaseNote.md

Co-authored-by: JoannaaKL <joannaakl@github.com>
Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
2022-12-14 10:33:02 +02:00
Brittany Ellich
f41f5d259d Use results for uploading step summaries (#2301)
* Use results service for uploading step summaries

* Use results summary over generic results naming convention

* Apply suggestions from code review

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Addressing feedback

* Fix merge issue

* Remove empty line

* Update Results json objects to use snake case

* Adding the reference

Co-authored-by: Yang Cao <yacaovsnc@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
2022-12-14 09:28:33 +01:00
Ava Stancu
369a4eccad Made worker logs available to stdout (#2307)
* Made worker logs available to stdout

* Log Worker Standard out line by line

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
2022-12-08 16:23:52 -05:00
Ava Stancu
088981a372 Listener stdout logging (#2291)
* Added env variable to control wether the terminal is silent

* Log to stdout if PrintLogToStdout is enabled

* Extracted console logging to stdouttracelistener

* Remove useless usings

* Rewrite TraceListener as superclass

* Only print to stdout if env is set

* Add comment for Console.Out

* Format Listener

* Revert var name in terminal

* Check env in hostcontext instead of Tracing constructor

* Remove superclass & dupe logging code

* Log hostType

* Readonly '_' prefix 'hostType'

* Fix test

* Revert Terminal change

Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
2022-12-06 16:16:00 +01:00
Nikola Jokic
852a80fcbd Return exit code when MANUALLY_TRAP_SIG is exported (#2285) 2022-11-28 11:33:01 -05:00
Ferenc Hammerl
63640e91fa Backfill notes and version from 'Release 2.299.1 runner.' (#2277)
* Release 2.299.1 runner.

* Fix typo in releaseNote

Co-authored-by: TingluoHuang <TingluoHuang@github.com>
2022-11-22 15:05:47 +01:00
Nikola Jokic
9122fe7e10 added to lowercase on setting github.action_status (#1944) 2022-11-22 15:05:32 +01:00
Nikola Jokic
6b8452170a (delete.sh) Loggin repaired and made runner_name optional defaulting to hostname (#1871)
* Loggin repaired and made runner_name optional defaulting to hostname

* Update scripts/delete.sh

Co-authored-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

Co-authored-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2022-11-22 14:47:22 +01:00
Nikola Jokic
cc49e65356 added replace to allow create latest svc to apply --replace flag (#2273) 2022-11-22 14:46:11 +01:00
Tatyana Kostromskaya
1632e4a343 Support runner upgrade messages (#2231)
Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
2022-11-21 16:17:47 +01:00
Ava Stancu
b465102e7f Updated info on process for requesting features and enhancements (#2259) 2022-11-18 16:07:59 +01:00
Amit Rathi
98c857b927 expose github.actor_id, github.workflow_ref & github.workflow_sha as environment variable (#2249)
* expose workflow refs/sha  as environment variables

* fixes environment variable ordering

* job_workflow_ref/sha aren't available in gh ctx
2022-11-17 11:11:52 -05:00
Chris Patterson
dda53af485 Small change to Node.js 12 deprecation message (#2262)
* Small change to Node.js 12 deprecation message

* Update src/Runner.Common/Constants.cs
2022-11-16 16:25:59 +01:00
Tingluo Huang
c0bc4c02f8 Add RUNNER_ALLOW_RUNASROOT=1 to dockerfile (#2254) 2022-11-15 12:38:11 -05:00
Nikola Jokic
c6630ce285 Dockerfile and workflow change for runner image (#2250)
* Workflow

* add back github-token to id:image

* added handle to image name

* removed core require

* multi line added :latest

* added label

* added repository_owner in IMAGE_NAME

* with the release

* release

* markdown label description

* Remove markdown desciprion

* Remove double quotes in labels

* Reverted back releaseVersion
2022-11-10 12:08:13 -05:00
Tingluo Huang
40ed7f8a40 Forward parameters into run() func in run.sh. (#2240) 2022-11-02 18:13:40 -04:00
Cory Miller
7f5067a8b5 prepare release notes for 2.299.0 (#2239) 2022-11-02 18:55:03 +00:00
Tingluo Huang
4adaf9c1e6 Use Global.Variables instead of JobContext and include action path/ref in the message. (#2214)
* Use Global.Variables instead of JobContext and include action path/ref in the message.

* encoding

* .
2022-11-02 09:40:19 -04:00
Nikola Jokic
d301c06a7e run.sh installs SIGINT and SIGTERM traps to gracefully stop runner (#2233)
* run.sh installs SIGINT and SIGTERM traps to gracefully stop runner

* replaced trap to force wait for child processes and to send kill to run-helper instead of Runner.Listener

* run with signal handling if RUNNER_MANUALLY_TRAP_SIG is set

* Update src/Misc/layoutroot/run.sh

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

Co-authored-by: Tingluo Huang <tingluohuang@github.com>
2022-11-02 09:28:14 -04:00
JoannaaKL
3e196355de Allow the container.image to be empty (#2235)
* Allow container.image to be null/empty

* Remove unnecessary workflow type

* Update src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs

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

* Rename ConvertToJobContainer to ConvertToContainer
It converts serviceContainers too

* Remove unused parameter
AllowExpressions was always false

* Allow service in yaml with empty string for value

* Don't attempt to start services without an image

* Improve error messages

* Revert "Remove unused parameter"

This reverts commit f4ab2d50d0.

* Revert "Rename ConvertToJobContainer to ConvertToContainer"

This reverts commit ffc62f8343.

* Fix revert merge conflict

* Removed info logs

* Added info log for services without container images

Co-authored-by: moonblade <moonblade168@gmail.com>
Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
Co-authored-by: Ava Stancu <avastancu@github.com>
2022-11-02 11:27:37 +01:00
Tauhid Anjum
dad7ad0384 Setting debug using GitHub Action variables (#2234) 2022-10-31 09:51:33 -04:00
Cory Miller
b18bda773f Add generateServiceConfig option for configure command (#2226)
For runners that are already configured but need to add systemd services after the fact, a new command option is added to generate the file only. Once generated, ./svc.sh install and other commands will be available.

This also adds support for falling back to the tenant name in the Actions URL in cases when the GitHub URL is not provided, such as for our hosted larger runners.
2022-10-26 08:48:23 -04:00
Cory Miller
3fc993da59 Disable linter errors (#2216) 2022-10-20 18:59:39 -04:00
Cory Miller
5421fe3f71 Add linter workflow (#2213) 2022-10-18 12:14:27 -04:00
Cory Miller
b87b4aac5c Fix IDE0090 (#2211) 2022-10-18 10:54:08 -04:00
Ferenc Hammerl
daba735b52 Add runner devcontainer (#2187)
Add runner devcontainer.json definition. Sets up dotnet, docker-in-docker, omnisharp and some vscode extensions
2022-10-17 14:03:24 +02:00
Ben Sherman
46ce960fd2 Fix markup for support link (#2114) 2022-10-13 16:56:10 +02:00
Ferenc Hammerl
f4b7f91c21 Allow '--disableupdate' in create-latest-svc.sh (#2201)
* Allow '--disableupdate' in create-latest-svc.sh

* Echo '--disableupdate' when used
2022-10-13 12:40:12 +02:00
Ava Stancu
ff65183e43 Avastancu/joannaakl/service container error log (#2110) (#2182)
* Avastancu/joannaakl/service container error log (#2110)

* adding support for a service container docker logs

* Adding Unit test to ContainerOperationProvider

* Adding another test to ContainerOperationProvider

* placed the docker logs output in dedicated ##group section

* Removed the exception thrown if the service container was not healthy

* Removed duplicated logging to the executionContext

* Updated the container logs sub-section message

* Print service containers only if they were healthy
Unhealthy service logs are printed in ContainerHealthCheckLogs called prior to this step.

* Removed recently added method to inspect docker logs
The method was doing the same thing as the existing DockerLogs method.

* Added execution context error
This will make a failed health check more visible in the UI without disrupting the execution of the program.

* Removing the section 'Waiting for all services to be ready'

Since nested subsections are not being displayed properly and we already need one subsection per service error.

* Update src/Runner.Worker/Container/DockerCommandManager.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Update src/Test/L0/TestHostContext.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Change the logic for printing Service Containers logs

Service container logs will be printed in the 'Start containers' section only if there is an error.
Healthy services will have their logs printed in the 'Stop Containers' section.

* Removed unused import

* Added back section group.

* Moved service containers error logs to separate group sections

* Removed the test testing the old logic flow.

* Remove unnecessary 'IsAnyUnhealthy' flag

* Remove printHello() function

* Add newline to TestHostContext

* Remove unnecessary field 'UnhealthyContainers'

* Rename boolean flag indicating service container failure

* Refactor healthcheck logic to separate method to enable unit testing.

* Remove the default value for bool variable

* Update src/Runner.Worker/ContainerOperationProvider.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Update src/Runner.Worker/ContainerOperationProvider.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Rename Healthcheck back to ContainerHealthcheck

* Make test sequential

* Unextract the container error logs method

* remove test asserting thrown exception

* Add configure await

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Add back test asserting exception

* Check service exit code if there is no healtcheck configured

* Remove unnecessary healthcheck for healthy service container

* Revert "Check service exit code if there is no healtcheck configured"

This reverts commit fec24e8341.

Co-authored-by: Ava S <avastancu@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Do not fail service containers without the healthcheck

Co-authored-by: JoannaaKL <joannaakl@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
2022-10-11 12:09:24 +02:00
Ferenc Hammerl
0f13055428 Backfill notes from release branch 2.298.2 (wrong branch name) (#2180)
* Update releaseNote.md

* Update runnerversion
2022-10-07 16:05:56 +02:00
Yashwanth Anantharaju
252f4de577 changes to support specific run service URL (#2158)
* changes to support run service url

* feedback
2022-10-06 10:28:32 -04:00
Robin Neatherway
b6a46f2114 Correct grammar in archive extraction error message (#2184) 2022-10-06 08:20:30 -04:00
Ferenc Hammerl
2145432f81 Revert "Avastancu/joannaakl/service container error log (#2110)" (#2179)
This reverts commit 949269104d.
2022-10-05 15:00:22 +00:00
Ferenc Hammerl
86d0ee8389 Backport 2.298.1 (#2175)
* Update releaseNote.md

* Update runnerversion
2022-10-04 15:20:35 +00:00
Ferenc Hammerl
1379ed2c72 Fix incorrect template vars to show SHA for WIN-ARM64 (#2171) 2022-10-04 17:05:18 +02:00
Francesco Renzi
4935be5526 Prepare release notes for v2.298.0 (#2169) 2022-10-04 12:09:58 +00:00
Francesco Renzi
920fba93dc Add warning for users using deprecated commands (#2164) 2022-10-04 12:14:22 +01:00
JoannaaKL
949269104d Avastancu/joannaakl/service container error log (#2110)
* adding support for a service container docker logs

* Adding Unit test to ContainerOperationProvider

* Adding another test to ContainerOperationProvider

* placed the docker logs output in dedicated ##group section

* Removed the exception thrown if the service container was not healthy

* Removed duplicated logging to the executionContext

* Updated the container logs sub-section message

* Print service containers only if they were healthy
Unhealthy service logs are printed in ContainerHealthCheckLogs called prior to this step.

* Removed recently added method to inspect docker logs
The method was doing the same thing as the existing DockerLogs method.

* Added execution context error
This will make a failed health check more visible in the UI without disrupting the execution of the program.

* Removing the section 'Waiting for all services to be ready'

Since nested subsections are not being displayed properly and we already need one subsection per service error.

* Update src/Runner.Worker/Container/DockerCommandManager.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Update src/Test/L0/TestHostContext.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Change the logic for printing Service Containers logs

Service container logs will be printed in the 'Start containers' section only if there is an error.
Healthy services will have their logs printed in the 'Stop Containers' section.

* Removed unused import

* Added back section group.

* Moved service containers error logs to separate group sections

* Removed the test testing the old logic flow.

* Remove unnecessary 'IsAnyUnhealthy' flag

* Remove printHello() function

* Add newline to TestHostContext

* Remove unnecessary field 'UnhealthyContainers'

* Rename boolean flag indicating service container failure

* Refactor healthcheck logic to separate method to enable unit testing.

* Remove the default value for bool variable

* Update src/Runner.Worker/ContainerOperationProvider.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Update src/Runner.Worker/ContainerOperationProvider.cs

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Rename Healthcheck back to ContainerHealthcheck

* Make test sequential

* Unextract the container error logs method

* remove test asserting thrown exception

* Add configure await

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

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

Co-authored-by: Tingluo Huang <tingluohuang@github.com>

* Add back test asserting exception

* Check service exit code if there is no healtcheck configured

* Remove unnecessary healthcheck for healthy service container

* Revert "Check service exit code if there is no healtcheck configured"

This reverts commit fec24e8341.

Co-authored-by: Ava S <avastancu@github.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
2022-10-03 17:50:20 +02:00
Tauhid Anjum
dca4f67143 Adding a new vars context for non-secret variables (#2096)
* Adding a new vars context for non-secret variables

* Fix test case

* Trigger checks

* Remove variables from env context and environment varibale

* remove extra references

* Add prefix handling to configuration variables

* Fix test cases

* Consume variables using vars in context data

* removed action_yaml changes
2022-09-30 09:37:47 -04:00
Thomas Boop
01ff38f975 2.297.0 release notes (#2155)
* 2.297.0 release notes
2022-09-26 11:22:05 -04:00
Tatyana Kostromskaya
bc67f99bae Add link to blog post to node 12 warn (#2156) 2022-09-26 17:05:29 +02:00
Thomas Boop
ae2f4a6f27 POC: Windows arm64 runner build (#2022)
Prerelease for windows-arm64 runner build
2022-09-26 09:20:43 -04:00
Francesco Renzi
15cbadb4af Add file commands for save-state and set-output (#2118) 2022-09-26 10:17:46 +01:00
Thomas Boop
0678e8df09 Add Release branches to pull request spec (#2134) 2022-09-19 15:28:46 +00:00
JoannaaKL
3a1c89715c Remove unused imports (#2126) 2022-09-15 15:55:45 +02:00
JoannaaKL
6cdd27263b Remove unused imports (#2124) 2022-09-15 12:14:10 +02:00
Francesco Renzi
32845a5448 Bump @actions/core from 1.2.6 to 1.9.1 in /src/Misc/expressionFunc/hashFiles (#2123) 2022-09-15 09:43:28 +00:00
Stefan Ruvceski
6e6410d300 fix for issue #2009 - composite summary file (#2077) 2022-09-12 14:51:36 -04:00
Thomas Boop
ed191b78ae Port hotfix to main branch (#2108)
* fix issue with env's overwriting environment

* add release notes

* handle value escaping

* compile regex for runtime perf improvements
2022-09-09 14:32:07 -04:00
Nikola Jokic
75786756bb fix ACTIONS_RUNNER_CONTAINER_HOOKS name in ADR (#2098) 2022-09-06 10:45:00 -04:00
Ferenc Hammerl
5e0c2ef816 2.296.1 Release (#2092) (#2099)
* docker: escape key-value pair as -e KEY and VALUE being environment var

* removed code duplication, removed unused method and test

* add release notes

Co-authored-by: Nikola Jokic <nikola-jokic@github.com>

Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
Co-authored-by: Nikola Jokic <nikola-jokic@github.com>
2022-09-02 15:43:22 +00:00
Nikola Jokic
95459dea5f docker: escape key-value pair as -e KEY and VALUE being environment var (#2091)
* docker: escape key-value pair as -e KEY and VALUE being environment var

* removed code duplication, removed unused method and test
2022-08-31 13:39:58 -04:00
Konrad Pabjan
59894790de Validate lines and columns for Annotations (#2082) 2022-08-24 16:02:51 -04:00
Ava Stancu
cba19c4d7e Release notes for 2.296.0 (#2078)
* Update releaseNote.md

* Update runnerversion
2022-08-23 10:42:40 -04:00
Nikola Jokic
01fd04464d Escaping key and quoting it to avoid key based command injection (#2062)
* escaping key and quoting it to avoid key based command injection

* extracted creation of flags to DockerUtil, with testing included
2022-08-23 10:42:29 -04:00
Tingluo Huang
1cb1779d6b Include step context name and start/finish time in step telemetry (#2069)
* Include step context name in telemetry.

* .
2022-08-22 21:26:52 -04:00
Nicholas Bergesen
42c86665a7 Display full job name and nested workflow details in log (#2049) 2022-08-22 17:20:58 -07:00
Ava Stancu
f9c2bf1dd7 Improved error logs for missing 'using' configuration in metadata file (#2052)
Co-authored-by: Octavia Stancu <avastancu@Octavias-MBP.home>
2022-08-16 17:17:42 +02:00
Ferenc Hammerl
84e7949457 Release notes 2.295.0 (#2046)
* Update releaseNote.md

* Update runnerversion

* Update releaseNote.md
2022-08-10 16:23:51 +02:00
Ferenc Hammerl
694d73d43c Fix broken run-helper update syntax and run-helper not updating on restart (#2050)
* Fix broken syntax in update wait for loop

* Update run-helper after each restart, not only at first
2022-08-09 16:50:52 +02:00
Ferenc Hammerl
352f201c62 Wait for update.sh|cmd to finish instead of waiting 5 seconds - before restarting a runner (#2044)
* update.sh new logic with creating a file and waiting for it for 30 sec

* pr refactor

* removing file when it's detected bu run-helper

* Update src/Misc/layoutroot/run-helper.sh.template

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

* clean up update.finished in Runner.Listener right before it starts a process _update.sh

* pr fix IOUtil.DeleteFile

* self update widnows version - cmd

* same logic for returnCode 4 - ephemeral

* Init var so cmd doesn't run into syntax errors

* Use constants, setting a var messed up ERRORLEVEL

* Use var for updatefile

Co-authored-by: stefanruvceski <ruvceskistefan@github.com>
Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
Co-authored-by: Ferenc Hammerl <hammerl.ferenc@gmail.com>
2022-08-08 23:37:43 +02:00
Pavel Iakovenko
503e50acb9 Support running Actions services on subdomain (#2041) 2022-08-05 13:29:49 -04:00
Lokesh Gopu
813af29886 Include current runner status while getting messages (#2026)
* get messages with runner status

* fixed l0 tests

* PR feedback
2022-07-28 16:42:02 -04:00
Tingluo Huang
72e2107b5e Change the auth challenge 401 to be verbose trace. (#2021) 2022-07-25 16:02:54 -04:00
Tingluo Huang
3567c042ea Bump newtonsoft.json to 13.0.1 (#2012) 2022-07-22 11:21:04 -04:00
Tingluo Huang
e646b6fec4 Move --jitconfig to valid ./run.sh args. (#2013) 2022-07-22 11:14:09 -04:00
aaros-pl
8d2be3d4fa missing .com in pipelines.actions url (#1973) 2022-07-21 23:12:36 -04:00
eric sciple
407a347f83 tweak verbiage (#1977) 2022-06-28 21:03:53 -04:00
ChristopherHX
7e74f8c9d5 fix: GITHUB_ENV in composite (#1794)
* fix: GITHUB_ENV in composite

* fix L0 Test
2022-06-28 20:50:50 -04:00
eric sciple
efdda93aeb Update git troubleshooting (#1971) 2022-06-24 12:12:07 -05:00
eric sciple
1d1998aabb Update description for command line arg "--pat" (#1970) 2022-06-24 11:44:16 -04:00
208 changed files with 7410 additions and 1034 deletions

View File

@@ -0,0 +1,24 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
{
"name": "Actions Runner Devcontainer",
"image": "mcr.microsoft.com/devcontainers/base:focal",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:1": {},
"ghcr.io/devcontainers/features/dotnet": {
"version": "6.0.300"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-azuretools.vscode-docker",
"ms-dotnettools.csharp",
"eamodio.gitlens"
]
}
},
// dotnet restore to install dependencies so OmniSharp works out of the box
// src/Test restores all other projects it references, src/Runner.PluginHost is not one of them
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost",
"remoteUser": "vscode"
}

View File

@@ -1,6 +1,7 @@
# https://editorconfig.org/ # https://editorconfig.org/
[*] [*]
charset = utf-8 # Set default charset to utf-8
insert_final_newline = true # ensure all files end with a single newline insert_final_newline = true # ensure all files end with a single newline
trim_trailing_whitespace = true # attempt to remove trailing whitespace on save trim_trailing_whitespace = true # attempt to remove trailing whitespace on save

View File

@@ -10,7 +10,7 @@ on:
- '**.md' - '**.md'
pull_request: pull_request:
branches: branches:
- '*' - '**'
paths-ignore: paths-ignore:
- '**.md' - '**.md'
@@ -18,7 +18,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ] runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ]
include: include:
- runtime: linux-x64 - runtime: linux-x64
os: ubuntu-latest os: ubuntu-latest
@@ -44,6 +44,10 @@ jobs:
os: windows-2019 os: windows-2019
devScript: ./dev devScript: ./dev
- runtime: win-arm64
os: windows-latest
devScript: ./dev
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@@ -82,7 +86,7 @@ jobs:
run: | run: |
${{ matrix.devScript }} test ${{ matrix.devScript }} test
working-directory: src working-directory: src
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' && matrix.runtime != 'win-arm64'
# Create runner package tar.gz/zip # Create runner package tar.gz/zip
- name: Package Release - name: Package Release
@@ -97,7 +101,7 @@ jobs:
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: runner-package-${{ matrix.runtime }} name: runner-package-${{ matrix.runtime }}
path: | path: |
_package _package
_package_trims/trim_externals _package_trims/trim_externals
_package_trims/trim_runtime _package_trims/trim_runtime

25
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Lint
on:
pull_request:
branches: [ main ]
jobs:
build:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
# Ensure full list of changed files within `super-linter`
fetch-depth: 0
- name: Run linters
uses: github/super-linter@v4
env:
DEFAULT_BRANCH: ${{ github.base_ref }}
DISABLE_ERRORS: true
EDITORCONFIG_FILE_NAME: .editorconfig
LINTER_RULES_PATH: /src/
VALIDATE_ALL_CODEBASE: false
VALIDATE_CSHARP: true

65
.github/workflows/publish-image.yml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Publish Runner Image
on:
workflow_dispatch:
inputs:
runnerVersion:
type: string
description: Version of the runner being installed
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/actions-runner
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Compute image version
id: image
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const inputRunnerVersion = "${{ github.event.inputs.runnerVersion }}"
if (inputRunnerVersion) {
console.log(`Using input runner version ${inputRunnerVersion}`)
core.setOutput('version', inputRunnerVersion);
return
}
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
console.log(`Using runner version ${runnerVersion}`)
core.setOutput('version', runnerVersion);
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v3
with:
context: ./images
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
build-args: |
RUNNER_VERSION=${{ steps.image.outputs.version }}
push: true
labels: |
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
org.opencontainers.image.licenses=MIT

View File

@@ -50,29 +50,33 @@ jobs:
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }} linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }} linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }} win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
win-arm64-sha: ${{ steps.sha.outputs.win-arm64-sha256 }}
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }} osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }} osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }}
linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }} linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }}
linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }} linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }}
linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }} linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }}
win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }} win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }}
win-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-arm64-sha256 }}
osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }} osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }}
osx-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-arm64-sha256 }} osx-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-arm64-sha256 }}
linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }} linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }}
linux-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm64-sha256 }} linux-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm64-sha256 }}
linux-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }} linux-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }}
win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }} win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }}
win-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-arm64-sha256 }}
osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }} osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }}
osx-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-arm64-sha256 }} osx-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-arm64-sha256 }}
linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }} linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }}
linux-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm64-sha256 }} linux-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm64-sha256 }}
linux-arm-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm-sha256 }} linux-arm-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm-sha256 }}
win-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-x64-sha256 }} win-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-x64-sha256 }}
win-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-arm64-sha256 }}
osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }} osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }}
osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }} osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }}
strategy: strategy:
matrix: matrix:
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ] runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64, win-arm64 ]
include: include:
- runtime: linux-x64 - runtime: linux-x64
os: ubuntu-latest os: ubuntu-latest
@@ -89,7 +93,7 @@ jobs:
- runtime: osx-x64 - runtime: osx-x64
os: macOS-latest os: macOS-latest
devScript: ./dev.sh devScript: ./dev.sh
- runtime: osx-arm64 - runtime: osx-arm64
os: macOS-latest os: macOS-latest
devScript: ./dev.sh devScript: ./dev.sh
@@ -98,6 +102,10 @@ jobs:
os: windows-2019 os: windows-2019
devScript: ./dev devScript: ./dev
- runtime: win-arm64
os: windows-latest
devScript: ./dev
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@@ -158,9 +166,9 @@ jobs:
id: sha_noruntime_noexternals id: sha_noruntime_noexternals
name: Compute SHA256 name: Compute SHA256
working-directory: _package_trims/trim_runtime_externals working-directory: _package_trims/trim_runtime_externals
- name: Create trimmedpackages.json for ${{ matrix.runtime }} - name: Create trimmedpackages.json for ${{ matrix.runtime }}
if: matrix.runtime == 'win-x64' if: matrix.runtime == 'win-x64' || matrix.runtime == 'win-arm64'
uses: actions/github-script@0.3.0 uses: actions/github-script@0.3.0
with: with:
github-token: ${{secrets.GITHUB_TOKEN}} github-token: ${{secrets.GITHUB_TOKEN}}
@@ -180,7 +188,7 @@ jobs:
fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages) fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages)
- name: Create trimmedpackages.json for ${{ matrix.runtime }} - name: Create trimmedpackages.json for ${{ matrix.runtime }}
if: matrix.runtime != 'win-x64' if: matrix.runtime != 'win-x64' && matrix.runtime != 'win-arm64'
uses: actions/github-script@0.3.0 uses: actions/github-script@0.3.0
with: with:
github-token: ${{secrets.GITHUB_TOKEN}} github-token: ${{secrets.GITHUB_TOKEN}}
@@ -239,24 +247,28 @@ jobs:
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '') const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion) var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
releaseNote = releaseNote.replace(/<WIN_ARM64_SHA>/g, '${{needs.build.outputs.win-arm64-sha}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}') releaseNote = releaseNote.replace(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<WIN_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.win-arm64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm-sha-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NOEXTERNALS>/g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<WIN_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.win-arm64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-x64-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-x64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_ARM_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm-sha-noruntime}}')
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA_NORUNTIME>/g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}')
releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<WIN_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<WIN_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.win-arm64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<OSX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}')
releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(/<LINUX_X64_SHA_NORUNTIME_NOEXTERNALS>/g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}')
@@ -271,6 +283,7 @@ jobs:
run: | run: |
ls -l ls -l
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
echo "${{needs.build.outputs.win-arm64-sha}} actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
@@ -300,6 +313,16 @@ jobs:
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
- name: Upload Release Asset (win-arm64)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-x64) - name: Upload Release Asset (linux-x64)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -361,6 +384,17 @@ jobs:
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
# Upload release assets (trim externals)
- name: Upload Release Asset (win-arm64-noexternals)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.zip
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-x64-noexternals) - name: Upload Release Asset (linux-x64-noexternals)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -422,6 +456,17 @@ jobs:
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
# Upload release assets (trim runtime)
- name: Upload Release Asset (win-arm64-noruntime)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.zip
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-x64-noruntime) - name: Upload Release Asset (linux-x64-noruntime)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -483,6 +528,17 @@ jobs:
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
# Upload release assets (trim runtime and externals)
- name: Upload Release Asset (win-arm64-noruntime-noexternals)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/_package_trims/trim_runtime_externals/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-x64-noruntime-noexternals) - name: Upload Release Asset (linux-x64-noruntime-noexternals)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -544,6 +600,17 @@ jobs:
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
# Upload release assets (trimmedpackages.json)
- name: Upload Release Asset (win-arm64-trimmedpackages.json)
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ github.workspace }}/win-arm64-trimmedpackages.json
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
asset_content_type: application/octet-stream
- name: Upload Release Asset (linux-x64-trimmedpackages.json) - name: Upload Release Asset (linux-x64-trimmedpackages.json)
uses: actions/upload-release-asset@v1.0.1 uses: actions/upload-release-asset@v1.0.1
env: env:
@@ -593,3 +660,52 @@ jobs:
asset_path: ${{ github.workspace }}/linux-arm64-trimmedpackages.json asset_path: ${{ github.workspace }}/linux-arm64-trimmedpackages.json
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
publish-image:
needs: release
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/actions-runner
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Compute image version
id: image
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const runnerVersion = fs.readFileSync('${{ github.workspace }}/releaseVersion', 'utf8').replace(/\n$/g, '')
console.log(`Using runner version ${runnerVersion}`)
core.setOutput('version', runnerVersion);
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v3
with:
context: ./images
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
build-args: |
RUNNER_VERSION=${{ steps.image.outputs.version }}
push: true
labels: |
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
org.opencontainers.image.licenses=MIT

View File

@@ -22,4 +22,4 @@ Runner releases:
## Contribute ## Contribute
We accept contributions in the form of issues and pull requests. [Read more here](docs/contribute.md) before contributing. We accept contributions in the form of issues and pull requests. The runner typically requires changes across the entire system and we aim for issues in the runner to be entirely self contained and fixable here. Therefore, we will primarily handle bug issues opened in this repo and we kindly request you to create all feature and enhancement requests on the [GitHub Feedback](https://github.com/community/community/discussions/categories/actions-and-packages) page. [Read more about our guidelines here](docs/contribute.md) before contributing.

View File

@@ -16,7 +16,7 @@ We should give them that option, and publish examples how how they can create th
- For example, the current runner overrides `HOME`, we can do that in the hook, but we shouldn't pass that hook as an ENV with the other env's the user has set, as that is not user input, it is how the runner invokes containers - For example, the current runner overrides `HOME`, we can do that in the hook, but we shouldn't pass that hook as an ENV with the other env's the user has set, as that is not user input, it is how the runner invokes containers
## Interface ## Interface
- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOK=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler. - You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOKS=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler.
- There is no partial opt in, you must handle every hook - There is no partial opt in, you must handle every hook
- We will pass a command and some args via `stdin` - We will pass a command and some args via `stdin`
- An exit code of 0 is a success, every other exit code is a failure - An exit code of 0 is a success, every other exit code is a failure

View File

@@ -15,7 +15,7 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
``` ```
curl -v https://api.github.com/api/v3/zen curl -v https://api.github.com/api/v3/zen
curl -v https://vstoken.actions.githubusercontent.com/_apis/health curl -v https://vstoken.actions.githubusercontent.com/_apis/health
curl -v https://pipelines.actions.githubusercontent/_apis/health curl -v https://pipelines.actions.githubusercontent.com/_apis/health
``` ```
- For GitHub Enterprise Server - For GitHub Enterprise Server
@@ -64,4 +64,4 @@ Make sure the runner has access to actions service for GitHub.com or GitHub Ente
## Still not working? ## Still not working?
Contact [GitHub Support](https://support.github.com] if you have further questuons, or log an issue at https://github.com/actions/runner if you think it's a runner issue. Contact [GitHub Support](https://support.github.com) if you have further questuons, or log an issue at https://github.com/actions/runner if you think it's a runner issue.

View File

@@ -20,11 +20,30 @@ The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` be
## How to fix the issue? ## How to fix the issue?
### 1. Check the common network issue ### 1. Check global and system git config
If you are having issues connecting to the server, check your global and system git config for any unexpected authentication headers. You might be seeing an error like:
```
fatal: unable to access 'https://github.com/actions/checkout/': The requested URL returned error: 400
```
The following commands can be used to check for unexpected authentication headers:
```
$ git config --global --list | grep extraheader
http.extraheader=AUTHORIZATION: unexpected_auth_header
$ git config --system --list | grep extraheader
```
The following command can be used to remove the above value: `git config --global --unset http.extraheader`
### 2. Check the common network issue
> Please check the [network doc](./network.md) > Please check the [network doc](./network.md)
### 2. SSL certificate related issue ### 3. SSL certificate related issue
If you are seeing `SSL Certificate problem:` in the log, it means the `git` can't connect to the GitHub server due to SSL handshake failure. If you are seeing `SSL Certificate problem:` in the log, it means the `git` can't connect to the GitHub server due to SSL handshake failure.
> Please check the [SSL cert doc](./sslcert.md) > Please check the [SSL cert doc](./sslcert.md)

View File

@@ -1,6 +1,6 @@
# Contributions # Contributions
We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors. We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors.Please note the runner typically requires changes across the entire system and we aim for issues in the runner to be entirely self contained and fixable here. Therefore, we will primarily handle bug issues opened in this repo and we kindly request you to create all feature and enhancement requests on the [GitHub Feedback](https://github.com/community/community/discussions/categories/actions-and-packages) page.
> IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost. > IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost.
@@ -27,6 +27,8 @@ An ADR is an Architectural Decision Record. This allows consensus on the direct
![Win](res/win_sm.png) Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev sh script) ![Win](res/win_sm.png) Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev sh script)
![Win-arm](res/win_sm.png) Visual Studio 2022 17.3 Preview or later. [Install here](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview)
## Quickstart: Run a job from a real repository ## Quickstart: Run a job from a real repository
If you just want to get from building the sourcecode to using it to execute an action, you will need: If you just want to get from building the sourcecode to using it to execute an action, you will need:

24
images/Dockerfile Normal file
View File

@@ -0,0 +1,24 @@
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
ARG RUNNER_VERSION
ARG RUNNER_ARCH="x64"
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.1.3
RUN apt update -y && apt install curl unzip -y
WORKDIR /actions-runner
RUN curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
&& tar xzf ./runner.tar.gz \
&& rm runner.tar.gz
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
&& unzip ./runner-container-hooks.zip -d ./k8s \
&& rm runner-container-hooks.zip
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0
ENV RUNNER_ALLOW_RUNASROOT=1
ENV RUNNER_MANUALLY_TRAP_SIG=1
WORKDIR /actions-runner
COPY --from=build /actions-runner .

View File

@@ -1,11 +1,17 @@
## Features ## Features
- Added support for a JIT runner config (#1925) - Expose github.actor_id, github.workflow_ref & github.workflow_sha as environment variable (#2249)
- Added `ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION` env option to force actions to run on a specific node version (#1913) - Added worker and listener logs to stdout (#2291, #2307)
## Bugs ## Bugs
- Fixed a bug where container hooks passed in path as a string rather then an array of strings (#1948) - Made github.action_status output lowercase to be consistent with job.status' output (#1944)
## Misc ## Misc
- Minor cleanup of error messages when running container hooks (#1949) - Added small size runner image for ARC (#2250)
- Small change to Node.js 12 deprecation message (#2262)
- Added the option to use the --replace argument to the create-latest-svc.sh (#2273)
- Made runner_name optional defaulting to hostname in delete.sh script (#1871)
- Return exit code when MANUALLY_TRAP_SIG is exported (#2285)
- Use results for uploading step summaries (#2301, #2321, #2328, #2329)
## 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,6 +27,22 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD") [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
``` ```
## [Pre-release] Windows arm64
**Warning:** Windows arm64 runners are currently in preview status and use [unofficial versions of nodejs](https://unofficial-builds.nodejs.org/). They are not intended for production workflows.
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
The following snipped needs to be run on `powershell`:
``` powershell
# Create a folder under the drive root
mkdir \actions-runner ; cd \actions-runner
# Download the latest runner package
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-arm64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-arm64-<RUNNER_VERSION>.zip
# Extract the installer
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-arm64-<RUNNER_VERSION>.zip", "$PWD")
```
## OSX x64 ## OSX x64
``` bash ``` bash
@@ -32,7 +54,7 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
``` ```
## [Pre-release] OSX arm64 (Apple silicon) ## OSX arm64 (Apple silicon)
``` bash ``` bash
# Create a folder # Create a folder
@@ -84,6 +106,7 @@ For additional details about configuring, running, or shutting down the runner p
The SHA-256 checksums for the packages included in this build are shown below: The SHA-256 checksums for the packages included in this build are shown below:
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 --> - actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
- actions-runner-win-arm64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-arm64 --><WIN_ARM64_SHA><!-- END SHA win-arm64 -->
- actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 --> - actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 -->
- actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 --> - actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 -->
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 --> - actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
@@ -91,6 +114,7 @@ The SHA-256 checksums for the packages included in this build are shown below:
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm --> - actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
- actions-runner-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals --> - actions-runner-win-x64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-x64_noexternals --><WIN_X64_SHA_NOEXTERNALS><!-- END SHA win-x64_noexternals -->
- actions-runner-win-arm64-<RUNNER_VERSION>-noexternals.zip <!-- BEGIN SHA win-arm64_noexternals --><WIN_ARM64_SHA_NOEXTERNALS><!-- END SHA win-arm64_noexternals -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-x64_noexternals --> - actions-runner-osx-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noexternals --><OSX_X64_SHA_NOEXTERNALS><!-- END SHA osx-x64_noexternals -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noexternals --><OSX_ARM64_SHA_NOEXTERNALS><!-- END SHA osx-arm64_noexternals --> - actions-runner-osx-arm64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noexternals --><OSX_ARM64_SHA_NOEXTERNALS><!-- END SHA osx-arm64_noexternals -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noexternals --><LINUX_X64_SHA_NOEXTERNALS><!-- END SHA linux-x64_noexternals --> - actions-runner-linux-x64-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noexternals --><LINUX_X64_SHA_NOEXTERNALS><!-- END SHA linux-x64_noexternals -->
@@ -98,6 +122,7 @@ The SHA-256 checksums for the packages included in this build are shown below:
- actions-runner-linux-arm-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noexternals --><LINUX_ARM_SHA_NOEXTERNALS><!-- END SHA linux-arm_noexternals --> - actions-runner-linux-arm-<RUNNER_VERSION>-noexternals.tar.gz <!-- BEGIN SHA linux-arm_noexternals --><LINUX_ARM_SHA_NOEXTERNALS><!-- END SHA linux-arm_noexternals -->
- actions-runner-win-x64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-x64_noruntime --><WIN_X64_SHA_NORUNTIME><!-- END SHA win-x64_noruntime --> - actions-runner-win-x64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-x64_noruntime --><WIN_X64_SHA_NORUNTIME><!-- END SHA win-x64_noruntime -->
- actions-runner-win-arm64-<RUNNER_VERSION>-noruntime.zip <!-- BEGIN SHA win-arm64_noruntime --><WIN_ARM64_SHA_NORUNTIME><!-- END SHA win-arm64_noruntime -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-x64_noruntime --> - actions-runner-osx-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-x64_noruntime --><OSX_X64_SHA_NORUNTIME><!-- END SHA osx-x64_noruntime -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-arm64_noruntime --><OSX_ARM64_SHA_NORUNTIME><!-- END SHA osx-arm64_noruntime --> - actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA osx-arm64_noruntime --><OSX_ARM64_SHA_NORUNTIME><!-- END SHA osx-arm64_noruntime -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-x64_noruntime --><LINUX_X64_SHA_NORUNTIME><!-- END SHA linux-x64_noruntime --> - actions-runner-linux-x64-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-x64_noruntime --><LINUX_X64_SHA_NORUNTIME><!-- END SHA linux-x64_noruntime -->
@@ -105,6 +130,7 @@ The SHA-256 checksums for the packages included in this build are shown below:
- actions-runner-linux-arm-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm_noruntime --><LINUX_ARM_SHA_NORUNTIME><!-- END SHA linux-arm_noruntime --> - actions-runner-linux-arm-<RUNNER_VERSION>-noruntime.tar.gz <!-- BEGIN SHA linux-arm_noruntime --><LINUX_ARM_SHA_NORUNTIME><!-- END SHA linux-arm_noruntime -->
- actions-runner-win-x64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-x64_noruntime_noexternals --><WIN_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-x64_noruntime_noexternals --> - actions-runner-win-x64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-x64_noruntime_noexternals --><WIN_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-x64_noruntime_noexternals -->
- actions-runner-win-arm64-<RUNNER_VERSION>-noruntime-noexternals.zip <!-- BEGIN SHA win-arm64_noruntime_noexternals --><WIN_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA win-arm64_noruntime_noexternals -->
- actions-runner-osx-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noruntime_noexternals --><OSX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-x64_noruntime_noexternals --> - actions-runner-osx-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-x64_noruntime_noexternals --><OSX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-x64_noruntime_noexternals -->
- actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noruntime_noexternals --><OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-arm64_noruntime_noexternals --> - actions-runner-osx-arm64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA osx-arm64_noruntime_noexternals --><OSX_ARM64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA osx-arm64_noruntime_noexternals -->
- actions-runner-linux-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noruntime_noexternals --><LINUX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-x64_noruntime_noexternals --> - actions-runner-linux-x64-<RUNNER_VERSION>-noruntime-noexternals.tar.gz <!-- BEGIN SHA linux-x64_noruntime_noexternals --><LINUX_X64_SHA_NORUNTIME_NOEXTERNALS><!-- END SHA linux-x64_noruntime_noexternals -->

View File

@@ -1 +1 @@
<Update to ./src/runnerversion when creating release> 2.300.2

View File

@@ -13,7 +13,7 @@ set -e
flags_found=false flags_found=false
while getopts 's:g:n:r:u:l:' opt; do while getopts 's:g:n:r:u:l:df' opt; do
flags_found=true flags_found=true
case $opt in case $opt in
@@ -35,6 +35,12 @@ while getopts 's:g:n:r:u:l:' opt; do
l) l)
labels=$OPTARG labels=$OPTARG
;; ;;
f)
replace='true'
;;
d)
disableupdate='true'
;;
*) *)
echo " echo "
Runner Service Installer Runner Service Installer
@@ -49,7 +55,9 @@ Usage:
-n optional name of the runner, defaults to hostname -n optional name of the runner, defaults to hostname
-r optional name of the runner group to add the runner to, defaults to the Default group -r optional name of the runner group to add the runner to, defaults to the Default group
-u optional user svc will run as, defaults to current -u optional user svc will run as, defaults to current
-l optional list of labels (split by comma) applied on the runner" -l optional list of labels (split by comma) applied on the runner
-d optional allow runner to remain on the current version for one month after the release of a newer version
-f optional replace any existing runner with the same name"
exit 0 exit 0
;; ;;
esac esac
@@ -169,8 +177,8 @@ fi
echo echo
echo "Configuring ${runner_name} @ $runner_url" echo "Configuring ${runner_name} @ $runner_url"
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup \"$runner_group\"}" echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup \"$runner_group\"} ${disableupdate:+--disableupdate}"
sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup "$runner_group"} sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN ${replace:+--replace} --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup "$runner_group"} ${disableupdate:+--disableupdate}
#--------------------------------------- #---------------------------------------
# Configuring as a service # Configuring as a service

View File

@@ -1,4 +1,4 @@
#/bin/bash #!/bin/bash
set -e set -e
@@ -12,7 +12,7 @@ set -e
# #
# Usage: # Usage:
# export RUNNER_CFG_PAT=<yourPAT> # export RUNNER_CFG_PAT=<yourPAT>
# ./delete.sh scope name # ./delete.sh <scope> [<name>]
# #
# scope required repo (:owner/:repo) or org (:organization) # scope required repo (:owner/:repo) or org (:organization)
# name optional defaults to hostname. name to delete # name optional defaults to hostname. name to delete
@@ -26,17 +26,17 @@ set -e
runner_scope=${1} runner_scope=${1}
runner_name=${2} runner_name=${2}
echo "Deleting runner ${runner_name} @ ${runner_scope}" function fatal()
function fatal()
{ {
echo "error: $1" >&2 echo "error: $1" >&2
exit 1 exit 1
} }
if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi
if [ -z "${runner_name}" ]; then fatal "supply name as argument 2"; fi
if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi
if [ -z "${runner_name}" ]; then runner_name=`hostname`; fi
echo "Deleting runner ${runner_name} @ ${runner_scope}"
which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc" which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc"
which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc" which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc"

View File

@@ -24,6 +24,9 @@
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'"> <PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
<DefineConstants>$(DefineConstants);X86</DefineConstants> <DefineConstants>$(DefineConstants);X86</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-arm64'">
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'"> <PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
<DefineConstants>$(DefineConstants);X64</DefineConstants> <DefineConstants>$(DefineConstants);X64</DefineConstants>

View File

@@ -0,0 +1 @@
39d0683f0f115a211cb10c473e9574c16549a19d4e9a6c637ded3d7022bf809f

View File

@@ -0,0 +1 @@
e5dace2d41cc0682d096dcce4970079ad48ec7107e46195970eecfdb3df2acef

View File

@@ -1 +1,4 @@
To update hashFiles under `Misc/layoutbin` run `npm install && npm run all` To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run all`.
> Note: this package also needs to be recompiled for dependabot PRs updating one of
> its dependencies.

View File

@@ -22,9 +22,13 @@
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "1.2.6", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
}, },
"node_modules/@actions/glob": { "node_modules/@actions/glob": {
"version": "0.1.0", "version": "0.1.0",
@@ -35,6 +39,14 @@
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
} }
}, },
"node_modules/@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"dependencies": {
"tunnel": "^0.0.6"
}
},
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
@@ -2381,6 +2393,14 @@
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
} }
}, },
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -2442,6 +2462,14 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache": { "node_modules/v8-compile-cache": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
@@ -2503,9 +2531,13 @@
}, },
"dependencies": { "dependencies": {
"@actions/core": { "@actions/core": {
"version": "1.2.6", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
}, },
"@actions/glob": { "@actions/glob": {
"version": "0.1.0", "version": "0.1.0",
@@ -2516,6 +2548,14 @@
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
} }
}, },
"@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"requires": {
"tunnel": "^0.0.6"
}
},
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
@@ -4189,6 +4229,11 @@
"tslib": "^1.8.1" "tslib": "^1.8.1"
} }
}, },
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"type-check": { "type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4231,6 +4276,11 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",

View File

@@ -3,6 +3,7 @@ PACKAGERUNTIME=$1
PRECACHE=$2 PRECACHE=$2
NODE_URL=https://nodejs.org/dist NODE_URL=https://nodejs.org/dist
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
NODE12_VERSION="12.22.7" NODE12_VERSION="12.22.7"
NODE16_VERSION="16.13.0" NODE16_VERSION="16.13.0"
@@ -134,6 +135,16 @@ if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
fi fi
fi fi
# Download the external tools only for Windows.
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
# todo: replace these with official release when available
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
if [[ "$PRECACHE" != "" ]]; then
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
fi
fi
# Download the external tools only for OSX. # Download the external tools only for OSX.
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir

File diff suppressed because it is too large Load Diff

View File

@@ -120,6 +120,9 @@ if ERRORLEVEL 1 (
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1 echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
type nul > update.finished
echo [%date% %time%] update.finished file creation succeed >> "%logfile%" 2>&1
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
rem runner service host can base on the log file name determin the result of the runner update rem runner service host can base on the log file name determin the result of the runner update
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1 echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1

View File

@@ -180,6 +180,9 @@ fi
date "+[%F %T-%4N] Update succeed" >> "$logfile" date "+[%F %T-%4N] Update succeed" >> "$logfile"
touch update.finished
date "+[%F %T-%4N] update.finished file creation succeed" >> "$logfile"
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart # rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
# runner service host can base on the log file name determin the result of the runner update # runner service host can base on the log file name determin the result of the runner update
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1 date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1

View File

@@ -1,5 +1,5 @@
@echo off @echo off
SET UPDATEFILE=update.finished
"%~dp0\bin\Runner.Listener.exe" run %* "%~dp0\bin\Runner.Listener.exe" run %*
rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N` rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N`
@@ -22,16 +22,30 @@ if %ERRORLEVEL% EQU 2 (
) )
if %ERRORLEVEL% EQU 3 ( if %ERRORLEVEL% EQU 3 (
rem Sleep 5 seconds to wait for the runner update process finish rem Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
echo "Runner listener exit because of updating, re-launch runner in 5 seconds" echo "Runner listener exit because of updating, re-launch runner after successful update"
ping 127.0.0.1 -n 6 -w 1000 >NUL FOR /L %%G IN (1,1,30) DO (
IF EXIST %UPDATEFILE% (
echo "Update finished successfully."
del %FILE%
exit /b 1
)
ping 127.0.0.1 -n 2 -w 1000 >NUL
)
exit /b 1 exit /b 1
) )
if %ERRORLEVEL% EQU 4 ( if %ERRORLEVEL% EQU 4 (
rem Sleep 5 seconds to wait for the ephemeral runner update process finish rem Wait for 30 seconds or for flag file to exists for the runner update process finish
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds" echo "Runner listener exit because of updating, re-launch runner after successful update"
ping 127.0.0.1 -n 6 -w 1000 >NUL FOR /L %%G IN (1,1,30) DO (
IF EXIST %UPDATEFILE% (
echo "Update finished successfully."
del %FILE%
exit /b 1
)
ping 127.0.0.1 -n 2 -w 1000 >NUL
)
exit /b 1 exit /b 1
) )

View File

@@ -17,6 +17,8 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
updateFile="update.finished"
"$DIR"/bin/Runner.Listener run $* "$DIR"/bin/Runner.Listener run $*
returnCode=$? returnCode=$?
@@ -31,14 +33,28 @@ elif [[ $returnCode == 2 ]]; then
"$DIR"/safe_sleep.sh 5 "$DIR"/safe_sleep.sh 5
exit 2 exit 2
elif [[ $returnCode == 3 ]]; then elif [[ $returnCode == 3 ]]; then
# Sleep 5 seconds to wait for the runner update process finish # Wait for 30 seconds or for flag file to exists for the runner update process finish
echo "Runner listener exit because of updating, re-launch runner in 5 seconds" echo "Runner listener exit because of updating, re-launch runner after successful update"
"$DIR"/safe_sleep.sh 5 for i in {0..30}; do
if test -f "$updateFile"; then
echo "Update finished successfully."
rm "$updateFile"
break
fi
"$DIR"/safe_sleep.sh 1
done
exit 2 exit 2
elif [[ $returnCode == 4 ]]; then elif [[ $returnCode == 4 ]]; then
# Sleep 5 seconds to wait for the ephemeral runner update process finish # Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds" echo "Runner listener exit because of updating, re-launch runner after successful update"
"$DIR"/safe_sleep.sh 5 for i in {0..30}; do
if test -f "$updateFile"; then
echo "Update finished successfully."
rm "$updateFile"
break
fi
"$DIR"/safe_sleep.sh 1
done
exit 2 exit 2
else else
echo "Exiting with unknown error code: ${returnCode}" echo "Exiting with unknown error code: ${returnCode}"

View File

@@ -9,16 +9,52 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
# run the helper process which keep the listener alive run() {
while :; # run the helper process which keep the listener alive
do while :;
"$DIR"/run-helper.sh $* do
returnCode=$? cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
if [[ $returnCode -eq 2 ]]; then "$DIR"/run-helper.sh $*
echo "Restarting runner..." returnCode=$?
else if [[ $returnCode -eq 2 ]]; then
echo "Exiting runner..." echo "Restarting runner..."
exit 0 else
fi echo "Exiting runner..."
done exit 0
fi
done
}
runWithManualTrap() {
# Set job control
set -m
trap 'kill -INT -$PID' INT TERM
# run the helper process which keep the listener alive
while :;
do
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
"$DIR"/run-helper.sh $* &
PID=$!
wait -f $PID
returnCode=$?
if [[ $returnCode -eq 2 ]]; then
echo "Restarting runner..."
else
echo "Exiting runner..."
# Unregister signal handling before exit
trap - INT TERM
# wait for last parts to be logged
wait $PID
exit $returnCode
fi
done
}
if [[ -z "$RUNNER_MANUALLY_TRAP_SIG" ]]; then
run $*
else
runWithManualTrap $*
fi

View File

@@ -66,12 +66,14 @@ libmscordbi.dylib
libmscordbi.so libmscordbi.so
Microsoft.CSharp.dll Microsoft.CSharp.dll
Microsoft.DiaSymReader.Native.amd64.dll Microsoft.DiaSymReader.Native.amd64.dll
Microsoft.DiaSymReader.Native.arm64.dll
Microsoft.VisualBasic.Core.dll Microsoft.VisualBasic.Core.dll
Microsoft.VisualBasic.dll Microsoft.VisualBasic.dll
Microsoft.Win32.Primitives.dll Microsoft.Win32.Primitives.dll
Microsoft.Win32.Registry.dll Microsoft.Win32.Registry.dll
mscordaccore.dll mscordaccore.dll
mscordaccore_amd64_amd64_6.0.522.21309.dll mscordaccore_amd64_amd64_6.0.522.21309.dll
mscordaccore_arm64_arm64_6.0.522.21309.dll
mscordbi.dll mscordbi.dll
mscorlib.dll mscorlib.dll
mscorrc.debug.dll mscorrc.debug.dll
@@ -261,4 +263,4 @@ System.Xml.XmlSerializer.dll
System.Xml.XPath.dll System.Xml.XPath.dll
System.Xml.XPath.XDocument.dll System.Xml.XPath.XDocument.dll
ucrtbase.dll ucrtbase.dll
WindowsBase.dll WindowsBase.dll

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -32,7 +31,7 @@ namespace GitHub.Runner.Common
new EscapeMapping(token: "%", replacement: "%25"), new EscapeMapping(token: "%", replacement: "%25"),
}; };
private readonly Dictionary<string, string> _properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, string> _properties = new(StringComparer.OrdinalIgnoreCase);
public const string Prefix = "##["; public const string Prefix = "##[";
public const string _commandKey = "::"; public const string _commandKey = "::";

View File

@@ -1,5 +1,3 @@
using System;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
public enum ActionResult public enum ActionResult

View File

@@ -0,0 +1,51 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.WebApi;
using GitHub.Services.Common;
using GitHub.Services.WebApi;
namespace GitHub.Runner.Common
{
[ServiceLocator(Default = typeof(ActionsRunServer))]
public interface IActionsRunServer : IRunnerService
{
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken token);
}
public sealed class ActionsRunServer : RunnerService, IActionsRunServer
{
private bool _hasConnection;
private VssConnection _connection;
private TaskAgentHttpClient _taskAgentClient;
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
{
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
_hasConnection = true;
}
private void CheckConnection()
{
if (!_hasConnection)
{
throw new InvalidOperationException($"SetConnection");
}
}
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken)
{
CheckConnection();
var jobMessage = RetryRequest<AgentJobRequestMessage>(async () =>
{
return await _taskAgentClient.GetJobMessageAsync(id, cancellationToken);
}, cancellationToken);
return jobMessage;
}
}
}

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GitHub.DistributedTask.Logging; using GitHub.DistributedTask.Logging;

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.IO; using System.IO;
@@ -75,17 +74,18 @@ namespace GitHub.Runner.Common
{ {
get get
{ {
Uri accountUri = new Uri(this.ServerUrl); Uri accountUri = new(this.ServerUrl);
string repoOrOrgName = string.Empty; string repoOrOrgName = string.Empty;
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase)) if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(this.GitHubUrl))
{ {
Uri gitHubUrl = new Uri(this.GitHubUrl); Uri gitHubUrl = new(this.GitHubUrl);
// Use the "NWO part" from the GitHub URL path // Use the "NWO part" from the GitHub URL path
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/'); repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
} }
else
if (string.IsNullOrEmpty(repoOrOrgName))
{ {
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
} }

View File

@@ -77,7 +77,7 @@ namespace GitHub.Runner.Common
public static readonly Architecture PlatformArchitecture = Architecture.X64; public static readonly Architecture PlatformArchitecture = Architecture.X64;
#elif ARM #elif ARM
public static readonly Architecture PlatformArchitecture = Architecture.Arm; public static readonly Architecture PlatformArchitecture = Architecture.Arm;
#elif ARM64 #elif ARM64
public static readonly Architecture PlatformArchitecture = Architecture.Arm64; public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
#endif #endif
@@ -128,6 +128,7 @@ namespace GitHub.Runner.Common
public static readonly string Check = "check"; public static readonly string Check = "check";
public static readonly string Commit = "commit"; public static readonly string Commit = "commit";
public static readonly string Ephemeral = "ephemeral"; public static readonly string Ephemeral = "ephemeral";
public static readonly string GenerateServiceConfig = "generateServiceConfig";
public static readonly string Help = "help"; public static readonly string Help = "help";
public static readonly string Replace = "replace"; public static readonly string Replace = "replace";
public static readonly string DisableUpdate = "disableupdate"; public static readonly string DisableUpdate = "disableupdate";
@@ -152,17 +153,19 @@ namespace GitHub.Runner.Common
public static readonly string DiskSpaceWarning = "runner.diskspace.warning"; public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action"; public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate"; public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks"; public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
} }
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry"; public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
public static readonly string WorkerCrash = "WORKER_CRASH"; public static readonly string WorkerCrash = "WORKER_CRASH";
public static readonly string LowDiskSpace = "LOW_DISK_SPACE"; public static readonly string LowDiskSpace = "LOW_DISK_SPACE";
public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND"; public static readonly string UnsupportedCommand = "UNSUPPORTED_COMMAND";
public static readonly string UnsupportedCommandMessage = "The `{0}` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/";
public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/"; public static readonly string UnsupportedCommandMessageDisabled = "The `{0}` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/";
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`."; public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary"; public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: {0}"; public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
public static readonly string Node12DetectedAfterEndOfLife = "Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: {0}. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.";
} }
public static class RunnerEvent public static class RunnerEvent
@@ -241,8 +244,9 @@ namespace GitHub.Runner.Common
public static readonly string ToolsDirectory = "agent.ToolsDirectory"; public static readonly string ToolsDirectory = "agent.ToolsDirectory";
// Set this env var to "node12" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions. // Set this env var to "node12" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions.
public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION"; public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION";
public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION"; public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION";
public static readonly string PrintLogToStdout = "ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT";
} }
public static class System public static class System
@@ -255,5 +259,12 @@ namespace GitHub.Runner.Common
public static readonly string PhaseDisplayName = "system.phaseDisplayName"; public static readonly string PhaseDisplayName = "system.phaseDisplayName";
} }
} }
public static class OperatingSystem
{
public static readonly int Windows11BuildVersion = 22000;
// Both windows 10 and windows 11 share the same Major Version 10, need to use the build version to differentiate
public static readonly int Windows11MajorVersion = 10;
}
} }
} }

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -15,7 +14,7 @@ namespace GitHub.Runner.Common
public sealed class ExtensionManager : RunnerService, IExtensionManager public sealed class ExtensionManager : RunnerService, IExtensionManager
{ {
private readonly ConcurrentDictionary<Type, List<IExtension>> _cache = new ConcurrentDictionary<Type, List<IExtension>>(); private readonly ConcurrentDictionary<Type, List<IExtension>> _cache = new();
public List<T> GetExtensions<T>() where T : class, IExtension public List<T> GetExtensions<T>() where T : class, IExtension
{ {
@@ -61,6 +60,8 @@ namespace GitHub.Runner.Common
Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker"); Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, Runner.Worker"); Add<T>(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.CreateStepSummaryCommand, Runner.Worker"); Add<T>(extensions, "GitHub.Runner.Worker.CreateStepSummaryCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputFileCommand, Runner.Worker");
break; break;
case "GitHub.Runner.Listener.Check.ICheckExtension": case "GitHub.Runner.Listener.Check.ICheckExtension":
Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener"); Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener");

View File

@@ -51,12 +51,12 @@ namespace GitHub.Runner.Common
private static int _defaultLogRetentionDays = 30; private static int _defaultLogRetentionDays = 30;
private static int[] _vssHttpMethodEventIds = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 24 }; private static int[] _vssHttpMethodEventIds = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 24 };
private static int[] _vssHttpCredentialEventIds = new int[] { 11, 13, 14, 15, 16, 17, 18, 20, 21, 22, 27, 29 }; private static int[] _vssHttpCredentialEventIds = new int[] { 11, 13, 14, 15, 16, 17, 18, 20, 21, 22, 27, 29 };
private readonly ConcurrentDictionary<Type, object> _serviceInstances = new ConcurrentDictionary<Type, object>(); private readonly ConcurrentDictionary<Type, object> _serviceInstances = new();
private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new ConcurrentDictionary<Type, Type>(); private readonly ConcurrentDictionary<Type, Type> _serviceTypes = new();
private readonly ISecretMasker _secretMasker = new SecretMasker(); private readonly ISecretMasker _secretMasker = new SecretMasker();
private readonly List<ProductInfoHeaderValue> _userAgents = new List<ProductInfoHeaderValue>() { new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version) }; private readonly List<ProductInfoHeaderValue> _userAgents = new() { new ProductInfoHeaderValue($"GitHubActionsRunner-{BuildConstants.RunnerPackage.PackageName}", BuildConstants.RunnerPackage.Version) };
private CancellationTokenSource _runnerShutdownTokenSource = new CancellationTokenSource(); private CancellationTokenSource _runnerShutdownTokenSource = new();
private object _perfLock = new object(); private object _perfLock = new();
private Tracing _trace; private Tracing _trace;
private Tracing _actionsHttpTrace; private Tracing _actionsHttpTrace;
private Tracing _netcoreHttpTrace; private Tracing _netcoreHttpTrace;
@@ -66,7 +66,7 @@ namespace GitHub.Runner.Common
private IDisposable _diagListenerSubscription; private IDisposable _diagListenerSubscription;
private StartupType _startupType; private StartupType _startupType;
private string _perfFile; private string _perfFile;
private RunnerWebProxy _webProxy = new RunnerWebProxy(); private RunnerWebProxy _webProxy = new();
public event EventHandler Unloading; public event EventHandler Unloading;
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token; public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
@@ -94,6 +94,13 @@ namespace GitHub.Runner.Common
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPreAmpersandEscape); this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPreAmpersandEscape);
this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPostAmpersandEscape); this.SecretMasker.AddValueEncoder(ValueEncoders.PowerShellPostAmpersandEscape);
// Create StdoutTraceListener if ENV is set
StdoutTraceListener stdoutTraceListener = null;
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Agent.PrintLogToStdout)))
{
stdoutTraceListener = new StdoutTraceListener(hostType);
}
// Create the trace manager. // Create the trace manager.
if (string.IsNullOrEmpty(logFile)) if (string.IsNullOrEmpty(logFile))
{ {
@@ -113,11 +120,11 @@ namespace GitHub.Runner.Common
// this should give us _diag folder under runner root directory // this should give us _diag folder under runner root directory
string diagLogDirectory = Path.Combine(new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).Parent.FullName, Constants.Path.DiagDirectory); string diagLogDirectory = Path.Combine(new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).Parent.FullName, Constants.Path.DiagDirectory);
_traceManager = new TraceManager(new HostTraceListener(diagLogDirectory, hostType, logPageSize, logRetentionDays), this.SecretMasker); _traceManager = new TraceManager(new HostTraceListener(diagLogDirectory, hostType, logPageSize, logRetentionDays), stdoutTraceListener, this.SecretMasker);
} }
else else
{ {
_traceManager = new TraceManager(new HostTraceListener(logFile), this.SecretMasker); _traceManager = new TraceManager(new HostTraceListener(logFile), stdoutTraceListener, this.SecretMasker);
} }
_trace = GetTrace(nameof(HostContext)); _trace = GetTrace(nameof(HostContext));

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
@@ -165,7 +164,7 @@ namespace GitHub.Runner.Common
{ {
if (_enableLogRetention) if (_enableLogRetention)
{ {
DirectoryInfo diags = new DirectoryInfo(_logFileDirectory); DirectoryInfo diags = new(_logFileDirectory);
var logs = diags.GetFiles($"{_logFilePrefix}*.log"); var logs = diags.GetFiles($"{_logFilePrefix}*.log");
foreach (var log in logs) foreach (var log in logs)
{ {

View File

@@ -1,10 +1,7 @@
using System; using System;
using System.IO;
using System.IO.Pipes;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -13,7 +13,8 @@ using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using GitHub.Services.WebApi.Utilities.Internal; using GitHub.Services.WebApi.Utilities.Internal;
using Newtonsoft.Json; using GitHub.Services.Results.Client;
using GitHub.Services.OAuth;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -23,11 +24,13 @@ namespace GitHub.Runner.Common
Task ConnectAsync(VssConnection jobConnection); Task ConnectAsync(VssConnection jobConnection);
void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint); void InitializeWebsocketClient(ServiceEndpoint serviceEndpoint);
void InitializeResultsClient(Uri uri, string token);
// logging and console // logging and console
Task<TaskLog> AppendLogContentAsync(Guid scopeIdentifier, string hubName, Guid planId, int logId, Stream uploadStream, CancellationToken cancellationToken); Task<TaskLog> AppendLogContentAsync(Guid scopeIdentifier, string hubName, Guid planId, int logId, Stream uploadStream, CancellationToken cancellationToken);
Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken); Task AppendTimelineRecordFeedAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, Guid stepId, IList<string> lines, long? startLine, CancellationToken cancellationToken);
Task<TaskAttachment> CreateAttachmentAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, String type, String name, Stream uploadStream, CancellationToken cancellationToken); Task<TaskAttachment> CreateAttachmentAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid timelineRecordId, String type, String name, Stream uploadStream, CancellationToken cancellationToken);
Task CreateStepSymmaryAsync(string planId, string jobId, string stepId, string file, CancellationToken cancellationToken);
Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken); Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken);
Task<Timeline> CreateTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken); Task<Timeline> CreateTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken);
Task<List<TimelineRecord>> UpdateTimelineRecordsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, IEnumerable<TimelineRecord> records, CancellationToken cancellationToken); Task<List<TimelineRecord>> UpdateTimelineRecordsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
@@ -41,6 +44,7 @@ namespace GitHub.Runner.Common
private bool _hasConnection; private bool _hasConnection;
private VssConnection _connection; private VssConnection _connection;
private TaskHttpClient _taskClient; private TaskHttpClient _taskClient;
private ResultsHttpClient _resultsClient;
private ClientWebSocket _websocketClient; private ClientWebSocket _websocketClient;
private ServiceEndpoint _serviceEndpoint; private ServiceEndpoint _serviceEndpoint;
@@ -144,6 +148,12 @@ namespace GitHub.Runner.Common
InitializeWebsocketClient(TimeSpan.Zero); InitializeWebsocketClient(TimeSpan.Zero);
} }
public void InitializeResultsClient(Uri uri, string token)
{
var httpMessageHandler = HostContext.CreateHttpClientHandler();
this._resultsClient = new ResultsHttpClient(uri, httpMessageHandler, token, disposeHandler: true);
}
public ValueTask DisposeAsync() public ValueTask DisposeAsync()
{ {
CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None); CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None);
@@ -306,6 +316,16 @@ namespace GitHub.Runner.Common
return _taskClient.CreateAttachmentAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, type, name, uploadStream, cancellationToken: cancellationToken); return _taskClient.CreateAttachmentAsync(scopeIdentifier, hubName, planId, timelineId, timelineRecordId, type, name, uploadStream, cancellationToken: cancellationToken);
} }
public Task CreateStepSymmaryAsync(string planId, string jobId, string stepId, string file, CancellationToken cancellationToken)
{
if (_resultsClient != null)
{
return _resultsClient.UploadStepSummaryAsync(planId, jobId, stepId, file, cancellationToken: cancellationToken);
}
throw new InvalidOperationException("Results client is not initialized.");
}
public Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken) public Task<TaskLog> CreateLogAsync(Guid scopeIdentifier, string hubName, Guid planId, TaskLog log, CancellationToken cancellationToken)
{ {
CheckConnection(); CheckConnection();

View File

@@ -20,6 +20,7 @@ namespace GitHub.Runner.Common
void Start(Pipelines.AgentJobRequestMessage jobRequest); void Start(Pipelines.AgentJobRequestMessage jobRequest);
void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null); void QueueWebConsoleLine(Guid stepRecordId, string line, long? lineNumber = null);
void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource); void QueueFileUpload(Guid timelineId, Guid timelineRecordId, string type, string name, string path, bool deleteSource);
void QueueSummaryUpload(Guid timelineId, Guid timelineRecordId, string stepId, string name, string path, bool deleteSource);
void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord); void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord);
} }
@@ -30,6 +31,7 @@ namespace GitHub.Runner.Common
private static readonly TimeSpan _delayForWebConsoleLineDequeue = TimeSpan.FromMilliseconds(500); private static readonly TimeSpan _delayForWebConsoleLineDequeue = TimeSpan.FromMilliseconds(500);
private static readonly TimeSpan _delayForTimelineUpdateDequeue = TimeSpan.FromMilliseconds(500); private static readonly TimeSpan _delayForTimelineUpdateDequeue = TimeSpan.FromMilliseconds(500);
private static readonly TimeSpan _delayForFileUploadDequeue = TimeSpan.FromMilliseconds(1000); private static readonly TimeSpan _delayForFileUploadDequeue = TimeSpan.FromMilliseconds(1000);
private static readonly TimeSpan _delayForSummaryUploadDequeue = TimeSpan.FromMilliseconds(1000);
// Job message information // Job message information
private Guid _scopeIdentifier; private Guid _scopeIdentifier;
@@ -39,30 +41,33 @@ namespace GitHub.Runner.Common
private Guid _jobTimelineRecordId; private Guid _jobTimelineRecordId;
// queue for web console line // queue for web console line
private readonly ConcurrentQueue<ConsoleLineInfo> _webConsoleLineQueue = new ConcurrentQueue<ConsoleLineInfo>(); private readonly ConcurrentQueue<ConsoleLineInfo> _webConsoleLineQueue = new();
// queue for file upload (log file or attachment) // queue for file upload (log file or attachment)
private readonly ConcurrentQueue<UploadFileInfo> _fileUploadQueue = new ConcurrentQueue<UploadFileInfo>(); private readonly ConcurrentQueue<UploadFileInfo> _fileUploadQueue = new();
private readonly ConcurrentQueue<SummaryUploadFileInfo> _summaryFileUploadQueue = new();
// queue for timeline or timeline record update (one queue per timeline) // queue for timeline or timeline record update (one queue per timeline)
private readonly ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>> _timelineUpdateQueue = new ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>>(); private readonly ConcurrentDictionary<Guid, ConcurrentQueue<TimelineRecord>> _timelineUpdateQueue = new();
// indicate how many timelines we have, we will process _timelineUpdateQueue base on the order of timeline in this list // indicate how many timelines we have, we will process _timelineUpdateQueue base on the order of timeline in this list
private readonly List<Guid> _allTimelines = new List<Guid>(); private readonly List<Guid> _allTimelines = new();
// bufferd timeline records that fail to update // bufferd timeline records that fail to update
private readonly Dictionary<Guid, List<TimelineRecord>> _bufferedRetryRecords = new Dictionary<Guid, List<TimelineRecord>>(); private readonly Dictionary<Guid, List<TimelineRecord>> _bufferedRetryRecords = new();
// Task for each queue's dequeue process // Task for each queue's dequeue process
private Task _webConsoleLineDequeueTask; private Task _webConsoleLineDequeueTask;
private Task _fileUploadDequeueTask; private Task _fileUploadDequeueTask;
private Task _summaryUploadDequeueTask;
private Task _timelineUpdateDequeueTask; private Task _timelineUpdateDequeueTask;
// common // common
private IJobServer _jobServer; private IJobServer _jobServer;
private Task[] _allDequeueTasks; private Task[] _allDequeueTasks;
private readonly TaskCompletionSource<int> _jobCompletionSource = new TaskCompletionSource<int>(); private readonly TaskCompletionSource<int> _jobCompletionSource = new();
private readonly TaskCompletionSource<int> _jobRecordUpdated = new TaskCompletionSource<int>(); private readonly TaskCompletionSource<int> _jobRecordUpdated = new();
private bool _queueInProcess = false; private bool _queueInProcess = false;
public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated; public TaskCompletionSource<int> JobRecordUpdated => _jobRecordUpdated;
@@ -93,6 +98,20 @@ namespace GitHub.Runner.Common
_jobServer.InitializeWebsocketClient(serviceEndPoint); _jobServer.InitializeWebsocketClient(serviceEndPoint);
// This code is usually wrapped by an instance of IExecutionContext which isn't available here.
jobRequest.Variables.TryGetValue("system.github.results_endpoint", out VariableValue resultsEndpointVariable);
var resultsReceiverEndpoint = resultsEndpointVariable?.Value;
if (serviceEndPoint?.Authorization != null &&
serviceEndPoint.Authorization.Parameters.TryGetValue("AccessToken", out var accessToken) &&
!string.IsNullOrEmpty(accessToken) &&
!string.IsNullOrEmpty(resultsReceiverEndpoint))
{
Trace.Info("Initializing results client");
_jobServer.InitializeResultsClient(new Uri(resultsReceiverEndpoint), accessToken);
}
if (_queueInProcess) if (_queueInProcess)
{ {
Trace.Info("No-opt, all queue process tasks are running."); Trace.Info("No-opt, all queue process tasks are running.");
@@ -120,10 +139,13 @@ namespace GitHub.Runner.Common
Trace.Info("Start process file upload queue."); Trace.Info("Start process file upload queue.");
_fileUploadDequeueTask = ProcessFilesUploadQueueAsync(); _fileUploadDequeueTask = ProcessFilesUploadQueueAsync();
Trace.Info("Start results file upload queue.");
_summaryUploadDequeueTask = ProcessSummaryUploadQueueAsync();
Trace.Info("Start process timeline update queue."); Trace.Info("Start process timeline update queue.");
_timelineUpdateDequeueTask = ProcessTimelinesUpdateQueueAsync(); _timelineUpdateDequeueTask = ProcessTimelinesUpdateQueueAsync();
_allDequeueTasks = new Task[] { _webConsoleLineDequeueTask, _fileUploadDequeueTask, _timelineUpdateDequeueTask }; _allDequeueTasks = new Task[] { _webConsoleLineDequeueTask, _fileUploadDequeueTask, _timelineUpdateDequeueTask, _summaryUploadDequeueTask };
_queueInProcess = true; _queueInProcess = true;
} }
@@ -154,6 +176,10 @@ namespace GitHub.Runner.Common
await ProcessFilesUploadQueueAsync(runOnce: true); await ProcessFilesUploadQueueAsync(runOnce: true);
Trace.Info("File upload queue drained."); Trace.Info("File upload queue drained.");
Trace.Verbose("Draining results summary upload queue.");
await ProcessSummaryUploadQueueAsync(runOnce: true);
Trace.Info("Results summary upload queue drained.");
// ProcessTimelinesUpdateQueueAsync() will throw exception during shutdown // ProcessTimelinesUpdateQueueAsync() will throw exception during shutdown
// if there is any timeline records that failed to update contains output variabls. // if there is any timeline records that failed to update contains output variabls.
Trace.Verbose("Draining timeline update queue."); Trace.Verbose("Draining timeline update queue.");
@@ -204,6 +230,28 @@ namespace GitHub.Runner.Common
_fileUploadQueue.Enqueue(newFile); _fileUploadQueue.Enqueue(newFile);
} }
public void QueueSummaryUpload(Guid timelineId, Guid timelineRecordId, string stepId, string name, string path, bool deleteSource)
{
ArgUtil.NotEmpty(timelineId, nameof(timelineId));
ArgUtil.NotEmpty(timelineRecordId, nameof(timelineRecordId));
// all parameter not null, file path exist.
var newFile = new SummaryUploadFileInfo()
{
TimelineId = timelineId,
TimelineRecordId = timelineRecordId,
Name = name,
Path = path,
PlanId = _planId.ToString(),
JobId = _jobTimelineRecordId.ToString(),
StepId = stepId,
DeleteSource = deleteSource
};
Trace.Verbose("Enqueue results file upload queue: file '{0}' attach to record {1}", newFile.Path, timelineRecordId);
_summaryFileUploadQueue.Enqueue(newFile);
}
public void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord) public void QueueTimelineRecordUpdate(Guid timelineId, TimelineRecord timelineRecord)
{ {
ArgUtil.NotEmpty(timelineId, nameof(timelineId)); ArgUtil.NotEmpty(timelineId, nameof(timelineId));
@@ -237,8 +285,8 @@ namespace GitHub.Runner.Common
} }
// Group consolelines by timeline record of each step // Group consolelines by timeline record of each step
Dictionary<Guid, List<TimelineRecordLogLine>> stepsConsoleLines = new Dictionary<Guid, List<TimelineRecordLogLine>>(); Dictionary<Guid, List<TimelineRecordLogLine>> stepsConsoleLines = new();
List<Guid> stepRecordIds = new List<Guid>(); // We need to keep lines in order List<Guid> stepRecordIds = new(); // We need to keep lines in order
int linesCounter = 0; int linesCounter = 0;
ConsoleLineInfo lineInfo; ConsoleLineInfo lineInfo;
while (_webConsoleLineQueue.TryDequeue(out lineInfo)) while (_webConsoleLineQueue.TryDequeue(out lineInfo))
@@ -264,7 +312,7 @@ namespace GitHub.Runner.Common
{ {
// Split consolelines into batch, each batch will container at most 100 lines. // Split consolelines into batch, each batch will container at most 100 lines.
int batchCounter = 0; int batchCounter = 0;
List<List<TimelineRecordLogLine>> batchedLines = new List<List<TimelineRecordLogLine>>(); List<List<TimelineRecordLogLine>> batchedLines = new();
foreach (var line in stepsConsoleLines[stepRecordId]) foreach (var line in stepsConsoleLines[stepRecordId])
{ {
var currentBatch = batchedLines.ElementAtOrDefault(batchCounter); var currentBatch = batchedLines.ElementAtOrDefault(batchCounter);
@@ -299,7 +347,7 @@ namespace GitHub.Runner.Common
{ {
try try
{ {
// Give at most 60s for each request. // Give at most 60s for each request.
using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60))) using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
{ {
await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token); await _jobServer.AppendTimelineRecordFeedAsync(_scopeIdentifier, _hubName, _planId, _jobTimelineId, _jobTimelineRecordId, stepRecordId, batch.Select(logLine => logLine.Line).ToList(), batch[0].LineNumber, timeoutTokenSource.Token);
@@ -338,7 +386,7 @@ namespace GitHub.Runner.Common
{ {
while (!_jobCompletionSource.Task.IsCompleted || runOnce) while (!_jobCompletionSource.Task.IsCompleted || runOnce)
{ {
List<UploadFileInfo> filesToUpload = new List<UploadFileInfo>(); List<UploadFileInfo> filesToUpload = new();
UploadFileInfo dequeueFile; UploadFileInfo dequeueFile;
while (_fileUploadQueue.TryDequeue(out dequeueFile)) while (_fileUploadQueue.TryDequeue(out dequeueFile))
{ {
@@ -394,17 +442,71 @@ namespace GitHub.Runner.Common
} }
} }
private async Task ProcessSummaryUploadQueueAsync(bool runOnce = false)
{
Trace.Info("Starting results-based upload queue...");
while (!_jobCompletionSource.Task.IsCompleted || runOnce)
{
List<SummaryUploadFileInfo> filesToUpload = new();
SummaryUploadFileInfo dequeueFile;
while (_summaryFileUploadQueue.TryDequeue(out dequeueFile))
{
filesToUpload.Add(dequeueFile);
// process at most 10 file upload.
if (!runOnce && filesToUpload.Count > 10)
{
break;
}
}
if (filesToUpload.Count > 0)
{
if (runOnce)
{
Trace.Info($"Uploading {filesToUpload.Count} summary files in one shot through results service.");
}
int errorCount = 0;
foreach (var file in filesToUpload)
{
try
{
await UploadSummaryFile(file);
}
catch (Exception ex)
{
Trace.Info("Catch exception during summary file upload to results, keep going since the process is best effort.");
Trace.Error(ex);
errorCount++;
}
}
Trace.Info("Tried to upload {0} summary files to results, success rate: {1}/{0}.", filesToUpload.Count, filesToUpload.Count - errorCount);
}
if (runOnce)
{
break;
}
else
{
await Task.Delay(_delayForSummaryUploadDequeue);
}
}
}
private async Task ProcessTimelinesUpdateQueueAsync(bool runOnce = false) private async Task ProcessTimelinesUpdateQueueAsync(bool runOnce = false)
{ {
while (!_jobCompletionSource.Task.IsCompleted || runOnce) while (!_jobCompletionSource.Task.IsCompleted || runOnce)
{ {
List<PendingTimelineRecord> pendingUpdates = new List<PendingTimelineRecord>(); List<PendingTimelineRecord> pendingUpdates = new();
foreach (var timeline in _allTimelines) foreach (var timeline in _allTimelines)
{ {
ConcurrentQueue<TimelineRecord> recordQueue; ConcurrentQueue<TimelineRecord> recordQueue;
if (_timelineUpdateQueue.TryGetValue(timeline, out recordQueue)) if (_timelineUpdateQueue.TryGetValue(timeline, out recordQueue))
{ {
List<TimelineRecord> records = new List<TimelineRecord>(); List<TimelineRecord> records = new();
TimelineRecord record; TimelineRecord record;
while (recordQueue.TryDequeue(out record)) while (recordQueue.TryDequeue(out record))
{ {
@@ -426,7 +528,7 @@ namespace GitHub.Runner.Common
// we need track whether we have new sub-timeline been created on the last run. // we need track whether we have new sub-timeline been created on the last run.
// if so, we need continue update timeline record even we on the last run. // if so, we need continue update timeline record even we on the last run.
bool pendingSubtimelineUpdate = false; bool pendingSubtimelineUpdate = false;
List<Exception> mainTimelineRecordsUpdateErrors = new List<Exception>(); List<Exception> mainTimelineRecordsUpdateErrors = new();
if (pendingUpdates.Count > 0) if (pendingUpdates.Count > 0)
{ {
foreach (var update in pendingUpdates) foreach (var update in pendingUpdates)
@@ -529,7 +631,7 @@ namespace GitHub.Runner.Common
return timelineRecords; return timelineRecords;
} }
Dictionary<Guid, TimelineRecord> dict = new Dictionary<Guid, TimelineRecord>(); Dictionary<Guid, TimelineRecord> dict = new();
foreach (TimelineRecord rec in timelineRecords) foreach (TimelineRecord rec in timelineRecords)
{ {
if (rec == null) if (rec == null)
@@ -665,6 +767,35 @@ namespace GitHub.Runner.Common
} }
} }
} }
private async Task UploadSummaryFile(SummaryUploadFileInfo file)
{
bool uploadSucceed = false;
try
{
// Upload the step summary
Trace.Info($"Starting to upload summary file to results service {file.Name}, {file.Path}");
var cancellationTokenSource = new CancellationTokenSource();
await _jobServer.CreateStepSymmaryAsync(file.PlanId, file.JobId, file.StepId, file.Path, cancellationTokenSource.Token);
uploadSucceed = true;
}
finally
{
if (uploadSucceed && file.DeleteSource)
{
try
{
File.Delete(file.Path);
}
catch (Exception ex)
{
Trace.Info("Catch exception during delete success results uploaded summary file.");
Trace.Error(ex);
}
}
}
}
} }
internal class PendingTimelineRecord internal class PendingTimelineRecord
@@ -683,6 +814,19 @@ namespace GitHub.Runner.Common
public bool DeleteSource { get; set; } public bool DeleteSource { get; set; }
} }
internal class SummaryUploadFileInfo
{
public Guid TimelineId { get; set; }
public Guid TimelineRecordId { get; set; }
public string Name { get; set; }
public string Path { get; set; }
public string PlanId { get; set; }
public string JobId { get; set; }
public string StepId { get; set; }
public bool DeleteSource { get; set; }
}
internal class ConsoleLineInfo internal class ConsoleLineInfo
{ {

View File

@@ -0,0 +1,14 @@
using System;
using GitHub.DistributedTask.WebApi;
namespace GitHub.Runner.Common
{
public class JobStatusEventArgs : EventArgs
{
public JobStatusEventArgs(TaskAgentStatus status)
{
this.Status = status;
}
public TaskAgentStatus Status { get; private set; }
}
}

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using System; using System;
using System.IO; using System.IO;

View File

@@ -76,7 +76,7 @@ namespace GitHub.Runner.Common
public async Task<WorkerMessage> ReceiveAsync(CancellationToken cancellationToken) public async Task<WorkerMessage> ReceiveAsync(CancellationToken cancellationToken)
{ {
WorkerMessage result = new WorkerMessage(MessageType.NotInitialized, string.Empty); WorkerMessage result = new(MessageType.NotInitialized, string.Empty);
result.MessageType = (MessageType)await _readStream.ReadInt32Async(cancellationToken); result.MessageType = (MessageType)await _readStream.ReadInt32Async(cancellationToken);
result.Body = await _readStream.ReadStringAsync(cancellationToken); result.Body = await _readStream.ReadStringAsync(cancellationToken);
Trace.Info($"Receiving message of length {result.Body.Length}, with hash '{IOUtil.GetSha256Hash(result.Body)}'"); Trace.Info($"Receiving message of length {result.Body.Length}, with hash '{IOUtil.GetSha256Hash(result.Body)}'");

View File

@@ -291,7 +291,7 @@ namespace GitHub.Runner.Common
public static string GetEnvironmentVariable(this Process process, IHostContext hostContext, string variable) public static string GetEnvironmentVariable(this Process process, IHostContext hostContext, string variable)
{ {
var trace = hostContext.GetTrace(nameof(LinuxProcessExtensions)); var trace = hostContext.GetTrace(nameof(LinuxProcessExtensions));
Dictionary<string, string> env = new Dictionary<string, string>(); Dictionary<string, string> env = new();
if (Directory.Exists("/proc")) if (Directory.Exists("/proc"))
{ {
@@ -322,8 +322,8 @@ namespace GitHub.Runner.Common
// It doesn't escape '=' or ' ', so we can't parse the output into a dictionary of all envs. // It doesn't escape '=' or ' ', so we can't parse the output into a dictionary of all envs.
// So we only look for the env you request, in the format of variable=value. (it won't work if you variable contains = or space) // So we only look for the env you request, in the format of variable=value. (it won't work if you variable contains = or space)
trace.Info($"Read env from output of `ps e -p {process.Id} -o command`"); trace.Info($"Read env from output of `ps e -p {process.Id} -o command`");
List<string> psOut = new List<string>(); List<string> psOut = new();
object outputLock = new object(); object outputLock = new();
using (var p = hostContext.CreateService<IProcessInvoker>()) using (var p = hostContext.CreateService<IProcessInvoker>())
{ {
p.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs stdout) p.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs stdout)

View File

@@ -1,4 +1,4 @@
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -1,14 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using Sdk.WebApi.WebApi.RawClient;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -23,42 +21,19 @@ namespace GitHub.Runner.Common
public sealed class RunServer : RunnerService, IRunServer public sealed class RunServer : RunnerService, IRunServer
{ {
private bool _hasConnection; private bool _hasConnection;
private VssConnection _connection; private Uri requestUri;
private TaskAgentHttpClient _taskAgentClient; private RawConnection _connection;
private RunServiceHttpClient _runServiceHttpClient;
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials) public async Task ConnectAsync(Uri serverUri, VssCredentials credentials)
{ {
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100)); requestUri = serverUri;
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
_connection = VssUtil.CreateRawConnection(new Uri(serverUri.Authority), credentials);
_runServiceHttpClient = await _connection.GetClientAsync<RunServiceHttpClient>();
_hasConnection = true; _hasConnection = true;
} }
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
{
Trace.Info($"EstablishVssConnection");
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
int attemptCount = 5;
while (attemptCount-- > 0)
{
var connection = VssUtil.CreateConnection(serverUrl, credentials, timeout: timeout);
try
{
await connection.ConnectAsync();
return connection;
}
catch (Exception ex) when (attemptCount > 0)
{
Trace.Info($"Catch exception during connect. {attemptCount} attempt left.");
Trace.Error(ex);
await HostContext.Delay(TimeSpan.FromMilliseconds(100), CancellationToken.None);
}
}
// should never reach here.
throw new InvalidOperationException(nameof(EstablishVssConnection));
}
private void CheckConnection() private void CheckConnection()
{ {
if (!_hasConnection) if (!_hasConnection)
@@ -70,37 +45,15 @@ namespace GitHub.Runner.Common
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken) public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken)
{ {
CheckConnection(); CheckConnection();
var jobMessage = RetryRequest<AgentJobRequestMessage>(async () => var jobMessage = RetryRequest<AgentJobRequestMessage>(
{ async () => await _runServiceHttpClient.GetJobMessageAsync(requestUri, id, cancellationToken), cancellationToken);
return await _taskAgentClient.GetJobMessageAsync(id, cancellationToken); if (jobMessage == null)
}, cancellationToken); {
throw new TaskOrchestrationJobNotFoundException(id);
}
return jobMessage; return jobMessage;
} }
private async Task<T> RetryRequest<T>(Func<Task<T>> func,
CancellationToken cancellationToken,
int maxRetryAttemptsCount = 5
)
{
var retryCount = 0;
while (true)
{
retryCount++;
cancellationToken.ThrowIfCancellationRequested();
try
{
return await func();
}
// TODO: Add handling of non-retriable exceptions: https://github.com/github/actions-broker/issues/122
catch (Exception ex) when (retryCount < maxRetryAttemptsCount)
{
Trace.Error("Catch exception during get full job message");
Trace.Error(ex);
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
Trace.Warning($"Back off {backOff.TotalSeconds} seconds before next retry. {maxRetryAttemptsCount - retryCount} attempt left.");
await Task.Delay(backOff, cancellationToken);
}
}
}
} }
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
@@ -16,7 +16,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" /> <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
<PackageReference Include="System.Threading.Channels" Version="4.4.0" /> <PackageReference Include="System.Threading.Channels" Version="4.4.0" />

View File

@@ -1,9 +1,8 @@
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common.Util;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
@@ -39,7 +38,7 @@ namespace GitHub.Runner.Common
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken); Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken); Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken); Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken); Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken);
// job request // job request
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken); Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
@@ -180,31 +179,6 @@ namespace GitHub.Runner.Common
} }
} }
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
{
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
int attemptCount = 5;
while (attemptCount-- > 0)
{
var connection = VssUtil.CreateConnection(serverUrl, credentials, timeout: timeout);
try
{
await connection.ConnectAsync();
return connection;
}
catch (Exception ex) when (attemptCount > 0)
{
Trace.Info($"Catch exception during connect. {attemptCount} attempt left.");
Trace.Error(ex);
await HostContext.Delay(TimeSpan.FromMilliseconds(100), CancellationToken.None);
}
}
// should never reach here.
throw new InvalidOperationException(nameof(EstablishVssConnection));
}
private void CheckConnection(RunnerConnectionType connectionType) private void CheckConnection(RunnerConnectionType connectionType)
{ {
switch (connectionType) switch (connectionType)
@@ -298,10 +272,10 @@ namespace GitHub.Runner.Common
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken); return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
} }
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken)
{ {
CheckConnection(RunnerConnectionType.MessageQueue); CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken); return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, runnerVersion, cancellationToken: cancellationToken);
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------

View File

@@ -1,4 +1,10 @@
using System; using System;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Runner.Sdk;
using GitHub.Services.Common;
using GitHub.Services.WebApi;
using Sdk.WebApi.WebApi.RawClient;
namespace GitHub.Runner.Common namespace GitHub.Runner.Common
{ {
@@ -21,9 +27,9 @@ namespace GitHub.Runner.Common
protected IHostContext HostContext { get; private set; } protected IHostContext HostContext { get; private set; }
protected Tracing Trace { get; private set; } protected Tracing Trace { get; private set; }
public string TraceName public string TraceName
{ {
get get
{ {
return GetType().Name; return GetType().Name;
} }
@@ -35,5 +41,57 @@ namespace GitHub.Runner.Common
Trace = HostContext.GetTrace(TraceName); Trace = HostContext.GetTrace(TraceName);
Trace.Entering(); Trace.Entering();
} }
protected async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
{
Trace.Info($"EstablishVssConnection");
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
int attemptCount = 5;
while (attemptCount-- > 0)
{
var connection = VssUtil.CreateConnection(serverUrl, credentials, timeout: timeout);
try
{
await connection.ConnectAsync();
return connection;
}
catch (Exception ex) when (attemptCount > 0)
{
Trace.Info($"Catch exception during connect. {attemptCount} attempt left.");
Trace.Error(ex);
await HostContext.Delay(TimeSpan.FromMilliseconds(100), CancellationToken.None);
}
}
// should never reach here.
throw new InvalidOperationException(nameof(EstablishVssConnection));
}
protected async Task<T> RetryRequest<T>(Func<Task<T>> func,
CancellationToken cancellationToken,
int maxRetryAttemptsCount = 5
)
{
var retryCount = 0;
while (true)
{
retryCount++;
cancellationToken.ThrowIfCancellationRequested();
try
{
return await func();
}
// TODO: Add handling of non-retriable exceptions: https://github.com/github/actions-broker/issues/122
catch (Exception ex) when (retryCount < maxRetryAttemptsCount)
{
Trace.Error("Catch exception during get full job message");
Trace.Error(ex);
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
Trace.Warning($"Back off {backOff.TotalSeconds} seconds before next retry. {maxRetryAttemptsCount - retryCount} attempt left.");
await Task.Delay(backOff, cancellationToken);
}
}
}
} }
} }

View File

@@ -0,0 +1,90 @@
using GitHub.Runner.Sdk;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
namespace GitHub.Runner.Common
{
public sealed class StdoutTraceListener : ConsoleTraceListener
{
private readonly string _hostType;
public StdoutTraceListener(string hostType)
{
this._hostType = hostType;
}
// Copied and modified slightly from .Net Core source code. Modification was required to make it compile.
// There must be some TraceFilter extension class that is missing in this source code.
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null))
{
return;
}
WriteHeader(source, eventType, id);
WriteLine(message);
WriteFooter(eventCache);
}
internal bool IsEnabled(TraceOptions opts)
{
return (opts & TraceOutputOptions) != 0;
}
// Altered from the original .Net Core implementation.
private void WriteHeader(string source, TraceEventType eventType, int id)
{
string type = null;
switch (eventType)
{
case TraceEventType.Critical:
type = "CRIT";
break;
case TraceEventType.Error:
type = "ERR ";
break;
case TraceEventType.Warning:
type = "WARN";
break;
case TraceEventType.Information:
type = "INFO";
break;
case TraceEventType.Verbose:
type = "VERB";
break;
default:
type = eventType.ToString();
break;
}
Write(StringUtil.Format("[{0} {1:u} {2} {3}] ", _hostType.ToUpperInvariant(), DateTime.UtcNow, type, source));
}
// Copied and modified slightly from .Net Core source code to make it compile. The original code
// accesses a private indentLevel field. In this code it has been modified to use the getter/setter.
private void WriteFooter(TraceEventCache eventCache)
{
if (eventCache == null)
return;
IndentLevel++;
if (IsEnabled(TraceOptions.ProcessId))
WriteLine("ProcessId=" + eventCache.ProcessId);
if (IsEnabled(TraceOptions.ThreadId))
WriteLine("ThreadId=" + eventCache.ThreadId);
if (IsEnabled(TraceOptions.DateTime))
WriteLine("DateTime=" + eventCache.DateTime.ToString("o", CultureInfo.InvariantCulture));
if (IsEnabled(TraceOptions.Timestamp))
WriteLine("Timestamp=" + eventCache.Timestamp);
IndentLevel--;
}
}
}

View File

@@ -18,7 +18,7 @@ namespace GitHub.Runner.Common
string ReadSecret(); string ReadSecret();
void Write(string message, ConsoleColor? colorCode = null); void Write(string message, ConsoleColor? colorCode = null);
void WriteLine(); void WriteLine();
void WriteLine(string line, ConsoleColor? colorCode = null); void WriteLine(string line, ConsoleColor? colorCode = null, bool skipTracing = false);
void WriteError(Exception ex); void WriteError(Exception ex);
void WriteError(string line); void WriteError(string line);
void WriteSection(string message); void WriteSection(string message);
@@ -81,7 +81,7 @@ namespace GitHub.Runner.Common
} }
// Trace whether a value was entered. // Trace whether a value was entered.
string val = new String(chars.ToArray()); string val = new(chars.ToArray());
if (!string.IsNullOrEmpty(val)) if (!string.IsNullOrEmpty(val))
{ {
HostContext.SecretMasker.AddValue(val); HostContext.SecretMasker.AddValue(val);
@@ -116,9 +116,12 @@ namespace GitHub.Runner.Common
// Do not add a format string overload. Terminal messages are user facing and therefore // Do not add a format string overload. Terminal messages are user facing and therefore
// should be localized. Use the Loc method in the StringUtil class. // should be localized. Use the Loc method in the StringUtil class.
public void WriteLine(string line, ConsoleColor? colorCode = null) public void WriteLine(string line, ConsoleColor? colorCode = null, bool skipTracing = false)
{ {
Trace.Info($"WRITE LINE: {line}"); if (!skipTracing)
{
Trace.Info($"WRITE LINE: {line}");
}
if (!Silent) if (!Silent)
{ {
if (colorCode != null) if (colorCode != null)

View File

@@ -1,10 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common.Internal; using GitHub.Services.Common.Internal;

View File

@@ -1,4 +1,3 @@
using GitHub.Runner.Common.Util;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
@@ -15,23 +14,25 @@ namespace GitHub.Runner.Common
public sealed class TraceManager : ITraceManager public sealed class TraceManager : ITraceManager
{ {
private readonly ConcurrentDictionary<string, Tracing> _sources = new ConcurrentDictionary<string, Tracing>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, Tracing> _sources = new(StringComparer.OrdinalIgnoreCase);
private readonly HostTraceListener _hostTraceListener; private readonly HostTraceListener _hostTraceListener;
private readonly StdoutTraceListener _stdoutTraceListener;
private TraceSetting _traceSetting; private TraceSetting _traceSetting;
private ISecretMasker _secretMasker; private ISecretMasker _secretMasker;
public TraceManager(HostTraceListener traceListener, ISecretMasker secretMasker) public TraceManager(HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener, ISecretMasker secretMasker)
: this(traceListener, new TraceSetting(), secretMasker) : this(traceListener, stdoutTraceListener, new TraceSetting(), secretMasker)
{ {
} }
public TraceManager(HostTraceListener traceListener, TraceSetting traceSetting, ISecretMasker secretMasker) public TraceManager(HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener, TraceSetting traceSetting, ISecretMasker secretMasker)
{ {
// Validate and store params. // Validate and store params.
ArgUtil.NotNull(traceListener, nameof(traceListener)); ArgUtil.NotNull(traceListener, nameof(traceListener));
ArgUtil.NotNull(traceSetting, nameof(traceSetting)); ArgUtil.NotNull(traceSetting, nameof(traceSetting));
ArgUtil.NotNull(secretMasker, nameof(secretMasker)); ArgUtil.NotNull(secretMasker, nameof(secretMasker));
_hostTraceListener = traceListener; _hostTraceListener = traceListener;
_stdoutTraceListener = stdoutTraceListener;
_traceSetting = traceSetting; _traceSetting = traceSetting;
_secretMasker = secretMasker; _secretMasker = secretMasker;
@@ -82,7 +83,7 @@ namespace GitHub.Runner.Common
Level = sourceTraceLevel.ToSourceLevels() Level = sourceTraceLevel.ToSourceLevels()
}; };
} }
return new Tracing(name, _secretMasker, sourceSwitch, _hostTraceListener); return new Tracing(name, _secretMasker, sourceSwitch, _hostTraceListener, _stdoutTraceListener);
} }
} }
} }

View File

@@ -1,5 +1,3 @@

using GitHub.Runner.Common.Util;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
@@ -14,7 +12,7 @@ namespace GitHub.Runner.Common
private ISecretMasker _secretMasker; private ISecretMasker _secretMasker;
private TraceSource _traceSource; private TraceSource _traceSource;
public Tracing(string name, ISecretMasker secretMasker, SourceSwitch sourceSwitch, HostTraceListener traceListener) public Tracing(string name, ISecretMasker secretMasker, SourceSwitch sourceSwitch, HostTraceListener traceListener, StdoutTraceListener stdoutTraceListener = null)
{ {
ArgUtil.NotNull(secretMasker, nameof(secretMasker)); ArgUtil.NotNull(secretMasker, nameof(secretMasker));
_secretMasker = secretMasker; _secretMasker = secretMasker;
@@ -29,6 +27,10 @@ namespace GitHub.Runner.Common
} }
_traceSource.Listeners.Add(traceListener); _traceSource.Listeners.Add(traceListener);
if (stdoutTraceListener != null)
{
_traceSource.Listeners.Add(stdoutTraceListener);
}
} }
public void Info(string message) public void Info(string message)

View File

@@ -7,7 +7,7 @@ namespace GitHub.Runner.Common.Util
{ {
private const string _defaultNodeVersion = "node16"; private const string _defaultNodeVersion = "node16";
#if OS_OSX && ARM64 #if (OS_OSX || OS_WINDOWS) && ARM64
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" }); public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" });
#else #else
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node12", "node16" }); public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node12", "node16" });

View File

@@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Common.Util namespace GitHub.Runner.Common.Util
{ {

View File

@@ -347,8 +347,8 @@ namespace GitHub.Runner.Listener.Check
public sealed class HttpEventSourceListener : EventListener public sealed class HttpEventSourceListener : EventListener
{ {
private readonly List<string> _logs; private readonly List<string> _logs;
private readonly object _lock = new object(); private readonly object _lock = new();
private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new Dictionary<string, HashSet<string>> private readonly Dictionary<string, HashSet<string>> _ignoredEvent = new()
{ {
{ {
"Microsoft-System-Net-Http", "Microsoft-System-Net-Http",

View File

@@ -2,7 +2,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.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common; using GitHub.Runner.Common;
@@ -168,4 +167,4 @@ namespace GitHub.Runner.Listener.Check
return result; return result;
} }
} }
} }

View File

@@ -2,7 +2,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.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Common; using GitHub.Runner.Common;
@@ -87,7 +86,7 @@ namespace GitHub.Runner.Listener.Check
result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************");
// Request to github.com or ghes server // Request to github.com or ghes server
Uri requestUrl = new Uri(url); Uri requestUrl = new(url);
var env = new Dictionary<string, string>() var env = new Dictionary<string, string>()
{ {
{ "HOSTNAME", requestUrl.Host }, { "HOSTNAME", requestUrl.Host },
@@ -179,4 +178,4 @@ namespace GitHub.Runner.Listener.Check
return result; return result;
} }
} }
} }

View File

@@ -4,7 +4,6 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using GitHub.DistributedTask.Logging;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
@@ -12,7 +11,7 @@ namespace GitHub.Runner.Listener
{ {
public sealed class CommandSettings public sealed class CommandSettings
{ {
private readonly Dictionary<string, string> _envArgs = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, string> _envArgs = new(StringComparer.OrdinalIgnoreCase);
private readonly CommandLineParser _parser; private readonly CommandLineParser _parser;
private readonly IPromptManager _promptManager; private readonly IPromptManager _promptManager;
private readonly Tracing _trace; private readonly Tracing _trace;
@@ -27,7 +26,7 @@ namespace GitHub.Runner.Listener
}; };
// Valid flags and args for specific command - key: command, value: array of valid flags and args // Valid flags and args for specific command - key: command, value: array of valid flags and args
private readonly Dictionary<string, string[]> validOptions = new Dictionary<string, string[]> private readonly Dictionary<string, string[]> validOptions = new()
{ {
// Valid configure flags and args // Valid configure flags and args
[Constants.Runner.CommandLine.Commands.Configure] = [Constants.Runner.CommandLine.Commands.Configure] =
@@ -35,11 +34,11 @@ namespace GitHub.Runner.Listener
{ {
Constants.Runner.CommandLine.Flags.DisableUpdate, Constants.Runner.CommandLine.Flags.DisableUpdate,
Constants.Runner.CommandLine.Flags.Ephemeral, Constants.Runner.CommandLine.Flags.Ephemeral,
Constants.Runner.CommandLine.Flags.GenerateServiceConfig,
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,
Constants.Runner.CommandLine.Args.Auth, Constants.Runner.CommandLine.Args.Auth,
Constants.Runner.CommandLine.Args.JitConfig,
Constants.Runner.CommandLine.Args.Labels, Constants.Runner.CommandLine.Args.Labels,
Constants.Runner.CommandLine.Args.MonitorSocketAddress, Constants.Runner.CommandLine.Args.MonitorSocketAddress,
Constants.Runner.CommandLine.Args.Name, Constants.Runner.CommandLine.Args.Name,
@@ -64,6 +63,7 @@ namespace GitHub.Runner.Listener
new string[] new string[]
{ {
Constants.Runner.CommandLine.Flags.Once, Constants.Runner.CommandLine.Flags.Once,
Constants.Runner.CommandLine.Args.JitConfig,
Constants.Runner.CommandLine.Args.StartupType Constants.Runner.CommandLine.Args.StartupType
}, },
// valid warmup flags and args // valid warmup flags and args
@@ -80,11 +80,12 @@ namespace GitHub.Runner.Listener
// Flags. // Flags.
public bool Check => TestFlag(Constants.Runner.CommandLine.Flags.Check); public bool Check => TestFlag(Constants.Runner.CommandLine.Flags.Check);
public bool Commit => TestFlag(Constants.Runner.CommandLine.Flags.Commit); public bool Commit => TestFlag(Constants.Runner.CommandLine.Flags.Commit);
public bool DisableUpdate => TestFlag(Constants.Runner.CommandLine.Flags.DisableUpdate);
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
public bool GenerateServiceConfig => TestFlag(Constants.Runner.CommandLine.Flags.GenerateServiceConfig);
public bool Help => TestFlag(Constants.Runner.CommandLine.Flags.Help); public bool Help => TestFlag(Constants.Runner.CommandLine.Flags.Help);
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended); public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version); public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
public bool DisableUpdate => TestFlag(Constants.Runner.CommandLine.Flags.DisableUpdate);
// Keep this around since customers still relies on it // Keep this around since customers still relies on it
public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once); public bool RunOnce => TestFlag(Constants.Runner.CommandLine.Flags.Once);
@@ -138,7 +139,7 @@ namespace GitHub.Runner.Listener
// Validate commandline parser result // Validate commandline parser result
public List<string> Validate() public List<string> Validate()
{ {
List<string> unknowns = new List<string>(); List<string> unknowns = new();
// detect unknown commands // detect unknown commands
unknowns.AddRange(_parser.Commands.Where(x => !validOptions.Keys.Contains(x, StringComparer.OrdinalIgnoreCase))); unknowns.AddRange(_parser.Commands.Where(x => !validOptions.Keys.Contains(x, StringComparer.OrdinalIgnoreCase)));

View File

@@ -3,6 +3,7 @@ using GitHub.Runner.Common;
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.Common.Internal;
using GitHub.Services.OAuth; using GitHub.Services.OAuth;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -80,12 +81,33 @@ namespace GitHub.Runner.Listener.Configuration
_term.WriteLine("--------------------------------------------------------------------------------"); _term.WriteLine("--------------------------------------------------------------------------------");
Trace.Info(nameof(ConfigureAsync)); Trace.Info(nameof(ConfigureAsync));
if (command.GenerateServiceConfig)
{
#if OS_LINUX
if (!IsConfigured())
{
throw new InvalidOperationException("--generateServiceConfig requires that the runner is already configured. For configuring a new runner as a service, run './config.sh'.");
}
RunnerSettings settings = _store.GetSettings();
Trace.Info($"generate service config for runner: {settings.AgentId}");
var controlManager = HostContext.GetService<ILinuxServiceControlManager>();
controlManager.GenerateScripts(settings);
return;
#else
throw new NotSupportedException("--generateServiceConfig is only supported on Linux.");
#endif
}
if (IsConfigured()) if (IsConfigured())
{ {
throw new InvalidOperationException("Cannot configure the runner because it is already configured. To reconfigure the runner, run 'config.cmd remove' or './config.sh remove' first."); throw new InvalidOperationException("Cannot configure the runner because it is already configured. To reconfigure the runner, run 'config.cmd remove' or './config.sh remove' first.");
} }
RunnerSettings runnerSettings = new RunnerSettings(); RunnerSettings runnerSettings = new();
// Loop getting url and creds until you can connect // Loop getting url and creds until you can connect
ICredentialProvider credProvider = null; ICredentialProvider credProvider = null;
@@ -128,7 +150,7 @@ namespace GitHub.Runner.Listener.Configuration
// Example githubServerUrl is https://my-ghes // Example githubServerUrl is https://my-ghes
var actionsServerUrl = new Uri(runnerSettings.ServerUrl); var actionsServerUrl = new Uri(runnerSettings.ServerUrl);
var githubServerUrl = new Uri(runnerSettings.GitHubUrl); var githubServerUrl = new Uri(runnerSettings.GitHubUrl);
if (!string.Equals(actionsServerUrl.Authority, githubServerUrl.Authority, StringComparison.OrdinalIgnoreCase)) if (!UriUtility.IsSubdomainOf(actionsServerUrl.Authority, githubServerUrl.Authority))
{ {
throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}."); throw new InvalidOperationException($"GitHub Actions is not properly configured in GHES. GHES url: {runnerSettings.GitHubUrl}, Actions url: {runnerSettings.ServerUrl}.");
} }
@@ -520,7 +542,7 @@ namespace GitHub.Runner.Listener.Configuration
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate) private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
{ {
TaskAgent agent = new TaskAgent(agentName) TaskAgent agent = new(agentName)
{ {
Authorization = new TaskAgentAuthorization Authorization = new TaskAgentAuthorization
{ {

View File

@@ -18,7 +18,7 @@ namespace GitHub.Runner.Listener.Configuration
public class CredentialManager : RunnerService, ICredentialManager public class CredentialManager : RunnerService, ICredentialManager
{ {
public static readonly Dictionary<string, Type> CredentialTypes = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase) public static readonly Dictionary<string, Type> CredentialTypes = new(StringComparer.OrdinalIgnoreCase)
{ {
{ Constants.Configuration.OAuth, typeof(OAuthCredential)}, { Constants.Configuration.OAuth, typeof(OAuthCredential)},
{ Constants.Configuration.OAuthAccessToken, typeof(OAuthAccessTokenCredential)}, { Constants.Configuration.OAuthAccessToken, typeof(OAuthAccessTokenCredential)},

View File

@@ -48,7 +48,7 @@ namespace GitHub.Runner.Listener.Configuration
ArgUtil.NotNullOrEmpty(token, nameof(token)); ArgUtil.NotNullOrEmpty(token, nameof(token));
trace.Info("token retrieved: {0} chars", token.Length); trace.Info("token retrieved: {0} chars", token.Length);
VssCredentials creds = new VssCredentials(new VssOAuthAccessTokenCredential(token), CredentialPromptType.DoNotPrompt); VssCredentials creds = new(new VssOAuthAccessTokenCredential(token), CredentialPromptType.DoNotPrompt);
trace.Info("cred created"); trace.Info("cred created");
return creds; return creds;

View File

@@ -1,5 +1,4 @@
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
@@ -72,7 +71,7 @@ namespace GitHub.Runner.Listener.Configuration
{ {
return defaultValue; return defaultValue;
} }
else if (isOptional) else if (isOptional)
{ {
return string.Empty; return string.Empty;
} }
@@ -87,11 +86,12 @@ namespace GitHub.Runner.Listener.Configuration
// Write the message prompt. // Write the message prompt.
_terminal.Write($"{description} "); _terminal.Write($"{description} ");
if(!string.IsNullOrEmpty(defaultValue)) if (!string.IsNullOrEmpty(defaultValue))
{ {
_terminal.Write($"[press Enter for {defaultValue}] "); _terminal.Write($"[press Enter for {defaultValue}] ");
} }
else if (isOptional){ else if (isOptional)
{
_terminal.Write($"[press Enter to skip] "); _terminal.Write($"[press Enter to skip] ");
} }
@@ -112,7 +112,7 @@ namespace GitHub.Runner.Listener.Configuration
return string.Empty; return string.Empty;
} }
} }
// Return the value if it is not empty and it is valid. // Return the value if it is not empty and it is valid.
// Otherwise try the loop again. // Otherwise try the loop again.
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))

View File

@@ -3,7 +3,6 @@ using System;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;

View File

@@ -44,7 +44,7 @@ namespace GitHub.Runner.Listener.Configuration
} }
// For the service name, replace any characters outside of the alpha-numeric set and ".", "_", "-" with "-" // For the service name, replace any characters outside of the alpha-numeric set and ".", "_", "-" with "-"
Regex regex = new Regex(@"[^0-9a-zA-Z._\-]"); Regex regex = new(@"[^0-9a-zA-Z._\-]");
string repoOrOrgName = regex.Replace(settings.RepoOrOrgName, "-"); string repoOrOrgName = regex.Replace(settings.RepoOrOrgName, "-");
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgName, settings.AgentName); serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgName, settings.AgentName);

View File

@@ -1,4 +1,4 @@
#if OS_LINUX #if OS_LINUX
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -6,7 +6,6 @@ using System.Linq;
using System.Text; using System.Text;
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Listener.Configuration namespace GitHub.Runner.Listener.Configuration
{ {

View File

@@ -27,6 +27,7 @@ namespace GitHub.Runner.Listener
bool Cancel(JobCancelMessage message); bool Cancel(JobCancelMessage message);
Task WaitAsync(CancellationToken token); Task WaitAsync(CancellationToken token);
Task ShutdownAsync(); Task ShutdownAsync();
event EventHandler<JobStatusEventArgs> JobStatus;
} }
// This implementation of IJobDispatcher is not thread safe. // This implementation of IJobDispatcher is not thread safe.
@@ -36,8 +37,8 @@ namespace GitHub.Runner.Listener
// and the server will not send another job while this one is still running. // and the server will not send another job while this one is still running.
public sealed class JobDispatcher : RunnerService, IJobDispatcher public sealed class JobDispatcher : RunnerService, IJobDispatcher
{ {
private static Regex _invalidJsonRegex = new Regex(@"invalid\ Json\ at\ position\ '(\d+)':", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex _invalidJsonRegex = new(@"invalid\ Json\ at\ position\ '(\d+)':", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new Lazy<Dictionary<long, TaskResult>>(); private readonly Lazy<Dictionary<long, TaskResult>> _localRunJobResult = new();
private int _poolId; private int _poolId;
IConfigurationStore _configurationStore; IConfigurationStore _configurationStore;
@@ -46,14 +47,16 @@ namespace GitHub.Runner.Listener
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
private readonly Queue<Guid> _jobDispatchedQueue = new Queue<Guid>(); private readonly Queue<Guid> _jobDispatchedQueue = new();
private readonly ConcurrentDictionary<Guid, WorkerDispatcher> _jobInfos = new ConcurrentDictionary<Guid, WorkerDispatcher>(); private readonly ConcurrentDictionary<Guid, WorkerDispatcher> _jobInfos = new();
// allow up to 30sec for any data to be transmitted over the process channel // allow up to 30sec for any data to be transmitted over the process channel
// timeout limit can be overwritten by environment GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT // timeout limit can be overwritten by environment GITHUB_ACTIONS_RUNNER_CHANNEL_TIMEOUT
private TimeSpan _channelTimeout; private TimeSpan _channelTimeout;
private TaskCompletionSource<bool> _runOnceJobCompleted = new TaskCompletionSource<bool>(); private TaskCompletionSource<bool> _runOnceJobCompleted = new();
public event EventHandler<JobStatusEventArgs> JobStatus;
public override void Initialize(IHostContext hostContext) public override void Initialize(IHostContext hostContext)
{ {
@@ -108,7 +111,7 @@ namespace GitHub.Runner.Listener
} }
} }
WorkerDispatcher newDispatch = new WorkerDispatcher(jobRequestMessage.JobId, jobRequestMessage.RequestId); WorkerDispatcher newDispatch = new(jobRequestMessage.JobId, jobRequestMessage.RequestId);
if (runOnce) if (runOnce)
{ {
Trace.Info("Start dispatcher for one time used runner."); Trace.Info("Start dispatcher for one time used runner.");
@@ -335,6 +338,11 @@ namespace GitHub.Runner.Listener
Busy = true; Busy = true;
try try
{ {
if (JobStatus != null)
{
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Busy));
}
if (previousJobDispatch != null) if (previousJobDispatch != null)
{ {
Trace.Verbose($"Make sure the previous job request {previousJobDispatch.JobId} has successfully finished on worker."); Trace.Verbose($"Make sure the previous job request {previousJobDispatch.JobId} has successfully finished on worker.");
@@ -349,7 +357,7 @@ namespace GitHub.Runner.Listener
term.WriteLine($"{DateTime.UtcNow:u}: Running job: {message.JobDisplayName}"); term.WriteLine($"{DateTime.UtcNow:u}: Running job: {message.JobDisplayName}");
// first job request renew succeed. // first job request renew succeed.
TaskCompletionSource<int> firstJobRequestRenewed = new TaskCompletionSource<int>(); TaskCompletionSource<int> firstJobRequestRenewed = new();
var notification = HostContext.GetService<IJobNotification>(); var notification = HostContext.GetService<IJobNotification>();
// lock renew cancellation token. // lock renew cancellation token.
@@ -390,8 +398,9 @@ namespace GitHub.Runner.Listener
HostContext.WritePerfCounter($"JobRequestRenewed_{requestId.ToString()}"); HostContext.WritePerfCounter($"JobRequestRenewed_{requestId.ToString()}");
Task<int> workerProcessTask = null; Task<int> workerProcessTask = null;
object _outputLock = new object(); object _outputLock = new();
List<string> workerOutput = new List<string>(); List<string> workerOutput = new();
bool printToStdout = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Agent.PrintLogToStdout));
using (var processChannel = HostContext.CreateService<IProcessChannel>()) using (var processChannel = HostContext.CreateService<IProcessChannel>())
using (var processInvoker = HostContext.CreateService<IProcessInvoker>()) using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
{ {
@@ -413,7 +422,15 @@ namespace GitHub.Runner.Listener
{ {
lock (_outputLock) lock (_outputLock)
{ {
workerOutput.Add(stdout.Data); if (!stdout.Data.StartsWith("[WORKER"))
{
workerOutput.Add(stdout.Data);
}
if (printToStdout)
{
term.WriteLine(stdout.Data, skipTracing: true);
}
} }
} }
}; };
@@ -650,6 +667,11 @@ namespace GitHub.Runner.Listener
finally finally
{ {
Busy = false; Busy = false;
if (JobStatus != null)
{
JobStatus(this, new JobStatusEventArgs(TaskAgentStatus.Online));
}
} }
} }
@@ -923,7 +945,7 @@ namespace GitHub.Runner.Listener
var runnerServer = HostContext.GetService<IRunnerServer>(); var runnerServer = HostContext.GetService<IRunnerServer>();
int completeJobRequestRetryLimit = 5; int completeJobRequestRetryLimit = 5;
List<Exception> exceptions = new List<Exception>(); List<Exception> exceptions = new();
while (completeJobRequestRetryLimit-- > 0) while (completeJobRequestRetryLimit-- > 0)
{ {
try try
@@ -1026,7 +1048,7 @@ namespace GitHub.Runner.Listener
public Task WorkerDispatch { get; set; } public Task WorkerDispatch { get; set; }
public CancellationTokenSource WorkerCancellationTokenSource { get; private set; } public CancellationTokenSource WorkerCancellationTokenSource { get; private set; }
public CancellationTokenSource WorkerCancelTimeoutKillTokenSource { get; private set; } public CancellationTokenSource WorkerCancelTimeoutKillTokenSource { get; private set; }
private readonly object _lock = new object(); private readonly object _lock = new();
public WorkerDispatcher(Guid jobId, long requestId) public WorkerDispatcher(Guid jobId, long requestId)
{ {

View File

@@ -23,6 +23,7 @@ namespace GitHub.Runner.Listener
Task DeleteSessionAsync(); Task DeleteSessionAsync();
Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token); Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token);
Task DeleteMessageAsync(TaskAgentMessage message); Task DeleteMessageAsync(TaskAgentMessage message);
void OnJobStatus(object sender, JobStatusEventArgs e);
} }
public sealed class MessageListener : RunnerService, IMessageListener public sealed class MessageListener : RunnerService, IMessageListener
@@ -37,7 +38,9 @@ namespace GitHub.Runner.Listener
private readonly TimeSpan _sessionCreationRetryInterval = TimeSpan.FromSeconds(30); private readonly TimeSpan _sessionCreationRetryInterval = TimeSpan.FromSeconds(30);
private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4); private readonly TimeSpan _sessionConflictRetryLimit = TimeSpan.FromMinutes(4);
private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30); private readonly TimeSpan _clockSkewRetryLimit = TimeSpan.FromMinutes(30);
private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new Dictionary<string, int>(); private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new();
private TaskAgentStatus runnerStatus = TaskAgentStatus.Online;
private CancellationTokenSource _getMessagesTokenSource;
public override void Initialize(IHostContext hostContext) public override void Initialize(IHostContext hostContext)
{ {
@@ -170,6 +173,23 @@ namespace GitHub.Runner.Listener
} }
} }
public void OnJobStatus(object sender, JobStatusEventArgs e)
{
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
{
Trace.Info("Received job status event. JobState: {0}", e.Status);
runnerStatus = e.Status;
try
{
_getMessagesTokenSource?.Cancel();
}
catch (ObjectDisposedException)
{
Trace.Info("_getMessagesTokenSource is already disposed.");
}
}
}
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token) public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
{ {
Trace.Entering(); Trace.Entering();
@@ -178,18 +198,21 @@ namespace GitHub.Runner.Listener
bool encounteringError = false; bool encounteringError = false;
int continuousError = 0; int continuousError = 0;
string errorMessage = string.Empty; string errorMessage = string.Empty;
Stopwatch heartbeat = new Stopwatch(); Stopwatch heartbeat = new();
heartbeat.Restart(); heartbeat.Restart();
while (true) while (true)
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
TaskAgentMessage message = null; TaskAgentMessage message = null;
_getMessagesTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
try try
{ {
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId, message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
_session.SessionId, _session.SessionId,
_lastMessageId, _lastMessageId,
token); runnerStatus,
BuildConstants.RunnerPackage.Version,
_getMessagesTokenSource.Token);
// Decrypt the message body if the session is using encryption // Decrypt the message body if the session is using encryption
message = DecryptMessage(message); message = DecryptMessage(message);
@@ -206,6 +229,11 @@ namespace GitHub.Runner.Listener
continuousError = 0; continuousError = 0;
} }
} }
catch (OperationCanceledException) when (_getMessagesTokenSource.Token.IsCancellationRequested && !token.IsCancellationRequested)
{
Trace.Info("Get messages has been cancelled using local token source. Continue to get messages with new status.");
continue;
}
catch (OperationCanceledException) when (token.IsCancellationRequested) catch (OperationCanceledException) when (token.IsCancellationRequested)
{ {
Trace.Info("Get next message has been cancelled."); Trace.Info("Get next message has been cancelled.");
@@ -261,6 +289,10 @@ namespace GitHub.Runner.Listener
await HostContext.Delay(_getNextMessageRetryInterval, token); await HostContext.Delay(_getNextMessageRetryInterval, token);
} }
} }
finally
{
_getMessagesTokenSource.Dispose();
}
if (message == null) if (message == null)
{ {

View File

@@ -1,12 +1,10 @@
using GitHub.Runner.Common; using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace GitHub.Runner.Listener namespace GitHub.Runner.Listener
@@ -18,7 +16,7 @@ namespace GitHub.Runner.Listener
// Add environment variables from .env file // Add environment variables from .env file
LoadAndSetEnv(); LoadAndSetEnv();
using (HostContext context = new HostContext("Runner")) using (HostContext context = new("Runner"))
{ {
return MainAsync(context, args).GetAwaiter().GetResult(); return MainAsync(context, args).GetAwaiter().GetResult();
} }
@@ -60,6 +58,18 @@ namespace GitHub.Runner.Listener
terminal.WriteLine("This runner version is built for Windows. Please install a correct build for your OS."); terminal.WriteLine("This runner version is built for Windows. Please install a correct build for your OS.");
return Constants.Runner.ReturnCode.TerminatedError; return Constants.Runner.ReturnCode.TerminatedError;
} }
#if ARM64
// A little hacky, but windows gives no way to differentiate between windows 10 and 11.
// By default only 11 supports native x64 app emulation on arm, so we only want to support windows 11
// https://docs.microsoft.com/en-us/windows/arm/overview#build-windows-apps-that-run-on-arm
// Windows 10 and 11 share a MajorVersion, so we also check the build version. Minor for both is 0, so doing < 0 doesn't really make a lot of sense.
if (Environment.OSVersion.Version.Major < Constants.OperatingSystem.Windows11MajorVersion ||
Environment.OSVersion.Version.Build < Constants.OperatingSystem.Windows11BuildVersion)
{
terminal.WriteLine("Win-arm64 runners require windows 11 or later. Please upgrade your operating system.");
return Constants.Runner.ReturnCode.TerminatedError;
}
#endif
break; break;
default: default:
terminal.WriteLine($"Running the runner on this platform is not supported. The current platform is {RuntimeInformation.OSDescription} and it was built for {Constants.Runner.Platform.ToString()}."); terminal.WriteLine($"Running the runner on this platform is not supported. The current platform is {RuntimeInformation.OSDescription} and it was built for {Constants.Runner.Platform.ToString()}.");

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
@@ -19,7 +19,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.4.0" /> <PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.4.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" /> <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.4.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" /> <PackageReference Include="System.ServiceProcess.ServiceController" Version="4.4.0" />

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -29,7 +28,7 @@ namespace GitHub.Runner.Listener
private IMessageListener _listener; private IMessageListener _listener;
private ITerminal _term; private ITerminal _term;
private bool _inConfigStage; private bool _inConfigStage;
private ManualResetEvent _completedCommand = new ManualResetEvent(false); private ManualResetEvent _completedCommand = new(false);
public override void Initialize(IHostContext hostContext) public override void Initialize(IHostContext hostContext)
{ {
@@ -360,6 +359,8 @@ namespace GitHub.Runner.Listener
bool runOnceJobReceived = false; bool runOnceJobReceived = false;
jobDispatcher = HostContext.CreateService<IJobDispatcher>(); jobDispatcher = HostContext.CreateService<IJobDispatcher>();
jobDispatcher.JobStatus += _listener.OnJobStatus;
while (!HostContext.RunnerShutdownToken.IsCancellationRequested) while (!HostContext.RunnerShutdownToken.IsCancellationRequested)
{ {
TaskAgentMessage message = null; TaskAgentMessage message = null;
@@ -429,12 +430,22 @@ namespace GitHub.Runner.Listener
message = await getNextMessage; //get next message message = await getNextMessage; //get next message
HostContext.WritePerfCounter($"MessageReceived_{message.MessageType}"); HostContext.WritePerfCounter($"MessageReceived_{message.MessageType}");
if (string.Equals(message.MessageType, AgentRefreshMessage.MessageType, StringComparison.OrdinalIgnoreCase)) if (string.Equals(message.MessageType, AgentRefreshMessage.MessageType, StringComparison.OrdinalIgnoreCase) ||
string.Equals(message.MessageType, RunnerRefreshMessage.MessageType, StringComparison.OrdinalIgnoreCase))
{ {
if (autoUpdateInProgress == false) if (autoUpdateInProgress == false)
{ {
autoUpdateInProgress = true; autoUpdateInProgress = true;
var runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body); AgentRefreshMessage runnerUpdateMessage = null;
if (string.Equals(message.MessageType, AgentRefreshMessage.MessageType, StringComparison.OrdinalIgnoreCase))
{
runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body);
}
else
{
var brokerRunnerUpdateMessage = JsonUtility.FromString<RunnerRefreshMessage>(message.Body);
runnerUpdateMessage = new AgentRefreshMessage(brokerRunnerUpdateMessage.RunnerId, brokerRunnerUpdateMessage.TargetVersion, TimeSpan.FromSeconds(brokerRunnerUpdateMessage.TimeoutInSeconds));
}
#if DEBUG #if DEBUG
// Can mock the update for testing // Can mock the update for testing
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_IS_MOCK_UPDATE"))) if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_IS_MOCK_UPDATE")))
@@ -495,16 +506,26 @@ namespace GitHub.Runner.Listener
else else
{ {
var messageRef = StringUtil.ConvertFromJson<RunnerJobRequestRef>(message.Body); var messageRef = StringUtil.ConvertFromJson<RunnerJobRequestRef>(message.Body);
Pipelines.AgentJobRequestMessage jobRequestMessage = null;
// Create connection // Create connection
var credMgr = HostContext.GetService<ICredentialManager>(); var credMgr = HostContext.GetService<ICredentialManager>();
var creds = credMgr.LoadCredentials(); var creds = credMgr.LoadCredentials();
var runServer = HostContext.CreateService<IRunServer>(); if (string.IsNullOrEmpty(messageRef.RunServiceUrl))
await runServer.ConnectAsync(new Uri(settings.ServerUrl), creds); {
var jobMessage = await runServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token); var actionsRunServer = HostContext.CreateService<IActionsRunServer>();
await actionsRunServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
jobRequestMessage = await actionsRunServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token);
}
else
{
var runServer = HostContext.CreateService<IRunServer>();
await runServer.ConnectAsync(new Uri(messageRef.RunServiceUrl), creds);
jobRequestMessage = await runServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token);
}
jobDispatcher.Run(jobMessage, runOnce); jobDispatcher.Run(jobRequestMessage, runOnce);
if (runOnce) if (runOnce)
{ {
Trace.Info("One time used runner received job message."); Trace.Info("One time used runner received job message.");
@@ -561,6 +582,7 @@ namespace GitHub.Runner.Listener
{ {
if (jobDispatcher != null) if (jobDispatcher != null)
{ {
jobDispatcher.JobStatus -= _listener.OnJobStatus;
await jobDispatcher.ShutdownAsync(); await jobDispatcher.ShutdownAsync();
} }
@@ -627,7 +649,7 @@ Config Options:
--labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}' --labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
--work string Relative runner work directory (default {Constants.Path.WorkDirectory}) --work string Relative runner work directory (default {Constants.Path.WorkDirectory})
--replace Replace any existing runner with the same name (default false) --replace Replace any existing runner with the same name (default false)
--pat GitHub personal access token used for checking network connectivity when executing `.{separator}run.{ext} --check` --pat GitHub personal access token with repo scope. Used for checking network connectivity when executing `.{separator}run.{ext} --check`
--disableupdate Disable self-hosted runner automatic update to the latest released version` --disableupdate Disable self-hosted runner automatic update to the latest released version`
--ephemeral Configure the runner to only take one job and then let the service un-configure the runner after the job finishes (default false)"); --ephemeral Configure the runner to only take one job and then let the service un-configure the runner after the job finishes (default false)");

View File

@@ -9,5 +9,7 @@ namespace GitHub.Runner.Listener
public string Id { get; set; } public string Id { get; set; }
[DataMember(Name = "runner_request_id")] [DataMember(Name = "runner_request_id")]
public string RunnerRequestId { get; set; } public string RunnerRequestId { get; set; }
[DataMember(Name = "run_service_url")]
public string RunServiceUrl { get; set; }
} }
} }

View File

@@ -32,14 +32,14 @@ namespace GitHub.Runner.Listener
private static string _platform = BuildConstants.RunnerPackage.PackageName; private static string _platform = BuildConstants.RunnerPackage.PackageName;
private static string _dotnetRuntime = "dotnetRuntime"; private static string _dotnetRuntime = "dotnetRuntime";
private static string _externals = "externals"; private static string _externals = "externals";
private readonly Dictionary<string, string> _contentHashes = new Dictionary<string, string>(); private readonly Dictionary<string, string> _contentHashes = new();
private PackageMetadata _targetPackage; private PackageMetadata _targetPackage;
private ITerminal _terminal; private ITerminal _terminal;
private IRunnerServer _runnerServer; private IRunnerServer _runnerServer;
private int _poolId; private int _poolId;
private int _agentId; private int _agentId;
private readonly ConcurrentQueue<string> _updateTrace = new ConcurrentQueue<string>(); private readonly ConcurrentQueue<string> _updateTrace = new();
private Task _cloneAndCalculateContentHashTask; private Task _cloneAndCalculateContentHashTask;
private string _dotnetRuntimeCloneDirectory; private string _dotnetRuntimeCloneDirectory;
private string _externalsCloneDirectory; private string _externalsCloneDirectory;
@@ -131,8 +131,10 @@ namespace GitHub.Runner.Listener
// For L0, we will skip execute update script. // For L0, we will skip execute update script.
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_EXECUTE_UPDATE_SCRIPT"))) if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_EXECUTE_UPDATE_SCRIPT")))
{ {
string flagFile = "update.finished";
IOUtil.DeleteFile(flagFile);
// kick off update script // kick off update script
Process invokeScript = new Process(); Process invokeScript = new();
#if OS_WINDOWS #if OS_WINDOWS
invokeScript.StartInfo.FileName = WhichUtil.Which("cmd.exe", trace: Trace); invokeScript.StartInfo.FileName = WhichUtil.Which("cmd.exe", trace: Trace);
invokeScript.StartInfo.Arguments = $"/c \"{updateScript}\""; invokeScript.StartInfo.Arguments = $"/c \"{updateScript}\"";
@@ -189,9 +191,9 @@ namespace GitHub.Runner.Listener
} }
Trace.Info($"Version '{_targetPackage.Version}' of '{_targetPackage.Type}' package available in server."); Trace.Info($"Version '{_targetPackage.Version}' of '{_targetPackage.Type}' package available in server.");
PackageVersion serverVersion = new PackageVersion(_targetPackage.Version); PackageVersion serverVersion = new(_targetPackage.Version);
Trace.Info($"Current running runner version is {BuildConstants.RunnerPackage.Version}"); Trace.Info($"Current running runner version is {BuildConstants.RunnerPackage.Version}");
PackageVersion runnerVersion = new PackageVersion(BuildConstants.RunnerPackage.Version); PackageVersion runnerVersion = new(BuildConstants.RunnerPackage.Version);
return serverVersion.CompareTo(runnerVersion) > 0; return serverVersion.CompareTo(runnerVersion) > 0;
} }
@@ -294,12 +296,12 @@ namespace GitHub.Runner.Listener
archiveFile = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), $"runner{targetVersion}.tar.gz"); archiveFile = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), $"runner{targetVersion}.tar.gz");
} }
if (File.Exists(archiveFile)) if (File.Exists(archiveFile))
{ {
_updateTrace.Enqueue($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded"); _updateTrace.Enqueue($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded");
_terminal.WriteLine($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded"); _terminal.WriteLine($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded");
} }
else else
{ {
archiveFile = null; archiveFile = null;
_terminal.WriteLine($"Mock runner archive not found at {archiveFile} for target version {targetVersion}, proceeding with download instead"); _terminal.WriteLine($"Mock runner archive not found at {archiveFile} for target version {targetVersion}, proceeding with download instead");
@@ -474,7 +476,7 @@ namespace GitHub.Runner.Listener
long downloadSize = 0; long downloadSize = 0;
//open zip stream in async mode //open zip stream in async mode
using (HttpClient httpClient = new HttpClient(HostContext.CreateHttpClientHandler())) using (HttpClient httpClient = new(HostContext.CreateHttpClientHandler()))
{ {
if (!string.IsNullOrEmpty(_targetPackage.Token)) if (!string.IsNullOrEmpty(_targetPackage.Token))
{ {
@@ -484,7 +486,7 @@ namespace GitHub.Runner.Listener
Trace.Info($"Downloading {packageDownloadUrl}"); Trace.Info($"Downloading {packageDownloadUrl}");
using (FileStream fs = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) using (FileStream fs = new(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
using (Stream result = await httpClient.GetStreamAsync(packageDownloadUrl)) using (Stream result = await httpClient.GetStreamAsync(packageDownloadUrl))
{ {
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k). //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
@@ -594,7 +596,7 @@ namespace GitHub.Runner.Listener
int exitCode = await processInvoker.ExecuteAsync(extractDirectory, tar, $"-xzf \"{archiveFile}\"", null, token); int exitCode = await processInvoker.ExecuteAsync(extractDirectory, tar, $"-xzf \"{archiveFile}\"", null, token);
if (exitCode != 0) if (exitCode != 0)
{ {
throw new NotSupportedException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. return code: {exitCode}."); throw new NotSupportedException($"Can't use 'tar -xzf' to extract archive file: {archiveFile}. return code: {exitCode}.");
} }
} }
} }

View File

@@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
@@ -15,7 +12,7 @@ namespace GitHub.Runner.PluginHost
{ {
public static class Program public static class Program
{ {
private static CancellationTokenSource tokenSource = new CancellationTokenSource(); private static CancellationTokenSource tokenSource = new();
private static string executingAssemblyLocation = string.Empty; private static string executingAssemblyLocation = string.Empty;
public static int Main(string[] args) public static int Main(string[] args)

View File

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

View File

@@ -63,7 +63,7 @@ namespace GitHub.Runner.Plugins.Artifact
string containerPath = actionsStorageArtifact.Name; // In actions storage artifacts, name equals the path string containerPath = actionsStorageArtifact.Name; // In actions storage artifacts, name equals the path
long containerId = actionsStorageArtifact.ContainerId; long containerId = actionsStorageArtifact.ContainerId;
FileContainerServer fileContainerServer = new FileContainerServer(context.VssConnection, projectId: new Guid(), containerId, containerPath); FileContainerServer fileContainerServer = new(context.VssConnection, projectId: new Guid(), containerId, containerPath);
await fileContainerServer.DownloadFromContainerAsync(context, targetPath, token); await fileContainerServer.DownloadFromContainerAsync(context, targetPath, token);
context.Output("Artifact download finished."); context.Output("Artifact download finished.");

View File

@@ -23,10 +23,10 @@ namespace GitHub.Runner.Plugins.Artifact
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k). //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
private const int _defaultCopyBufferSize = 81920; private const int _defaultCopyBufferSize = 81920;
private readonly ConcurrentQueue<string> _fileUploadQueue = new ConcurrentQueue<string>(); private readonly ConcurrentQueue<string> _fileUploadQueue = new();
private readonly ConcurrentQueue<DownloadInfo> _fileDownloadQueue = new ConcurrentQueue<DownloadInfo>(); private readonly ConcurrentQueue<DownloadInfo> _fileDownloadQueue = new();
private readonly ConcurrentDictionary<string, ConcurrentQueue<string>> _fileUploadTraceLog = new ConcurrentDictionary<string, ConcurrentQueue<string>>(); private readonly ConcurrentDictionary<string, ConcurrentQueue<string>> _fileUploadTraceLog = new();
private readonly ConcurrentDictionary<string, ConcurrentQueue<string>> _fileUploadProgressLog = new ConcurrentDictionary<string, ConcurrentQueue<string>>(); private readonly ConcurrentDictionary<string, ConcurrentQueue<string>> _fileUploadProgressLog = new();
private readonly FileContainerHttpClient _fileContainerHttpClient; private readonly FileContainerHttpClient _fileContainerHttpClient;
private CancellationTokenSource _uploadCancellationTokenSource; private CancellationTokenSource _uploadCancellationTokenSource;
@@ -67,7 +67,7 @@ namespace GitHub.Runner.Plugins.Artifact
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// Find out all container items need to be processed // Find out all container items need to be processed
List<FileContainerItem> containerItems = new List<FileContainerItem>(); List<FileContainerItem> containerItems = new();
int retryCount = 0; int retryCount = 0;
while (retryCount < 3) while (retryCount < 3)
{ {
@@ -106,7 +106,7 @@ namespace GitHub.Runner.Plugins.Artifact
// Create all required empty folders and emptry files, gather a list of files that we need to download from server. // Create all required empty folders and emptry files, gather a list of files that we need to download from server.
int foldersCreated = 0; int foldersCreated = 0;
int emptryFilesCreated = 0; int emptryFilesCreated = 0;
List<DownloadInfo> downloadFiles = new List<DownloadInfo>(); List<DownloadInfo> downloadFiles = new();
foreach (var item in containerItems.OrderBy(x => x.Path)) foreach (var item in containerItems.OrderBy(x => x.Path))
{ {
if (!item.Path.StartsWith(_containerPath, StringComparison.OrdinalIgnoreCase)) if (!item.Path.StartsWith(_containerPath, StringComparison.OrdinalIgnoreCase))
@@ -306,7 +306,7 @@ namespace GitHub.Runner.Plugins.Artifact
Task downloadMonitor = DownloadReportingAsync(context, files.Count(), token); Task downloadMonitor = DownloadReportingAsync(context, files.Count(), token);
// Start parallel download tasks. // Start parallel download tasks.
List<Task<DownloadResult>> parallelDownloadingTasks = new List<Task<DownloadResult>>(); List<Task<DownloadResult>> parallelDownloadingTasks = new();
for (int downloader = 0; downloader < concurrentDownloads; downloader++) for (int downloader = 0; downloader < concurrentDownloads; downloader++)
{ {
parallelDownloadingTasks.Add(DownloadAsync(context, downloader, token)); parallelDownloadingTasks.Add(DownloadAsync(context, downloader, token));
@@ -358,7 +358,7 @@ namespace GitHub.Runner.Plugins.Artifact
Task uploadMonitor = UploadReportingAsync(context, files.Count(), _uploadCancellationTokenSource.Token); Task uploadMonitor = UploadReportingAsync(context, files.Count(), _uploadCancellationTokenSource.Token);
// Start parallel upload tasks. // Start parallel upload tasks.
List<Task<UploadResult>> parallelUploadingTasks = new List<Task<UploadResult>>(); List<Task<UploadResult>> parallelUploadingTasks = new();
for (int uploader = 0; uploader < concurrentUploads; uploader++) for (int uploader = 0; uploader < concurrentUploads; uploader++)
{ {
parallelUploadingTasks.Add(UploadAsync(context, uploader, _uploadCancellationTokenSource.Token)); parallelUploadingTasks.Add(UploadAsync(context, uploader, _uploadCancellationTokenSource.Token));
@@ -381,8 +381,8 @@ namespace GitHub.Runner.Plugins.Artifact
private async Task<DownloadResult> DownloadAsync(RunnerActionPluginExecutionContext context, int downloaderId, CancellationToken token) private async Task<DownloadResult> DownloadAsync(RunnerActionPluginExecutionContext context, int downloaderId, CancellationToken token)
{ {
List<DownloadInfo> failedFiles = new List<DownloadInfo>(); List<DownloadInfo> failedFiles = new();
Stopwatch downloadTimer = new Stopwatch(); Stopwatch downloadTimer = new();
while (_fileDownloadQueue.TryDequeue(out DownloadInfo fileToDownload)) while (_fileDownloadQueue.TryDequeue(out DownloadInfo fileToDownload))
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
@@ -396,7 +396,7 @@ namespace GitHub.Runner.Plugins.Artifact
{ {
context.Debug($"Start downloading file: '{fileToDownload.ItemPath}' (Downloader {downloaderId})"); context.Debug($"Start downloading file: '{fileToDownload.ItemPath}' (Downloader {downloaderId})");
downloadTimer.Restart(); downloadTimer.Restart();
using (FileStream fs = new FileStream(fileToDownload.LocalPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true)) using (FileStream fs = new(fileToDownload.LocalPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
using (var downloadStream = await _fileContainerHttpClient.DownloadFileAsync(_containerId, fileToDownload.ItemPath, token, _projectId)) using (var downloadStream = await _fileContainerHttpClient.DownloadFileAsync(_containerId, fileToDownload.ItemPath, token, _projectId))
{ {
await downloadStream.CopyToAsync(fs, _defaultCopyBufferSize, token); await downloadStream.CopyToAsync(fs, _defaultCopyBufferSize, token);
@@ -453,10 +453,10 @@ namespace GitHub.Runner.Plugins.Artifact
private async Task<UploadResult> UploadAsync(RunnerActionPluginExecutionContext context, int uploaderId, CancellationToken token) private async Task<UploadResult> UploadAsync(RunnerActionPluginExecutionContext context, int uploaderId, CancellationToken token)
{ {
List<string> failedFiles = new List<string>(); List<string> failedFiles = new();
long uploadedSize = 0; long uploadedSize = 0;
string fileToUpload; string fileToUpload;
Stopwatch uploadTimer = new Stopwatch(); Stopwatch uploadTimer = new();
while (_fileUploadQueue.TryDequeue(out fileToUpload)) while (_fileUploadQueue.TryDequeue(out fileToUpload))
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();

View File

@@ -1,5 +1,3 @@
using System;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Actions.Pipelines.WebApi; using GitHub.Actions.Pipelines.WebApi;

View File

@@ -68,7 +68,7 @@ namespace GitHub.Runner.Plugins.Artifact
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}"); context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId: Guid.Empty, containerId, artifactName); FileContainerServer fileContainerHelper = new(context.VssConnection, projectId: Guid.Empty, containerId, artifactName);
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
long size = 0; long size = 0;
@@ -87,7 +87,7 @@ namespace GitHub.Runner.Plugins.Artifact
// Definition ID is a dummy value only used by HTTP client routing purposes // Definition ID is a dummy value only used by HTTP client routing purposes
int definitionId = 1; int definitionId = 1;
PipelinesServer pipelinesHelper = new PipelinesServer(context.VssConnection); PipelinesServer pipelinesHelper = new(context.VssConnection);
var artifact = await pipelinesHelper.AssociateActionsStorageArtifactAsync( var artifact = await pipelinesHelper.AssociateActionsStorageArtifactAsync(
definitionId, definitionId,

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -9,7 +8,6 @@ using System.Threading.Tasks;
using System.IO; using System.IO;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.DistributedTask.Pipelines.ContextData;
namespace GitHub.Runner.Plugins.Repository namespace GitHub.Runner.Plugins.Repository
{ {
@@ -20,7 +18,7 @@ namespace GitHub.Runner.Plugins.Repository
#else #else
private static readonly Encoding s_encoding = null; private static readonly Encoding s_encoding = null;
#endif #endif
private readonly Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) private readonly Dictionary<string, string> gitEnv = new(StringComparer.OrdinalIgnoreCase)
{ {
{ "GIT_TERMINAL_PROMPT", "0" }, { "GIT_TERMINAL_PROMPT", "0" },
}; };
@@ -94,11 +92,11 @@ namespace GitHub.Runner.Plugins.Repository
} }
// required 2.0, all git operation commandline args need min git version 2.0 // required 2.0, all git operation commandline args need min git version 2.0
Version minRequiredGitVersion = new Version(2, 0); Version minRequiredGitVersion = new(2, 0);
EnsureGitVersion(minRequiredGitVersion, throwOnNotMatch: true); EnsureGitVersion(minRequiredGitVersion, throwOnNotMatch: true);
// suggest user upgrade to 2.9 for better git experience // suggest user upgrade to 2.9 for better git experience
Version recommendGitVersion = new Version(2, 9); Version recommendGitVersion = new(2, 9);
if (!EnsureGitVersion(recommendGitVersion, throwOnNotMatch: false)) if (!EnsureGitVersion(recommendGitVersion, throwOnNotMatch: false))
{ {
context.Output($"To get a better Git experience, upgrade your Git to at least version '{recommendGitVersion}'. Your current Git version is '{gitVersion}'."); context.Output($"To get a better Git experience, upgrade your Git to at least version '{recommendGitVersion}'. Your current Git version is '{gitVersion}'.");
@@ -432,7 +430,7 @@ namespace GitHub.Runner.Plugins.Repository
context.Debug($"Inspect remote.origin.url for repository under {repositoryPath}"); context.Debug($"Inspect remote.origin.url for repository under {repositoryPath}");
Uri fetchUrl = null; Uri fetchUrl = null;
List<string> outputStrings = new List<string>(); List<string> outputStrings = new();
int exitCode = await ExecuteGitCommandAsync(context, repositoryPath, "config", "--get remote.origin.url", outputStrings); int exitCode = await ExecuteGitCommandAsync(context, repositoryPath, "config", "--get remote.origin.url", outputStrings);
if (exitCode != 0) if (exitCode != 0)
@@ -479,7 +477,7 @@ namespace GitHub.Runner.Plugins.Repository
context.Debug($"Checking git config {configKey} exist or not"); context.Debug($"Checking git config {configKey} exist or not");
// ignore any outputs by redirect them into a string list, since the output might contains secrets. // ignore any outputs by redirect them into a string list, since the output might contains secrets.
List<string> outputStrings = new List<string>(); List<string> outputStrings = new();
int exitcode = await ExecuteGitCommandAsync(context, repositoryPath, "config", StringUtil.Format($"--get-all {configKey}"), outputStrings); int exitcode = await ExecuteGitCommandAsync(context, repositoryPath, "config", StringUtil.Format($"--get-all {configKey}"), outputStrings);
return exitcode == 0; return exitcode == 0;
@@ -541,7 +539,7 @@ namespace GitHub.Runner.Plugins.Repository
string runnerWorkspace = context.GetRunnerContext("workspace"); string runnerWorkspace = context.GetRunnerContext("workspace");
ArgUtil.Directory(runnerWorkspace, "runnerWorkspace"); ArgUtil.Directory(runnerWorkspace, "runnerWorkspace");
Version version = null; Version version = null;
List<string> outputStrings = new List<string>(); List<string> outputStrings = new();
int exitCode = await ExecuteGitCommandAsync(context, runnerWorkspace, "version", null, outputStrings); int exitCode = await ExecuteGitCommandAsync(context, runnerWorkspace, "version", null, outputStrings);
context.Output($"{string.Join(Environment.NewLine, outputStrings)}"); context.Output($"{string.Join(Environment.NewLine, outputStrings)}");
if (exitCode == 0) if (exitCode == 0)
@@ -552,7 +550,7 @@ namespace GitHub.Runner.Plugins.Repository
{ {
string verString = outputStrings.First(); string verString = outputStrings.First();
// we interested about major.minor.patch version // we interested about major.minor.patch version
Regex verRegex = new Regex("\\d+\\.\\d+(\\.\\d+)?", RegexOptions.IgnoreCase); Regex verRegex = new("\\d+\\.\\d+(\\.\\d+)?", RegexOptions.IgnoreCase);
var matchResult = verRegex.Match(verString); var matchResult = verRegex.Match(verString);
if (matchResult.Success && !string.IsNullOrEmpty(matchResult.Value)) if (matchResult.Success && !string.IsNullOrEmpty(matchResult.Value))
{ {
@@ -574,7 +572,7 @@ namespace GitHub.Runner.Plugins.Repository
string runnerWorkspace = context.GetRunnerContext("workspace"); string runnerWorkspace = context.GetRunnerContext("workspace");
ArgUtil.Directory(runnerWorkspace, "runnerWorkspace"); ArgUtil.Directory(runnerWorkspace, "runnerWorkspace");
Version version = null; Version version = null;
List<string> outputStrings = new List<string>(); List<string> outputStrings = new();
int exitCode = await ExecuteGitCommandAsync(context, runnerWorkspace, "lfs version", null, outputStrings); int exitCode = await ExecuteGitCommandAsync(context, runnerWorkspace, "lfs version", null, outputStrings);
context.Output($"{string.Join(Environment.NewLine, outputStrings)}"); context.Output($"{string.Join(Environment.NewLine, outputStrings)}");
if (exitCode == 0) if (exitCode == 0)
@@ -585,7 +583,7 @@ namespace GitHub.Runner.Plugins.Repository
{ {
string verString = outputStrings.First(); string verString = outputStrings.First();
// we interested about major.minor.patch version // we interested about major.minor.patch version
Regex verRegex = new Regex("\\d+\\.\\d+(\\.\\d+)?", RegexOptions.IgnoreCase); Regex verRegex = new("\\d+\\.\\d+(\\.\\d+)?", RegexOptions.IgnoreCase);
var matchResult = verRegex.Match(verString); var matchResult = verRegex.Match(verString);
if (matchResult.Success && !string.IsNullOrEmpty(matchResult.Value)) if (matchResult.Success && !string.IsNullOrEmpty(matchResult.Value))
{ {

View File

@@ -6,11 +6,9 @@ using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Text; using System.Text;
using System.Diagnostics;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System.Linq; using System.Linq;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Services.WebApi;
namespace GitHub.Runner.Plugins.Repository.v1_0 namespace GitHub.Runner.Plugins.Repository.v1_0
{ {
@@ -23,7 +21,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
private const string _remotePullRefsPrefix = "refs/remotes/pull/"; private const string _remotePullRefsPrefix = "refs/remotes/pull/";
// min git version that support add extra auth header. // min git version that support add extra auth header.
private Version _minGitVersionSupportAuthHeader = new Version(2, 9); private Version _minGitVersionSupportAuthHeader = new(2, 9);
#if OS_WINDOWS #if OS_WINDOWS
// min git version that support override sslBackend setting. // min git version that support override sslBackend setting.
@@ -31,7 +29,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
#endif #endif
// min git-lfs version that support add extra auth header. // min git-lfs version that support add extra auth header.
private Version _minGitLfsVersionSupportAuthHeader = new Version(2, 1); private Version _minGitLfsVersionSupportAuthHeader = new(2, 1);
private void RequirementCheck(RunnerActionPluginExecutionContext executionContext, GitCliManager gitCommandManager, bool checkGitLfs) private void RequirementCheck(RunnerActionPluginExecutionContext executionContext, GitCliManager gitCommandManager, bool checkGitLfs)
{ {
@@ -85,7 +83,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
var githubUrl = executionContext.GetGitHubContext("server_url"); var githubUrl = executionContext.GetGitHubContext("server_url");
var githubUri = new Uri(!string.IsNullOrEmpty(githubUrl) ? githubUrl : "https://github.com"); var githubUri = new Uri(!string.IsNullOrEmpty(githubUrl) ? githubUrl : "https://github.com");
var portInfo = githubUri.IsDefaultPort ? string.Empty : $":{githubUri.Port}"; var portInfo = githubUri.IsDefaultPort ? string.Empty : $":{githubUri.Port}";
Uri repositoryUrl = new Uri($"{githubUri.Scheme}://{githubUri.Host}{portInfo}/{repoFullName}"); Uri repositoryUrl = new($"{githubUri.Scheme}://{githubUri.Host}{portInfo}/{repoFullName}");
if (!repositoryUrl.IsAbsoluteUri) if (!repositoryUrl.IsAbsoluteUri)
{ {
throw new InvalidOperationException("Repository url need to be an absolute uri."); throw new InvalidOperationException("Repository url need to be an absolute uri.");
@@ -123,7 +121,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
executionContext.Debug($"gitLfsSupport={gitLfsSupport}"); executionContext.Debug($"gitLfsSupport={gitLfsSupport}");
// Initialize git command manager with additional environment variables. // Initialize git command manager with additional environment variables.
Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); Dictionary<string, string> gitEnv = new(StringComparer.OrdinalIgnoreCase);
// Disable prompting for git credential manager // Disable prompting for git credential manager
gitEnv["GCM_INTERACTIVE"] = "Never"; gitEnv["GCM_INTERACTIVE"] = "Never";
@@ -143,7 +141,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty; gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
} }
GitCliManager gitCommandManager = new GitCliManager(gitEnv); GitCliManager gitCommandManager = new(gitEnv);
await gitCommandManager.LoadGitExecutionInfo(executionContext); await gitCommandManager.LoadGitExecutionInfo(executionContext);
// Make sure the build machine met all requirements for the git repository // Make sure the build machine met all requirements for the git repository
@@ -295,8 +293,8 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty); await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
} }
List<string> additionalFetchArgs = new List<string>(); List<string> additionalFetchArgs = new();
List<string> additionalLfsFetchArgs = new List<string>(); List<string> additionalLfsFetchArgs = new();
// add accessToken as basic auth header to handle auth challenge. // add accessToken as basic auth header to handle auth challenge.
if (!string.IsNullOrEmpty(accessToken)) if (!string.IsNullOrEmpty(accessToken))
@@ -322,7 +320,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
} }
} }
List<string> additionalFetchSpecs = new List<string>(); List<string> additionalFetchSpecs = new();
additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*"); additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");
if (IsPullRequest(sourceBranch)) if (IsPullRequest(sourceBranch))
@@ -397,7 +395,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}"); throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
} }
List<string> additionalSubmoduleUpdateArgs = new List<string>(); List<string> additionalSubmoduleUpdateArgs = new();
if (!string.IsNullOrEmpty(accessToken)) if (!string.IsNullOrEmpty(accessToken))
{ {

View File

@@ -1,12 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using System.IO; using System.IO;
using GitHub.DistributedTask.Pipelines.ContextData;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using GitHub.DistributedTask.Pipelines.Expressions; using GitHub.DistributedTask.Pipelines.Expressions;
using System.Text; using System.Text;
@@ -15,7 +12,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
{ {
public class CheckoutTask : IRunnerActionPlugin public class CheckoutTask : IRunnerActionPlugin
{ {
private readonly Regex _validSha1 = new Regex(@"\b[0-9a-f]{40}\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled, TimeSpan.FromSeconds(2)); private readonly Regex _validSha1 = new(@"\b[0-9a-f]{40}\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled, TimeSpan.FromSeconds(2));
public async Task RunAsync(RunnerActionPluginExecutionContext executionContext, CancellationToken token) public async Task RunAsync(RunnerActionPluginExecutionContext executionContext, CancellationToken token)
{ {

View File

@@ -4,9 +4,7 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Text.RegularExpressions;
using System.Text; using System.Text;
using System.Diagnostics;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using System.Linq; using System.Linq;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
@@ -24,7 +22,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
private const string _tagRefsPrefix = "refs/tags/"; private const string _tagRefsPrefix = "refs/tags/";
// min git version that support add extra auth header. // min git version that support add extra auth header.
private Version _minGitVersionSupportAuthHeader = new Version(2, 9); private Version _minGitVersionSupportAuthHeader = new(2, 9);
#if OS_WINDOWS #if OS_WINDOWS
// min git version that support override sslBackend setting. // min git version that support override sslBackend setting.
@@ -32,7 +30,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
#endif #endif
// min git-lfs version that support add extra auth header. // min git-lfs version that support add extra auth header.
private Version _minGitLfsVersionSupportAuthHeader = new Version(2, 1); private Version _minGitLfsVersionSupportAuthHeader = new(2, 1);
public static string ProblemMatcher => @" public static string ProblemMatcher => @"
{ {
@@ -64,9 +62,9 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
{ {
// Validate args. // Validate args.
ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNull(executionContext, nameof(executionContext));
Dictionary<string, string> configModifications = new Dictionary<string, string>(); Dictionary<string, string> configModifications = new();
executionContext.Output($"Syncing repository: {repoFullName}"); executionContext.Output($"Syncing repository: {repoFullName}");
Uri repositoryUrl = new Uri($"https://github.com/{repoFullName}"); Uri repositoryUrl = new($"https://github.com/{repoFullName}");
if (!repositoryUrl.IsAbsoluteUri) if (!repositoryUrl.IsAbsoluteUri)
{ {
throw new InvalidOperationException("Repository url need to be an absolute uri."); throw new InvalidOperationException("Repository url need to be an absolute uri.");
@@ -104,7 +102,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
executionContext.Debug($"gitLfsSupport={gitLfsSupport}"); executionContext.Debug($"gitLfsSupport={gitLfsSupport}");
// Initialize git command manager with additional environment variables. // Initialize git command manager with additional environment variables.
Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); Dictionary<string, string> gitEnv = new(StringComparer.OrdinalIgnoreCase);
// Disable git prompt // Disable git prompt
gitEnv["GIT_TERMINAL_PROMPT"] = "0"; gitEnv["GIT_TERMINAL_PROMPT"] = "0";
@@ -127,7 +125,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty; gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
} }
GitCliManager gitCommandManager = new GitCliManager(gitEnv); GitCliManager gitCommandManager = new(gitEnv);
await gitCommandManager.LoadGitExecutionInfo(executionContext); await gitCommandManager.LoadGitExecutionInfo(executionContext);
// Make sure the build machine met all requirements for the git repository // Make sure the build machine met all requirements for the git repository
@@ -279,8 +277,8 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty); await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
} }
List<string> additionalFetchArgs = new List<string>(); List<string> additionalFetchArgs = new();
List<string> additionalLfsFetchArgs = new List<string>(); List<string> additionalLfsFetchArgs = new();
// Add http.https://github.com.extraheader=... to gitconfig // Add http.https://github.com.extraheader=... to gitconfig
// accessToken as basic auth header to handle any auth challenge from github.com // accessToken as basic auth header to handle any auth challenge from github.com
@@ -305,7 +303,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
} }
} }
List<string> additionalFetchSpecs = new List<string>(); List<string> additionalFetchSpecs = new();
additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*"); additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");
if (IsPullRequest(sourceBranch)) if (IsPullRequest(sourceBranch))
@@ -380,7 +378,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}"); throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
} }
List<string> additionalSubmoduleUpdateArgs = new List<string>(); List<string> additionalSubmoduleUpdateArgs = new();
int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken); int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken);
if (exitCode_submoduleUpdate != 0) if (exitCode_submoduleUpdate != 0)
@@ -406,7 +404,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
executionContext.Output($"Cleanup cached git credential from {repositoryPath}."); executionContext.Output($"Cleanup cached git credential from {repositoryPath}.");
// Initialize git command manager // Initialize git command manager
GitCliManager gitCommandManager = new GitCliManager(); GitCliManager gitCommandManager = new();
await gitCommandManager.LoadGitExecutionInfo(executionContext); await gitCommandManager.LoadGitExecutionInfo(executionContext);
executionContext.Debug("Remove any extraheader setting from git config."); executionContext.Debug("Remove any extraheader setting from git config.");
@@ -501,7 +499,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
string gitConfig = Path.Combine(targetPath, ".git/config"); string gitConfig = Path.Combine(targetPath, ".git/config");
if (File.Exists(gitConfig)) if (File.Exists(gitConfig))
{ {
List<string> safeGitConfig = new List<string>(); List<string> safeGitConfig = new();
var gitConfigContents = File.ReadAllLines(gitConfig); var gitConfigContents = File.ReadAllLines(gitConfig);
foreach (var line in gitConfigContents) foreach (var line in gitConfigContents)
{ {

View File

@@ -1,13 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GitHub.Runner.Sdk; using GitHub.Runner.Sdk;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
using System.IO; using System.IO;
using GitHub.DistributedTask.Pipelines.ContextData;
using System.Text.RegularExpressions;
using GitHub.DistributedTask.Pipelines.Expressions; using GitHub.DistributedTask.Pipelines.Expressions;
using System.Text; using System.Text;

View File

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

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
@@ -11,7 +10,6 @@ using GitHub.DistributedTask.WebApi;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using Newtonsoft.Json; using Newtonsoft.Json;
using Pipelines = GitHub.DistributedTask.Pipelines;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {
@@ -25,7 +23,7 @@ namespace GitHub.Runner.Sdk
private readonly string DebugEnvironmentalVariable = "ACTIONS_STEP_DEBUG"; private readonly string DebugEnvironmentalVariable = "ACTIONS_STEP_DEBUG";
private VssConnection _connection; private VssConnection _connection;
private RunnerWebProxy _webProxy; private RunnerWebProxy _webProxy;
private readonly object _stdoutLock = new object(); private readonly object _stdoutLock = new();
private readonly ITraceWriter _trace; // for unit tests private readonly ITraceWriter _trace; // for unit tests
public RunnerActionPluginExecutionContext() public RunnerActionPluginExecutionContext()
@@ -222,7 +220,7 @@ namespace GitHub.Runner.Sdk
return input; return input;
} }
private Dictionary<string, string> _commandEscapeMappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) private Dictionary<string, string> _commandEscapeMappings = new(StringComparer.OrdinalIgnoreCase)
{ {
{ {
";", "%3B" ";", "%3B"

View File

@@ -24,18 +24,18 @@ namespace GitHub.Runner.Sdk
private Stopwatch _stopWatch; private Stopwatch _stopWatch;
private int _asyncStreamReaderCount = 0; private int _asyncStreamReaderCount = 0;
private bool _waitingOnStreams = false; private bool _waitingOnStreams = false;
private readonly AsyncManualResetEvent _outputProcessEvent = new AsyncManualResetEvent(); private readonly AsyncManualResetEvent _outputProcessEvent = new();
private readonly TaskCompletionSource<bool> _processExitedCompletionSource = new TaskCompletionSource<bool>(); private readonly TaskCompletionSource<bool> _processExitedCompletionSource = new();
private readonly CancellationTokenSource _processStandardInWriteCancellationTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource _processStandardInWriteCancellationTokenSource = new();
private readonly ConcurrentQueue<string> _errorData = new ConcurrentQueue<string>(); private readonly ConcurrentQueue<string> _errorData = new();
private readonly ConcurrentQueue<string> _outputData = new ConcurrentQueue<string>(); private readonly ConcurrentQueue<string> _outputData = new();
private readonly TimeSpan _sigintTimeout = TimeSpan.FromMilliseconds(7500); private readonly TimeSpan _sigintTimeout = TimeSpan.FromMilliseconds(7500);
private readonly TimeSpan _sigtermTimeout = TimeSpan.FromMilliseconds(2500); private readonly TimeSpan _sigtermTimeout = TimeSpan.FromMilliseconds(2500);
private ITraceWriter Trace { get; set; } private ITraceWriter Trace { get; set; }
private class AsyncManualResetEvent private class AsyncManualResetEvent
{ {
private volatile TaskCompletionSource<bool> m_tcs = new TaskCompletionSource<bool>(); private volatile TaskCompletionSource<bool> m_tcs = new();
public Task WaitAsync() { return m_tcs.Task; } public Task WaitAsync() { return m_tcs.Task; }
@@ -387,8 +387,8 @@ namespace GitHub.Runner.Sdk
private void ProcessOutput() private void ProcessOutput()
{ {
List<string> errorData = new List<string>(); List<string> errorData = new();
List<string> outputData = new List<string>(); List<string> outputData = new();
string errorLine; string errorLine;
while (_errorData.TryDequeue(out errorLine)) while (_errorData.TryDequeue(out errorLine))

View File

@@ -3,12 +3,12 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<NoWarn>NU1701;NU1603</NoWarn> <NoWarn>NU1701;NU1603</NoWarn>
<Version>$(Version)</Version> <Version>$(Version)</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Sdk\Sdk.csproj" /> <ProjectReference Include="..\Sdk\Sdk.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -23,9 +23,9 @@ namespace GitHub.Runner.Sdk
private string _httpsProxyPassword; private string _httpsProxyPassword;
private string _noProxyString; private string _noProxyString;
private readonly List<ByPassInfo> _noProxyList = new List<ByPassInfo>(); private readonly List<ByPassInfo> _noProxyList = new();
private readonly HashSet<string> _noProxyUnique = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _noProxyUnique = new(StringComparer.OrdinalIgnoreCase);
private readonly Regex _validIpRegex = new Regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", RegexOptions.Compiled); private readonly Regex _validIpRegex = new("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", RegexOptions.Compiled);
public string HttpProxyAddress => _httpProxyAddress; public string HttpProxyAddress => _httpProxyAddress;
public string HttpProxyUsername => _httpProxyUsername; public string HttpProxyUsername => _httpProxyUsername;

View File

@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -53,7 +52,7 @@ namespace GitHub.Runner.Sdk
using (SHA256 sha256hash = SHA256.Create()) using (SHA256 sha256hash = SHA256.Create())
{ {
byte[] data = sha256hash.ComputeHash(Encoding.UTF8.GetBytes(hashString)); byte[] data = sha256hash.ComputeHash(Encoding.UTF8.GetBytes(hashString));
StringBuilder sBuilder = new StringBuilder(); StringBuilder sBuilder = new();
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
{ {
sBuilder.Append(data[i].ToString("x2")); sBuilder.Append(data[i].ToString("x2"));
@@ -78,7 +77,7 @@ namespace GitHub.Runner.Sdk
public static void DeleteDirectory(string path, bool contentsOnly, bool continueOnContentDeleteError, CancellationToken cancellationToken) public static void DeleteDirectory(string path, bool contentsOnly, bool continueOnContentDeleteError, CancellationToken cancellationToken)
{ {
ArgUtil.NotNullOrEmpty(path, nameof(path)); ArgUtil.NotNullOrEmpty(path, nameof(path));
DirectoryInfo directory = new DirectoryInfo(path); DirectoryInfo directory = new(path);
if (!directory.Exists) if (!directory.Exists)
{ {
return; return;
@@ -364,12 +363,12 @@ namespace GitHub.Runner.Sdk
Directory.CreateDirectory(target); Directory.CreateDirectory(target);
// Get the file contents of the directory to copy. // Get the file contents of the directory to copy.
DirectoryInfo sourceDir = new DirectoryInfo(source); DirectoryInfo sourceDir = new(source);
foreach (FileInfo sourceFile in sourceDir.GetFiles() ?? new FileInfo[0]) foreach (FileInfo sourceFile in sourceDir.GetFiles() ?? new FileInfo[0])
{ {
// Check if the file already exists. // Check if the file already exists.
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
FileInfo targetFile = new FileInfo(Path.Combine(target, sourceFile.Name)); FileInfo targetFile = new(Path.Combine(target, sourceFile.Name));
if (!targetFile.Exists || if (!targetFile.Exists ||
sourceFile.Length != targetFile.Length || sourceFile.Length != targetFile.Length ||
sourceFile.LastWriteTime != targetFile.LastWriteTime) sourceFile.LastWriteTime != targetFile.LastWriteTime)

View File

@@ -1,4 +1,3 @@
using System;
using System.IO; using System.IO;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk

View File

@@ -1,11 +1,7 @@
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text; using System.Text;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
@@ -13,7 +9,7 @@ namespace GitHub.Runner.Sdk
public static class StringUtil public static class StringUtil
{ {
private static readonly object[] s_defaultFormatArgs = new object[] { null }; private static readonly object[] s_defaultFormatArgs = new object[] { null };
private static Lazy<JsonSerializerSettings> s_serializerSettings = new Lazy<JsonSerializerSettings>(() => private static Lazy<JsonSerializerSettings> s_serializerSettings = new(() =>
{ {
var settings = new VssJsonMediaTypeFormatter().SerializerSettings; var settings = new VssJsonMediaTypeFormatter().SerializerSettings;
settings.DateParseHandling = DateParseHandling.None; settings.DateParseHandling = DateParseHandling.None;

View File

@@ -21,7 +21,7 @@ namespace GitHub.Runner.Sdk
return baseUrl; return baseUrl;
} }
UriBuilder credUri = new UriBuilder(baseUrl); UriBuilder credUri = new(baseUrl);
// ensure we have a username, uribuild will throw if username is empty but password is not. // ensure we have a username, uribuild will throw if username is empty but password is not.
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))

View File

@@ -9,6 +9,7 @@ using GitHub.Services.OAuth;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Net; using System.Net;
using Sdk.WebApi.WebApi.RawClient;
namespace GitHub.Runner.Sdk namespace GitHub.Runner.Sdk
{ {
@@ -34,7 +35,11 @@ namespace GitHub.Runner.Sdk
} }
} }
public static VssConnection CreateConnection(Uri serverUri, VssCredentials credentials, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, TimeSpan? timeout = null) public static VssConnection CreateConnection(
Uri serverUri,
VssCredentials credentials,
IEnumerable<DelegatingHandler> additionalDelegatingHandler = null,
TimeSpan? timeout = null)
{ {
VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone(); VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone();
@@ -57,7 +62,7 @@ namespace GitHub.Runner.Sdk
settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200)); settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200));
} }
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ALLOW_REDIRECT"))) if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("USE_BROKER_FLOW")))
{ {
settings.AllowAutoRedirect = true; settings.AllowAutoRedirect = true;
} }
@@ -71,7 +76,47 @@ namespace GitHub.Runner.Sdk
// settings are applied to an HttpRequestMessage. // settings are applied to an HttpRequestMessage.
settings.AcceptLanguages.Remove(CultureInfo.InvariantCulture); settings.AcceptLanguages.Remove(CultureInfo.InvariantCulture);
VssConnection connection = new VssConnection(serverUri, new VssHttpMessageHandler(credentials, settings), additionalDelegatingHandler); VssConnection connection = new(serverUri, new VssHttpMessageHandler(credentials, settings), additionalDelegatingHandler);
return connection;
}
public static RawConnection CreateRawConnection(
Uri serverUri,
VssCredentials credentials,
IEnumerable<DelegatingHandler> additionalDelegatingHandler = null,
TimeSpan? timeout = null)
{
RawClientHttpRequestSettings settings = RawClientHttpRequestSettings.Default.Clone();
int maxRetryRequest;
if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY") ?? string.Empty, out maxRetryRequest))
{
maxRetryRequest = 3;
}
// make sure MaxRetryRequest in range [3, 10]
settings.MaxRetryRequest = Math.Min(Math.Max(maxRetryRequest, 3), 10);
if (!int.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_TIMEOUT") ?? string.Empty, out int httpRequestTimeoutSeconds))
{
settings.SendTimeout = timeout ?? TimeSpan.FromSeconds(100);
}
else
{
// prefer environment variable
settings.SendTimeout = TimeSpan.FromSeconds(Math.Min(Math.Max(httpRequestTimeoutSeconds, 100), 1200));
}
// Remove Invariant from the list of accepted languages.
//
// The constructor of VssHttpRequestSettings (base class of VssClientHttpRequestSettings) adds the current
// UI culture to the list of accepted languages. The UI culture will be Invariant on OSX/Linux when the
// LANG environment variable is not set when the program starts. If Invariant is in the list of accepted
// languages, then "System.ArgumentException: The value cannot be null or empty." will be thrown when the
// settings are applied to an HttpRequestMessage.
settings.AcceptLanguages.Remove(CultureInfo.InvariantCulture);
RawConnection connection = new(serverUri, new RawHttpMessageHandler(credentials.ToOAuthCredentials(), settings), additionalDelegatingHandler);
return connection; return connection;
} }

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> </startup>
</configuration> </configuration>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

View File

@@ -11,10 +11,15 @@
<AssemblyName>RunnerService</AssemblyName> <AssemblyName>RunnerService</AssemblyName>
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<DelaySign>false</DelaySign> <DelaySign>false</DelaySign>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(PackageRuntime)' == 'win-arm64' ">
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(PackageRuntime)' != 'win-arm64' ">
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -61,7 +66,10 @@
<DependentUpon>Resource.resx</DependentUpon> <DependentUpon>Resource.resx</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup Condition=" '$(Platform)' == 'ARM' ">
<None Include="AppARM.config" />
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' != 'ARM' ">
<None Include="App.config" /> <None Include="App.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -71,7 +79,7 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>

View File

@@ -21,9 +21,9 @@ namespace GitHub.Runner.Worker
public sealed class ActionCommandManager : RunnerService, IActionCommandManager public sealed class ActionCommandManager : RunnerService, IActionCommandManager
{ {
private const string _stopCommand = "stop-commands"; private const string _stopCommand = "stop-commands";
private readonly Dictionary<string, IActionCommandExtension> _commandExtensions = new Dictionary<string, IActionCommandExtension>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, IActionCommandExtension> _commandExtensions = new(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> _registeredCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _registeredCommands = new(StringComparer.OrdinalIgnoreCase);
private readonly object _commandSerializeLock = new object(); private readonly object _commandSerializeLock = new();
private bool _stopProcessCommand = false; private bool _stopProcessCommand = false;
private string _stopToken = null; private string _stopToken = null;
@@ -307,6 +307,17 @@ namespace GitHub.Runner.Worker
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
{ {
if (context.Global.Variables.GetBoolean("DistributedTask.DeprecateStepOutputCommands") ?? false)
{
var issue = new Issue()
{
Type = IssueType.Warning,
Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command)
};
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand;
context.AddIssue(issue);
}
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName)) if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
{ {
throw new Exception("Required field 'name' is missing in ##[set-output] command."); throw new Exception("Required field 'name' is missing in ##[set-output] command.");
@@ -331,6 +342,17 @@ namespace GitHub.Runner.Worker
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container)
{ {
if (context.Global.Variables.GetBoolean("DistributedTask.DeprecateStepOutputCommands") ?? false)
{
var issue = new Issue()
{
Type = IssueType.Warning,
Message = String.Format(Constants.Runner.UnsupportedCommandMessage, this.Command)
};
issue.Data[Constants.Runner.InternalTelemetryIssueDataKey] = Constants.Runner.UnsupportedCommand;
context.AddIssue(issue);
}
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName)) if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
{ {
throw new Exception("Required field 'name' is missing in ##[save-state] command."); throw new Exception("Required field 'name' is missing in ##[save-state] command.");
@@ -585,6 +607,8 @@ namespace GitHub.Runner.Worker
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container)
{ {
ValidateLinesAndColumns(command, context);
command.Properties.TryGetValue(IssueCommandProperties.File, out string file); command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
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);
@@ -594,7 +618,7 @@ namespace GitHub.Runner.Worker
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()
{ {
Category = "General", Category = "General",
Type = this.Type, Type = this.Type,

Some files were not shown because too many files have changed in this diff Show More