mirror of
https://github.com/actions/runner.git
synced 2025-12-20 06:29:53 +00:00
Compare commits
10 Commits
luketomlin
...
johnsudol/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cbaea9cb8 | ||
|
|
1acad3fee2 | ||
|
|
995ef97863 | ||
|
|
0fabfa67ca | ||
|
|
c40f389f13 | ||
|
|
ec0e6c72eb | ||
|
|
6cdd031970 | ||
|
|
7b0a262a43 | ||
|
|
689a94d915 | ||
|
|
8e35cbcc36 |
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@@ -131,7 +131,7 @@ jobs:
|
|||||||
file=$(ls)
|
file=$(ls)
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
echo "Computed sha256: $sha for $file"
|
echo "Computed sha256: $sha for $file"
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
shell: bash
|
shell: bash
|
||||||
id: sha
|
id: sha
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
@@ -140,8 +140,8 @@ jobs:
|
|||||||
file=$(ls)
|
file=$(ls)
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
echo "Computed sha256: $sha for $file"
|
echo "Computed sha256: $sha for $file"
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
echo "sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=sha256::$sha"
|
||||||
shell: bash
|
shell: bash
|
||||||
id: sha_noexternals
|
id: sha_noexternals
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
@@ -150,8 +150,8 @@ jobs:
|
|||||||
file=$(ls)
|
file=$(ls)
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
echo "Computed sha256: $sha for $file"
|
echo "Computed sha256: $sha for $file"
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
echo "sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=sha256::$sha"
|
||||||
shell: bash
|
shell: bash
|
||||||
id: sha_noruntime
|
id: sha_noruntime
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
@@ -160,8 +160,8 @@ jobs:
|
|||||||
file=$(ls)
|
file=$(ls)
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
sha=$(sha256sum $file | awk '{ print $1 }')
|
||||||
echo "Computed sha256: $sha for $file"
|
echo "Computed sha256: $sha for $file"
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=${{matrix.runtime}}-sha256::$sha"
|
||||||
echo "sha256=$sha" >> $GITHUB_OUTPUT
|
echo "::set-output name=sha256::$sha"
|
||||||
shell: bash
|
shell: bash
|
||||||
id: sha_noruntime_noexternals
|
id: sha_noruntime_noexternals
|
||||||
name: Compute SHA256
|
name: Compute SHA256
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
|
|||||||
|
|
||||||
ARG RUNNER_VERSION
|
ARG RUNNER_VERSION
|
||||||
ARG RUNNER_ARCH="x64"
|
ARG RUNNER_ARCH="x64"
|
||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.3.1
|
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
||||||
ARG DOCKER_VERSION=20.10.23
|
ARG DOCKER_VERSION=20.10.23
|
||||||
|
|
||||||
RUN apt update -y && apt install curl unzip -y
|
RUN apt update -y && apt install curl unzip -y
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
## Features
|
## Features
|
||||||
- Support matrix context in output keys (#2477)
|
- Add support for ghe.com domain (#2420)
|
||||||
- Add update certificates to `./run.sh` if `RUNNER_UPDATE_CA_CERTS` env is set (#2471)
|
- Add docker cli to the runner image. (#2425)
|
||||||
- Bypass all proxies for all hosts if `no_proxy='*'` is set (#2395)
|
|
||||||
- Change runner image to make user/folder align with `ubuntu-latest` hosted runner. (#2469)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Exit on runner version deprecation error (#2299)
|
- Fix URL construction bug for RunService (#2396)
|
||||||
- Runner service exit after consecutive re-try exits (#2426)
|
- Defer evaluation of a step's DisplayName until its condition is evaluated. (#2313)
|
||||||
|
- Replace '(' and ')' with '[' and '] from OS.Description for fixing User-Agent header validation (#2288)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- Replace deprecated command with environment file (#2429)
|
- Bump dotnet sdk to latest version. (#2392)
|
||||||
- Make requests to `Run` service to renew job request (#2461)
|
- Start calling run service for job completion (#2412, #2423)
|
||||||
- Add job/step log upload to Result service (#2447, #2439)
|
|
||||||
|
|
||||||
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
||||||
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
||||||
|
|||||||
3
src/Misc/expressionFunc/hashFilesV2/.eslintignore
Normal file
3
src/Misc/expressionFunc/hashFilesV2/.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
||||||
61
src/Misc/expressionFunc/hashFilesV2/.eslintrc.json
Normal file
61
src/Misc/expressionFunc/hashFilesV2/.eslintrc.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"extends": ["plugin:github/recommended"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 9,
|
||||||
|
"sourceType": "module",
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"eslint-comments/no-use": "off",
|
||||||
|
"import/no-namespace": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||||
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
|
"@typescript-eslint/array-type": "error",
|
||||||
|
"@typescript-eslint/await-thenable": "error",
|
||||||
|
"@typescript-eslint/naming-convention": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"selector": "default",
|
||||||
|
"format": ["camelCase"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"camelcase": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||||
|
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||||
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
|
"@typescript-eslint/no-for-in-array": "error",
|
||||||
|
"@typescript-eslint/no-inferrable-types": "error",
|
||||||
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
|
"@typescript-eslint/no-namespace": "error",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
|
"@typescript-eslint/no-var-requires": "error",
|
||||||
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
|
"@typescript-eslint/promise-function-async": "error",
|
||||||
|
"@typescript-eslint/require-array-sort-compare": "error",
|
||||||
|
"@typescript-eslint/restrict-plus-operands": "error",
|
||||||
|
"@typescript-eslint/semi": ["error", "never"],
|
||||||
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
|
"@typescript-eslint/unbound-method": "error",
|
||||||
|
"filenames/match-regex" : "off",
|
||||||
|
"github/no-then" : 1, // warning
|
||||||
|
"semi": "off"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/Misc/expressionFunc/hashFilesV2/.prettierignore
Normal file
3
src/Misc/expressionFunc/hashFilesV2/.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
||||||
11
src/Misc/expressionFunc/hashFilesV2/.prettierrc.json
Normal file
11
src/Misc/expressionFunc/hashFilesV2/.prettierrc.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 80,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"parser": "typescript"
|
||||||
|
}
|
||||||
4
src/Misc/expressionFunc/hashFilesV2/README.md
Normal file
4
src/Misc/expressionFunc/hashFilesV2/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
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.
|
||||||
5525
src/Misc/expressionFunc/hashFilesV2/package-lock.json
generated
Normal file
5525
src/Misc/expressionFunc/hashFilesV2/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
36
src/Misc/expressionFunc/hashFilesV2/package.json
Normal file
36
src/Misc/expressionFunc/hashFilesV2/package.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "hashFiles",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "GitHub Actions HashFiles() expression function",
|
||||||
|
"main": "lib/hashFiles.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"format": "prettier --write **/*.ts",
|
||||||
|
"format-check": "prettier --check **/*.ts",
|
||||||
|
"lint": "eslint src/**/*.ts",
|
||||||
|
"pack": "ncc build -o ../../layoutbin/hashFilesV2",
|
||||||
|
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/actions/runner.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"actions"
|
||||||
|
],
|
||||||
|
"author": "GitHub Actions",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/glob": "^0.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^12.7.12",
|
||||||
|
"@typescript-eslint/parser": "^5.15.0",
|
||||||
|
"@vercel/ncc": "^0.36.0",
|
||||||
|
"eslint": "^8.11.0",
|
||||||
|
"eslint-plugin-github": "^4.3.5",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"prettier": "^2.8.4",
|
||||||
|
"typescript": "^3.6.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/Misc/expressionFunc/hashFilesV2/src/hashFiles.ts
Normal file
31
src/Misc/expressionFunc/hashFilesV2/src/hashFiles.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import * as glob from '@actions/glob'
|
||||||
|
|
||||||
|
async function run(): Promise<void> {
|
||||||
|
// arg0 -> node
|
||||||
|
// arg1 -> hashFiles.js
|
||||||
|
// env[followSymbolicLinks] = true/null
|
||||||
|
// env[patterns] -> glob patterns
|
||||||
|
let followSymbolicLinks = false
|
||||||
|
const matchPatterns = process.env.patterns || ''
|
||||||
|
if (process.env.followSymbolicLinks === 'true') {
|
||||||
|
console.log('Follow symbolic links')
|
||||||
|
followSymbolicLinks = true
|
||||||
|
}
|
||||||
|
const githubWorkspace = process.cwd()
|
||||||
|
console.log(`Match Pattern: ${matchPatterns}`)
|
||||||
|
try {
|
||||||
|
const result = await glob.hashFiles(
|
||||||
|
matchPatterns,
|
||||||
|
githubWorkspace,
|
||||||
|
{followSymbolicLinks},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
console.error(`__OUTPUT__${result}__OUTPUT__`)
|
||||||
|
process.exit(0)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
12
src/Misc/expressionFunc/hashFilesV2/tsconfig.json
Normal file
12
src/Misc/expressionFunc/hashFilesV2/tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||||
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
|
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||||
|
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
|
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "**/*.test.ts"]
|
||||||
|
}
|
||||||
5342
src/Misc/layoutbin/hashFilesV2/index.js
Normal file
5342
src/Misc/layoutbin/hashFilesV2/index.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -53,33 +53,6 @@ runWithManualTrap() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCerts() {
|
|
||||||
local sudo_prefix=""
|
|
||||||
local user_id=`id -u`
|
|
||||||
|
|
||||||
if [ $user_id -ne 0 ]; then
|
|
||||||
if [[ ! -x "$(command -v sudo)" ]]; then
|
|
||||||
echo "Warning: failed to update certificate store: sudo is required but not found"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
sudo_prefix="sudo"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x "$(command -v update-ca-certificates)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-certificates"
|
|
||||||
elif [[ -x "$(command -v update-ca-trust)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-trust"
|
|
||||||
else
|
|
||||||
echo "Warning: failed to update certificate store: update-ca-certificates or update-ca-trust not found. This can happen if you're using a different runner base image."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ ! -z "$RUNNER_UPDATE_CA_CERTS" ]]; then
|
|
||||||
updateCerts
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$RUNNER_MANUALLY_TRAP_SIG" ]]; then
|
if [[ -z "$RUNNER_MANUALLY_TRAP_SIG" ]]; then
|
||||||
run $*
|
run $*
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ checkScripts/downloadCert.js
|
|||||||
checkScripts/makeWebRequest.js
|
checkScripts/makeWebRequest.js
|
||||||
darwin.svc.sh.template
|
darwin.svc.sh.template
|
||||||
hashFiles/index.js
|
hashFiles/index.js
|
||||||
|
hashFilesV2/index.js
|
||||||
installdependencies.sh
|
installdependencies.sh
|
||||||
macos-run-invoker.js
|
macos-run-invoker.js
|
||||||
Microsoft.IdentityModel.Logging.dll
|
Microsoft.IdentityModel.Logging.dll
|
||||||
|
|||||||
@@ -50,9 +50,6 @@ namespace GitHub.Runner.Common
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string MonitorSocketAddress { get; set; }
|
public string MonitorSocketAddress { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool UseV2Flow { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsHostedServer
|
public bool IsHostedServer
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -156,6 +156,7 @@ namespace GitHub.Runner.Common
|
|||||||
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 UseGlobHashFiles = "DistributedTask.UseGlobHashFiles";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
||||||
|
|||||||
@@ -1,245 +0,0 @@
|
|||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(RunnerDotcomServer))]
|
|
||||||
public interface IRunnerDotcomServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, string githubUrl, string githubToken, string agentName);
|
|
||||||
|
|
||||||
Task<TaskAgent> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey, string hostId);
|
|
||||||
Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken);
|
|
||||||
|
|
||||||
string GetGitHubRequestId(HttpResponseHeaders headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum RequestType
|
|
||||||
{
|
|
||||||
Get,
|
|
||||||
Post,
|
|
||||||
Patch,
|
|
||||||
Delete
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RunnerDotcomServer : RunnerService, IRunnerDotcomServer
|
|
||||||
{
|
|
||||||
private ITerminal _term;
|
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
|
||||||
{
|
|
||||||
base.Initialize(hostContext);
|
|
||||||
_term = hostContext.GetService<ITerminal>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<List<TaskAgent>> GetRunnersAsync(int runnerGroupId, string githubUrl, string githubToken, string agentName = null)
|
|
||||||
{
|
|
||||||
var githubApiUrl = "";
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (path.Length == 1)
|
|
||||||
{
|
|
||||||
// org runner
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runner-groups/{runnerGroupId}/runners";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.Length == 2)
|
|
||||||
{
|
|
||||||
// repo or enterprise runner.
|
|
||||||
if (!string.Equals(path[0], "enterprises", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runner-groups/{runnerGroupId}/runners";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"'{githubUrl}' should point to an org or enterprise.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var runnersList = await RetryRequest<ListRunnersResponse>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
|
||||||
var agents = runnersList.ToTaskAgents();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(agentName))
|
|
||||||
{
|
|
||||||
return agents;
|
|
||||||
}
|
|
||||||
|
|
||||||
return agents.Where(x => string.Equals(x.Name, agentName, StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<TaskAgentPool>> GetRunnerGroupsAsync(string githubUrl, string githubToken)
|
|
||||||
{
|
|
||||||
var githubApiUrl = "";
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (path.Length == 1)
|
|
||||||
{
|
|
||||||
// org runner
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/orgs/{path[0]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/orgs/{path[0]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.Length == 2)
|
|
||||||
{
|
|
||||||
// repo or enterprise runner.
|
|
||||||
if (!string.Equals(path[0], "enterprises", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/{path[0]}/{path[1]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/{path[0]}/{path[1]}/actions/runner-groups";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"'{githubUrl}' should point to an org or enterprise.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var agentPools = await RetryRequest<RunnerGroupList>(githubApiUrl, githubToken, RequestType.Get, 3, "Failed to get agents pools");
|
|
||||||
|
|
||||||
return agentPools?.ToAgentPoolList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<TaskAgent> AddRunnerAsync(int runnerGroupId, TaskAgent agent, string githubUrl, string githubToken, string publicKey, string hostId)
|
|
||||||
{
|
|
||||||
var gitHubUrlBuilder = new UriBuilder(githubUrl);
|
|
||||||
var path = gitHubUrlBuilder.Path.Split('/', '\\', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
string githubApiUrl;
|
|
||||||
if (UrlUtil.IsHostedServer(gitHubUrlBuilder))
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/actions/runners/register";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
githubApiUrl = $"{gitHubUrlBuilder.Scheme}://{gitHubUrlBuilder.Host}/api/v3/actions/runners/register";
|
|
||||||
}
|
|
||||||
|
|
||||||
var bodyObject = new Dictionary<string, Object>()
|
|
||||||
{
|
|
||||||
{"url", githubUrl},
|
|
||||||
{"group_id", runnerGroupId},
|
|
||||||
{"name", agent.Name},
|
|
||||||
{"version", agent.Version},
|
|
||||||
{"updates_disabled", agent.DisableUpdate},
|
|
||||||
{"ephemeral", agent.Ephemeral},
|
|
||||||
{"labels", agent.Labels},
|
|
||||||
{"public_key", publicKey},
|
|
||||||
{"host_id", hostId},
|
|
||||||
};
|
|
||||||
|
|
||||||
var body = new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json");
|
|
||||||
|
|
||||||
var runner = await RetryRequest<DistributedTask.WebApi.Runner>(githubApiUrl, githubToken, RequestType.Post, 3, "Failed to add agent", body);
|
|
||||||
agent.Id = runner.Id;
|
|
||||||
agent.Authorization = new TaskAgentAuthorization()
|
|
||||||
{
|
|
||||||
AuthorizationUrl = runner.RunnerAuthorization.AuthorizationUrl,
|
|
||||||
ClientId = new Guid(runner.RunnerAuthorization.ClientId),
|
|
||||||
};
|
|
||||||
return agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<T> RetryRequest<T>(string githubApiUrl, string githubToken, RequestType requestType, int maxRetryAttemptsCount = 5, string errorMessage = null, StringContent body = null)
|
|
||||||
{
|
|
||||||
int retry = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
retry++;
|
|
||||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
|
||||||
using (var httpClient = new HttpClient(httpClientHandler))
|
|
||||||
{
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
|
|
||||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
|
||||||
|
|
||||||
var responseStatus = System.Net.HttpStatusCode.OK;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = null;
|
|
||||||
if (requestType == RequestType.Get)
|
|
||||||
{
|
|
||||||
response = await httpClient.GetAsync(githubApiUrl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response = await httpClient.PostAsync(githubApiUrl, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
responseStatus = response.StatusCode;
|
|
||||||
var githubRequestId = GetGitHubRequestId(response.Headers);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Trace.Info($"Http response code: {response.StatusCode} from '{requestType.ToString()} {githubApiUrl}' ({githubRequestId})");
|
|
||||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
|
||||||
return StringUtil.ConvertFromJson<T>(jsonResponse);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_term.WriteError($"Http response code: {response.StatusCode} from '{requestType.ToString()} {githubApiUrl}' (Request Id: {githubRequestId})");
|
|
||||||
var errorResponse = await response.Content.ReadAsStringAsync();
|
|
||||||
_term.WriteError(errorResponse);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (retry < maxRetryAttemptsCount && responseStatus != System.Net.HttpStatusCode.NotFound)
|
|
||||||
{
|
|
||||||
Trace.Error($"{errorMessage} -- Atempt: {retry}");
|
|
||||||
Trace.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
|
|
||||||
Trace.Info($"Retrying in {backOff.Seconds} seconds");
|
|
||||||
await Task.Delay(backOff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetGitHubRequestId(HttpResponseHeaders headers)
|
|
||||||
{
|
|
||||||
if (headers.TryGetValues("x-github-request-id", out var headerValues))
|
|
||||||
{
|
|
||||||
return headerValues.FirstOrDefault();
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@ using GitHub.Runner.Sdk;
|
|||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using GitHub.Services.Common.Internal;
|
using GitHub.Services.Common.Internal;
|
||||||
using GitHub.Services.OAuth;
|
using GitHub.Services.OAuth;
|
||||||
using GitHub.Services.WebApi.Jwt;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Listener.Configuration
|
namespace GitHub.Runner.Listener.Configuration
|
||||||
{
|
{
|
||||||
@@ -32,14 +31,12 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
private IConfigurationStore _store;
|
private IConfigurationStore _store;
|
||||||
private IRunnerServer _runnerServer;
|
private IRunnerServer _runnerServer;
|
||||||
private IRunnerDotcomServer _dotcomServer;
|
|
||||||
private ITerminal _term;
|
private ITerminal _term;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
_runnerServer = HostContext.GetService<IRunnerServer>();
|
_runnerServer = HostContext.GetService<IRunnerServer>();
|
||||||
_dotcomServer = HostContext.GetService<IRunnerDotcomServer>();
|
|
||||||
Trace.Verbose("Creating _store");
|
Trace.Verbose("Creating _store");
|
||||||
_store = hostContext.GetService<IConfigurationStore>();
|
_store = hostContext.GetService<IConfigurationStore>();
|
||||||
Trace.Verbose("store created");
|
Trace.Verbose("store created");
|
||||||
@@ -116,8 +113,6 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
ICredentialProvider credProvider = null;
|
ICredentialProvider credProvider = null;
|
||||||
VssCredentials creds = null;
|
VssCredentials creds = null;
|
||||||
_term.WriteSection("Authentication");
|
_term.WriteSection("Authentication");
|
||||||
string registerToken = string.Empty;
|
|
||||||
string hostId = string.Empty;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// When testing against a dev deployment of Actions Service, set this environment variable
|
// When testing against a dev deployment of Actions Service, set this environment variable
|
||||||
@@ -135,14 +130,11 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
runnerSettings.GitHubUrl = inputUrl;
|
runnerSettings.GitHubUrl = inputUrl;
|
||||||
registerToken = await GetRunnerTokenAsync(command, inputUrl, "registration");
|
var registerToken = await GetRunnerTokenAsync(command, inputUrl, "registration");
|
||||||
GitHubAuthResult authResult = await GetTenantCredential(inputUrl, registerToken, Constants.RunnerEvent.Register);
|
GitHubAuthResult authResult = await GetTenantCredential(inputUrl, registerToken, Constants.RunnerEvent.Register);
|
||||||
runnerSettings.ServerUrl = authResult.TenantUrl;
|
runnerSettings.ServerUrl = authResult.TenantUrl;
|
||||||
runnerSettings.UseV2Flow = authResult.UseV2Flow;
|
|
||||||
_term.WriteLine($"Using V2 flow: {runnerSettings.UseV2Flow}");
|
|
||||||
creds = authResult.ToVssCredentials();
|
creds = authResult.ToVssCredentials();
|
||||||
Trace.Info("cred retrieved via GitHub auth");
|
Trace.Info("cred retrieved via GitHub auth");
|
||||||
hostId = GetHostId(authResult.Token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -184,11 +176,9 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// We want to use the native CSP of the platform for storage, so we use the RSACSP directly
|
// We want to use the native CSP of the platform for storage, so we use the RSACSP directly
|
||||||
RSAParameters publicKey;
|
RSAParameters publicKey;
|
||||||
var keyManager = HostContext.GetService<IRSAKeyManager>();
|
var keyManager = HostContext.GetService<IRSAKeyManager>();
|
||||||
string publicKeyXML;
|
|
||||||
using (var rsa = keyManager.CreateKey())
|
using (var rsa = keyManager.CreateKey())
|
||||||
{
|
{
|
||||||
publicKey = rsa.ExportParameters(false);
|
publicKey = rsa.ExportParameters(false);
|
||||||
publicKeyXML = rsa.ToXmlString(includePrivateParameters: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_term.WriteSection("Runner Registration");
|
_term.WriteSection("Runner Registration");
|
||||||
@@ -196,17 +186,9 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// If we have more than one runner group available, allow the user to specify which one to be added into
|
// If we have more than one runner group available, allow the user to specify which one to be added into
|
||||||
string poolName = null;
|
string poolName = null;
|
||||||
TaskAgentPool agentPool = null;
|
TaskAgentPool agentPool = null;
|
||||||
List<TaskAgentPool> agentPools;
|
List<TaskAgentPool> agentPools = await _runnerServer.GetAgentPoolsAsync();
|
||||||
if (runnerSettings.UseV2Flow)
|
|
||||||
{
|
|
||||||
agentPools = await _dotcomServer.GetRunnerGroupsAsync(runnerSettings.GitHubUrl, registerToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
agentPools = await _runnerServer.GetAgentPoolsAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskAgentPool defaultPool = agentPools?.Where(x => x.IsInternal).FirstOrDefault();
|
TaskAgentPool defaultPool = agentPools?.Where(x => x.IsInternal).FirstOrDefault();
|
||||||
|
|
||||||
if (agentPools?.Where(x => !x.IsHosted).Count() > 0)
|
if (agentPools?.Where(x => !x.IsHosted).Count() > 0)
|
||||||
{
|
{
|
||||||
poolName = command.GetRunnerGroupName(defaultPool?.Name);
|
poolName = command.GetRunnerGroupName(defaultPool?.Name);
|
||||||
@@ -244,16 +226,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
|
|
||||||
var userLabels = command.GetLabels();
|
var userLabels = command.GetLabels();
|
||||||
_term.WriteLine();
|
_term.WriteLine();
|
||||||
List<TaskAgent> agents;
|
|
||||||
if (runnerSettings.UseV2Flow)
|
|
||||||
{
|
|
||||||
agents = await _dotcomServer.GetRunnersAsync(runnerSettings.PoolId, runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
agents = await _runnerServer.GetAgentsAsync(runnerSettings.PoolId, runnerSettings.AgentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var agents = await _runnerServer.GetAgentsAsync(runnerSettings.PoolId, runnerSettings.AgentName);
|
||||||
Trace.Verbose("Returns {0} agents", agents.Count);
|
Trace.Verbose("Returns {0} agents", agents.Count);
|
||||||
agent = agents.FirstOrDefault();
|
agent = agents.FirstOrDefault();
|
||||||
if (agent != null)
|
if (agent != null)
|
||||||
@@ -299,16 +273,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
|
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
|
||||||
if (runnerSettings.UseV2Flow)
|
|
||||||
{
|
|
||||||
agent = await _dotcomServer.AddRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML, hostId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
agent = await _runnerServer.AddAgentAsync(runnerSettings.PoolId, agent);
|
agent = await _runnerServer.AddAgentAsync(runnerSettings.PoolId, agent);
|
||||||
}
|
|
||||||
|
|
||||||
if (command.DisableUpdate &&
|
if (command.DisableUpdate &&
|
||||||
command.DisableUpdate != agent.DisableUpdate)
|
command.DisableUpdate != agent.DisableUpdate)
|
||||||
{
|
{
|
||||||
@@ -686,7 +652,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(string.Empty));
|
||||||
responseStatus = response.StatusCode;
|
responseStatus = response.StatusCode;
|
||||||
var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
|
var githubRequestId = GetGitHubRequestId(response.Headers);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -749,7 +715,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
|
||||||
responseStatus = response.StatusCode;
|
responseStatus = response.StatusCode;
|
||||||
var githubRequestId = _dotcomServer.GetGitHubRequestId(response.Headers);
|
var githubRequestId = GetGitHubRequestId(response.Headers);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -779,11 +745,13 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary hack for sending legacy host id using v2 flow
|
private string GetGitHubRequestId(HttpResponseHeaders headers)
|
||||||
private string GetHostId(string accessToken)
|
|
||||||
{
|
{
|
||||||
var claims = JsonWebToken.Create(accessToken).ExtractClaims();
|
if (headers.TryGetValues("x-github-request-id", out var headerValues))
|
||||||
return claims.FirstOrDefault(x => x.Type == "aud").Value.Split(':').LastOrDefault();
|
{
|
||||||
|
return headerValues.FirstOrDefault();
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
@@ -93,9 +93,6 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
[DataMember(Name = "token")]
|
[DataMember(Name = "token")]
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
|
|
||||||
[DataMember(Name = "use_v2_flow")]
|
|
||||||
public bool UseV2Flow { get; set; }
|
|
||||||
|
|
||||||
public VssCredentials ToVssCredentials()
|
public VssCredentials ToVssCredentials()
|
||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(TokenSchema, nameof(TokenSchema));
|
ArgUtil.NotNullOrEmpty(TokenSchema, nameof(TokenSchema));
|
||||||
|
|||||||
@@ -245,10 +245,6 @@ namespace GitHub.Runner.Listener
|
|||||||
_accessTokenRevoked = true;
|
_accessTokenRevoked = true;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Trace.Error("Catch exception during get next message.");
|
Trace.Error("Catch exception during get next message.");
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Listener
|
namespace GitHub.Runner.Listener
|
||||||
{
|
{
|
||||||
@@ -138,12 +137,6 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException e) when (e.InnerException is InvalidTaskAgentVersionException)
|
|
||||||
{
|
|
||||||
terminal.WriteError($"An error occured: {e.Message}");
|
|
||||||
trace.Error(e);
|
|
||||||
return Constants.Runner.ReturnCode.TerminatedError;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
terminal.WriteError($"An error occurred: {e.Message}");
|
terminal.WriteError($"An error occurred: {e.Message}");
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ namespace GitHub.Runner.Worker
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
|
inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions, ExecutionContext.ToExpressionState());
|
||||||
}
|
}
|
||||||
|
|
||||||
var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -355,7 +355,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
DictionaryContextData expressionValues = ExecutionContext.GetExpressionValues(stepHost);
|
DictionaryContextData expressionValues = ExecutionContext.GetExpressionValues(stepHost);
|
||||||
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, expressionValues, ExecutionContext.ExpressionFunctions);
|
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, expressionValues, ExecutionContext.ExpressionFunctions, ExecutionContext.ToExpressionState());
|
||||||
|
|
||||||
return inputs;
|
return inputs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ namespace GitHub.Runner.Worker.Expressions
|
|||||||
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out var workspace);
|
githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out var workspace);
|
||||||
var workspaceData = workspace as StringContextData;
|
var workspaceData = workspace as StringContextData;
|
||||||
ArgUtil.NotNull(workspaceData, nameof(workspaceData));
|
ArgUtil.NotNull(workspaceData, nameof(workspaceData));
|
||||||
|
var executionContext = templateContext.State[nameof(IExecutionContext)] as IExecutionContext;
|
||||||
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
|
|
||||||
string githubWorkspace = workspaceData.Value;
|
string githubWorkspace = workspaceData.Value;
|
||||||
bool followSymlink = false;
|
bool followSymlink = false;
|
||||||
@@ -64,7 +66,15 @@ namespace GitHub.Runner.Worker.Expressions
|
|||||||
string runnerRoot = new DirectoryInfo(binDir).Parent.FullName;
|
string runnerRoot = new DirectoryInfo(binDir).Parent.FullName;
|
||||||
|
|
||||||
string node = Path.Combine(runnerRoot, "externals", NodeUtil.GetInternalNodeVersion(), "bin", $"node{IOUtil.ExeExtension}");
|
string node = Path.Combine(runnerRoot, "externals", NodeUtil.GetInternalNodeVersion(), "bin", $"node{IOUtil.ExeExtension}");
|
||||||
string hashFilesScript = Path.Combine(binDir, "hashFiles");
|
//Feature flag to fetch a new version of hashFiles script
|
||||||
|
string hashFilesScript = string.Empty;
|
||||||
|
var isGlobHashFilesEnabled = executionContext.Global.Variables.GetBoolean("DistributedTask.UseGlobHashFiles") ?? false;
|
||||||
|
if (isGlobHashFilesEnabled)
|
||||||
|
{
|
||||||
|
hashFilesScript = Path.Combine(binDir, "hashFilesV2");
|
||||||
|
}
|
||||||
|
hashFilesScript = Path.Combine(binDir, "hashFiles");
|
||||||
|
|
||||||
var hashResult = string.Empty;
|
var hashResult = string.Empty;
|
||||||
var p = new ProcessInvoker(new HashFilesTrace(context.Trace));
|
var p = new ProcessInvoker(new HashFilesTrace(context.Trace));
|
||||||
p.ErrorDataReceived += ((_, data) =>
|
p.ErrorDataReceived += ((_, data) =>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -164,13 +164,14 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
public Dictionary<String, String> EvaluateStepInputs(
|
public Dictionary<String, String> EvaluateStepInputs(
|
||||||
TemplateToken token,
|
TemplateToken token,
|
||||||
DictionaryContextData contextData,
|
DictionaryContextData contextData,
|
||||||
IList<IFunctionInfo> expressionFunctions)
|
IList<IFunctionInfo> expressionFunctions,
|
||||||
|
IEnumerable<KeyValuePair<String, Object>> expressionState = null)
|
||||||
{
|
{
|
||||||
var result = default(Dictionary<String, String>);
|
var result = default(Dictionary<String, String>);
|
||||||
|
|
||||||
if (token != null && token.Type != TokenType.Null)
|
if (token != null && token.Type != TokenType.Null)
|
||||||
{
|
{
|
||||||
var context = CreateContext(contextData, expressionFunctions);
|
var context = CreateContext(contextData, expressionFunctions, expressionState);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepWith, token, 0, null, omitHeader: true);
|
token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepWith, token, 0, null, omitHeader: true);
|
||||||
|
|||||||
@@ -222,9 +222,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"job-outputs": {
|
"job-outputs": {
|
||||||
"context": [
|
|
||||||
"matrix"
|
|
||||||
],
|
|
||||||
"mapping": {
|
"mapping": {
|
||||||
"loose-key-type": "non-empty-string",
|
"loose-key-type": "non-empty-string",
|
||||||
"loose-value-type": "string-runner-context"
|
"loose-value-type": "string-runner-context"
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
using GitHub.Services.WebApi;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
|
|
||||||
public class ListRunnersResponse
|
|
||||||
{
|
|
||||||
public ListRunnersResponse()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListRunnersResponse(ListRunnersResponse responseToBeCloned)
|
|
||||||
{
|
|
||||||
this.TotalCount = responseToBeCloned.TotalCount;
|
|
||||||
this.Runners = responseToBeCloned.Runners;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("total_count")]
|
|
||||||
public int TotalCount
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("runners")]
|
|
||||||
public List<Runner> Runners
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListRunnersResponse Clone()
|
|
||||||
{
|
|
||||||
return new ListRunnersResponse(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TaskAgent> ToTaskAgents()
|
|
||||||
{
|
|
||||||
return Runners.Select(runner => new TaskAgent() { Name = runner.Name }).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
public class Runner
|
|
||||||
{
|
|
||||||
|
|
||||||
public class Authorization
|
|
||||||
{
|
|
||||||
[JsonProperty("authorization_url")]
|
|
||||||
public Uri AuthorizationUrl
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
internal set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("client_id")]
|
|
||||||
public string ClientId
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
internal set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
internal set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("id")]
|
|
||||||
public Int32 Id
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
internal set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("authorization")]
|
|
||||||
public Authorization RunnerAuthorization
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
internal set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
using GitHub.Services.WebApi;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An organization-level grouping of runners.
|
|
||||||
/// </summary>
|
|
||||||
[DataContract]
|
|
||||||
public class RunnerGroup
|
|
||||||
{
|
|
||||||
internal RunnerGroup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public RunnerGroup(String name)
|
|
||||||
{
|
|
||||||
this.Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RunnerGroup(RunnerGroup poolToBeCloned)
|
|
||||||
{
|
|
||||||
this.Id = poolToBeCloned.Id;
|
|
||||||
this.IsHosted = poolToBeCloned.IsHosted;
|
|
||||||
this.Name = poolToBeCloned.Name;
|
|
||||||
this.IsDefault = poolToBeCloned.IsDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
[JsonProperty("id")]
|
|
||||||
public Int32 Id
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public String Name
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether or not this pool is internal and can't be modified by users
|
|
||||||
/// </summary>
|
|
||||||
[DataMember]
|
|
||||||
[JsonProperty("default")]
|
|
||||||
public bool IsDefault
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether or not this pool is managed by the service.
|
|
||||||
/// </summary>
|
|
||||||
[DataMember]
|
|
||||||
[JsonProperty("is_hosted")]
|
|
||||||
public Boolean IsHosted
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RunnerGroupList
|
|
||||||
{
|
|
||||||
public RunnerGroupList()
|
|
||||||
{
|
|
||||||
this.RunnerGroups = new List<RunnerGroup>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TaskAgentPool> ToAgentPoolList()
|
|
||||||
{
|
|
||||||
var agentPools = this.RunnerGroups.Select(x => new TaskAgentPool(x.Name)
|
|
||||||
{
|
|
||||||
Id = x.Id,
|
|
||||||
IsHosted = x.IsHosted,
|
|
||||||
IsInternal = x.IsDefault
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
return agentPools;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("runner_groups")]
|
|
||||||
public List<RunnerGroup> RunnerGroups { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("total_count")]
|
|
||||||
public int Count { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
public class ConfigurationManagerL0
|
public class ConfigurationManagerL0
|
||||||
{
|
{
|
||||||
private Mock<IRunnerServer> _runnerServer;
|
private Mock<IRunnerServer> _runnerServer;
|
||||||
private Mock<IRunnerDotcomServer> _dotcomServer;
|
|
||||||
private Mock<ILocationServer> _locationServer;
|
private Mock<ILocationServer> _locationServer;
|
||||||
private Mock<ICredentialManager> _credMgr;
|
private Mock<ICredentialManager> _credMgr;
|
||||||
private Mock<IPromptManager> _promptManager;
|
private Mock<IPromptManager> _promptManager;
|
||||||
@@ -56,7 +55,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
_store = new Mock<IConfigurationStore>();
|
_store = new Mock<IConfigurationStore>();
|
||||||
_extnMgr = new Mock<IExtensionManager>();
|
_extnMgr = new Mock<IExtensionManager>();
|
||||||
_rsaKeyManager = new Mock<IRSAKeyManager>();
|
_rsaKeyManager = new Mock<IRSAKeyManager>();
|
||||||
_dotcomServer = new Mock<IRunnerDotcomServer>();
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
_serviceControlManager = new Mock<IWindowsServiceControlManager>();
|
_serviceControlManager = new Mock<IWindowsServiceControlManager>();
|
||||||
@@ -108,10 +106,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
_runnerServer.Setup(x => x.AddAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
_runnerServer.Setup(x => x.AddAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
||||||
_runnerServer.Setup(x => x.ReplaceAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
_runnerServer.Setup(x => x.ReplaceAgentAsync(It.IsAny<int>(), It.IsAny<TaskAgent>())).Returns(Task.FromResult(expectedAgent));
|
||||||
|
|
||||||
_dotcomServer.Setup(x => x.GetRunnersAsync(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgents));
|
|
||||||
_dotcomServer.Setup(x => x.GetRunnerGroupsAsync(It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedPools));
|
|
||||||
_dotcomServer.Setup(x => x.AddRunnerAsync(It.IsAny<int>(), It.IsAny<TaskAgent>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(expectedAgent));
|
|
||||||
|
|
||||||
rsa = new RSACryptoServiceProvider(2048);
|
rsa = new RSACryptoServiceProvider(2048);
|
||||||
|
|
||||||
_rsaKeyManager.Setup(x => x.CreateKey()).Returns(rsa);
|
_rsaKeyManager.Setup(x => x.CreateKey()).Returns(rsa);
|
||||||
@@ -125,7 +119,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
tc.SetSingleton<IConfigurationStore>(_store.Object);
|
tc.SetSingleton<IConfigurationStore>(_store.Object);
|
||||||
tc.SetSingleton<IExtensionManager>(_extnMgr.Object);
|
tc.SetSingleton<IExtensionManager>(_extnMgr.Object);
|
||||||
tc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
tc.SetSingleton<IRunnerServer>(_runnerServer.Object);
|
||||||
tc.SetSingleton<IRunnerDotcomServer>(_dotcomServer.Object);
|
|
||||||
tc.SetSingleton<ILocationServer>(_locationServer.Object);
|
tc.SetSingleton<ILocationServer>(_locationServer.Object);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
|||||||
@@ -25,21 +25,21 @@ runs:
|
|||||||
- run: exit ${{ inputs.exit-code }}
|
- run: exit ${{ inputs.exit-code }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- run: echo "default=true" >> $GITHUB_OUTPUT
|
- run: echo "::set-output name=default::true"
|
||||||
id: default-conditional
|
id: default-conditional
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- run: echo "success=true" >> $GITHUB_OUTPUT
|
- run: echo "::set-output name=success::true"
|
||||||
id: success-conditional
|
id: success-conditional
|
||||||
shell: bash
|
shell: bash
|
||||||
if: success()
|
if: success()
|
||||||
|
|
||||||
- run: echo "failure=true" >> $GITHUB_OUTPUT
|
- run: echo "::set-output name=failure::true"
|
||||||
id: failure-conditional
|
id: failure-conditional
|
||||||
shell: bash
|
shell: bash
|
||||||
if: failure()
|
if: failure()
|
||||||
|
|
||||||
- run: echo "always=true" >> $GITHUB_OUTPUT
|
- run: echo "::set-output name=always::true"
|
||||||
id: always-conditional
|
id: always-conditional
|
||||||
shell: bash
|
shell: bash
|
||||||
if: always()
|
if: always()
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.303.0
|
2.302.1
|
||||||
|
|||||||
Reference in New Issue
Block a user