Compare commits

..

1 Commits

Author SHA1 Message Date
Salman Chishti
6f9a9110ad Update release version to 2.328.0 2025-08-13 17:44:53 +01:00
24 changed files with 273 additions and 1141 deletions

View File

@@ -4,7 +4,7 @@
"features": { "features": {
"ghcr.io/devcontainers/features/docker-in-docker:1": {}, "ghcr.io/devcontainers/features/docker-in-docker:1": {},
"ghcr.io/devcontainers/features/dotnet": { "ghcr.io/devcontainers/features/dotnet": {
"version": "8.0.413" "version": "8.0.412"
}, },
"ghcr.io/devcontainers/features/node:1": { "ghcr.io/devcontainers/features/node:1": {
"version": "20" "version": "20"

View File

@@ -14,9 +14,6 @@ on:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
permissions:
contents: read
jobs: jobs:
build: build:
strategy: strategy:
@@ -83,48 +80,3 @@ jobs:
name: runner-package-${{ matrix.runtime }} name: runner-package-${{ matrix.runtime }}
path: | path: |
_package _package
docker:
strategy:
matrix:
os: [ ubuntu-latest, ubuntu-24.04-arm ]
include:
- os: ubuntu-latest
docker_platform: linux/amd64
- os: ubuntu-24.04-arm
docker_platform: linux/arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- name: Get latest runner version
id: latest_runner
uses: actions/github-script@v7
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const release = await github.rest.repos.getLatestRelease({
owner: 'actions',
repo: 'runner',
});
const version = release.data.tag_name.replace(/^v/, '');
core.setOutput('version', version);
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: ./images
load: true
platforms: ${{ matrix.docker_platform }}
tags: |
${{ github.sha }}:latest
build-args: |
RUNNER_VERSION=${{ steps.latest_runner.outputs.version }}
- name: Test Docker image
run: |
docker run --rm ${{ github.sha }}:latest ./run.sh --version

View File

@@ -334,12 +334,11 @@ jobs:
push: true push: true
labels: | labels: |
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}} org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
org.opencontainers.image.licenses=MIT
annotations: |
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }} org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
org.opencontainers.image.licenses=MIT
- name: Generate attestation - name: Generate attestation
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v2
with: with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }} subject-digest: ${{ steps.build-and-push.outputs.digest }}

View File

@@ -1 +1,6 @@
cd src/Misc/expressionFunc/hashFiles && npx lint-staged #!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
cd src/Misc/expressionFunc/hashFiles
npx lint-staged

View File

@@ -1,12 +1,12 @@
# Source: https://github.com/dotnet/dotnet-docker # Source: https://github.com/dotnet/dotnet-docker
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-noble AS build FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy AS build
ARG TARGETOS ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH
ARG RUNNER_VERSION ARG RUNNER_VERSION
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.7.0 ARG RUNNER_CONTAINER_HOOKS_VERSION=0.7.0
ARG DOCKER_VERSION=28.3.3 ARG DOCKER_VERSION=28.3.2
ARG BUILDX_VERSION=0.27.0 ARG BUILDX_VERSION=0.26.1
RUN apt update -y && apt install curl unzip -y RUN apt update -y && apt install curl unzip -y
@@ -32,12 +32,12 @@ RUN export RUNNER_ARCH=${TARGETARCH} \
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \ "https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx && chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-noble FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
ENV RUNNER_MANUALLY_TRAP_SIG=1 ENV RUNNER_MANUALLY_TRAP_SIG=1
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1 ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
ENV ImageOS=ubuntu24 ENV ImageOS=ubuntu22
# 'gpg-agent' and 'software-properties-common' are needed for the 'add-apt-repository' command that follows # 'gpg-agent' and 'software-properties-common' are needed for the 'add-apt-repository' command that follows
RUN apt update -y \ RUN apt update -y \

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
"pack": "ncc build -o ../../layoutbin/hashFiles", "pack": "ncc build -o ../../layoutbin/hashFiles",
"all": "npm run format && npm run lint && npm run build && npm run pack", "all": "npm run format && npm run lint && npm run build && npm run pack",
"prepare": "cd ../../../../ && husky" "prepare": "cd ../../../../ && husky install"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -36,15 +36,15 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.2", "@types/node": "^20.6.2",
"@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/eslint-plugin": "^6.7.2",
"@typescript-eslint/parser": "^6.7.2", "@typescript-eslint/parser": "^6.7.2",
"@vercel/ncc": "^0.38.3", "@vercel/ncc": "^0.38.0",
"eslint": "^8.47.0", "eslint": "^8.47.0",
"eslint-plugin-github": "^4.10.2", "eslint-plugin-github": "^4.10.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"husky": "^9.1.7", "husky": "^8.0.3",
"lint-staged": "^15.5.0", "lint-staged": "^15.5.0",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"typescript": "^5.9.2" "typescript": "^5.2.2"
} }
} }

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
SECONDS=0 SECONDS=0
while [[ $SECONDS -lt $1 ]]; do while [[ $SECONDS != $1 ]]; do
: :
done done

View File

@@ -23,8 +23,6 @@ namespace GitHub.Runner.Common
Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken token); Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken token);
Task AcknowledgeRunnerRequestAsync(string runnerRequestId, Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, CancellationToken token);
Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials); Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials);
Task ForceRefreshConnection(VssCredentials credentials); Task ForceRefreshConnection(VssCredentials credentials);
@@ -69,17 +67,10 @@ namespace GitHub.Runner.Common
var brokerSession = RetryRequest<TaskAgentMessage>( var brokerSession = RetryRequest<TaskAgentMessage>(
async () => await _brokerHttpClient.GetRunnerMessageAsync(sessionId, version, status, os, architecture, disableUpdate, cancellationToken), cancellationToken, shouldRetry: ShouldRetryException); async () => await _brokerHttpClient.GetRunnerMessageAsync(sessionId, version, status, os, architecture, disableUpdate, cancellationToken), cancellationToken, shouldRetry: ShouldRetryException);
return brokerSession; return brokerSession;
} }
public async Task AcknowledgeRunnerRequestAsync(string runnerRequestId, Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, CancellationToken cancellationToken)
{
CheckConnection();
// No retries
await _brokerHttpClient.AcknowledgeRunnerRequestAsync(runnerRequestId, sessionId, version, status, os, architecture, cancellationToken);
}
public async Task DeleteSessionAsync(CancellationToken cancellationToken) public async Task DeleteSessionAsync(CancellationToken cancellationToken)
{ {
CheckConnection(); CheckConnection();

View File

@@ -53,9 +53,6 @@ namespace GitHub.Runner.Common
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public bool UseV2Flow { get; set; } public bool UseV2Flow { get; set; }
[DataMember(EmitDefaultValue = false)]
public bool UseRunnerAdminFlow { get; set; }
[DataMember(EmitDefaultValue = false)] [DataMember(EmitDefaultValue = false)]
public string ServerUrlV2 { get; set; } public string ServerUrlV2 { get; set; }

View File

@@ -169,7 +169,6 @@ namespace GitHub.Runner.Common
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks"; public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
public static readonly string AddCheckRunIdToJobContext = "actions_add_check_run_id_to_job_context"; public static readonly string AddCheckRunIdToJobContext = "actions_add_check_run_id_to_job_context";
public static readonly string DisplayHelpfulActionsDownloadErrors = "actions_display_helpful_actions_download_errors"; public static readonly string DisplayHelpfulActionsDownloadErrors = "actions_display_helpful_actions_download_errors";
public static readonly string ContainerActionRunnerTemp = "actions_container_action_runner_temp";
} }
// Node version migration related constants // Node version migration related constants

View File

@@ -70,7 +70,7 @@ namespace GitHub.Runner.Common
protected async Task RetryRequest(Func<Task> func, protected async Task RetryRequest(Func<Task> func,
CancellationToken cancellationToken, CancellationToken cancellationToken,
int maxAttempts = 5, int maxRetryAttemptsCount = 5,
Func<Exception, bool> shouldRetry = null Func<Exception, bool> shouldRetry = null
) )
{ {
@@ -79,31 +79,31 @@ namespace GitHub.Runner.Common
await func(); await func();
return Unit.Value; return Unit.Value;
} }
await RetryRequest<Unit>(wrappedFunc, cancellationToken, maxAttempts, shouldRetry); await RetryRequest<Unit>(wrappedFunc, cancellationToken, maxRetryAttemptsCount, shouldRetry);
} }
protected async Task<T> RetryRequest<T>(Func<Task<T>> func, protected async Task<T> RetryRequest<T>(Func<Task<T>> func,
CancellationToken cancellationToken, CancellationToken cancellationToken,
int maxAttempts = 5, int maxRetryAttemptsCount = 5,
Func<Exception, bool> shouldRetry = null Func<Exception, bool> shouldRetry = null
) )
{ {
var attempt = 0; var retryCount = 0;
while (true) while (true)
{ {
attempt++; retryCount++;
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
try try
{ {
return await func(); return await func();
} }
// TODO: Add handling of non-retriable exceptions: https://github.com/github/actions-broker/issues/122 // TODO: Add handling of non-retriable exceptions: https://github.com/github/actions-broker/issues/122
catch (Exception ex) when (attempt < maxAttempts && (shouldRetry == null || shouldRetry(ex))) catch (Exception ex) when (retryCount < maxRetryAttemptsCount && (shouldRetry == null || shouldRetry(ex)))
{ {
Trace.Error("Catch exception during request"); Trace.Error("Catch exception during request");
Trace.Error(ex); Trace.Error(ex);
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15)); var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
Trace.Warning($"Back off {backOff.TotalSeconds} seconds before next retry. {maxAttempts - attempt} attempt left."); Trace.Warning($"Back off {backOff.TotalSeconds} seconds before next retry. {maxRetryAttemptsCount - retryCount} attempt left.");
await Task.Delay(backOff, cancellationToken); await Task.Delay(backOff, cancellationToken);
} }
} }

View File

@@ -23,7 +23,7 @@ namespace GitHub.Runner.Listener
private RunnerSettings _settings; private RunnerSettings _settings;
private ITerminal _term; private ITerminal _term;
private TimeSpan _getNextMessageRetryInterval; private TimeSpan _getNextMessageRetryInterval;
private TaskAgentStatus _runnerStatus = TaskAgentStatus.Online; private TaskAgentStatus runnerStatus = TaskAgentStatus.Online;
private CancellationTokenSource _getMessagesTokenSource; private CancellationTokenSource _getMessagesTokenSource;
private VssCredentials _creds; private VssCredentials _creds;
private VssCredentials _credsV2; private VssCredentials _credsV2;
@@ -258,7 +258,7 @@ namespace GitHub.Runner.Listener
public void OnJobStatus(object sender, JobStatusEventArgs e) public void OnJobStatus(object sender, JobStatusEventArgs e)
{ {
Trace.Info("Received job status event. JobState: {0}", e.Status); Trace.Info("Received job status event. JobState: {0}", e.Status);
_runnerStatus = e.Status; runnerStatus = e.Status;
try try
{ {
_getMessagesTokenSource?.Cancel(); _getMessagesTokenSource?.Cancel();
@@ -291,7 +291,7 @@ namespace GitHub.Runner.Listener
} }
message = await _brokerServer.GetRunnerMessageAsync(_session.SessionId, message = await _brokerServer.GetRunnerMessageAsync(_session.SessionId,
_runnerStatus, runnerStatus,
BuildConstants.RunnerPackage.Version, BuildConstants.RunnerPackage.Version,
VarUtil.OS, VarUtil.OS,
VarUtil.OSArchitecture, VarUtil.OSArchitecture,
@@ -417,21 +417,6 @@ namespace GitHub.Runner.Listener
await Task.CompletedTask; await Task.CompletedTask;
} }
public async Task AcknowledgeMessageAsync(string runnerRequestId, CancellationToken cancellationToken)
{
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // Short timeout
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
Trace.Info($"Acknowledging runner request '{runnerRequestId}'.");
await _brokerServer.AcknowledgeRunnerRequestAsync(
runnerRequestId,
_session.SessionId,
_runnerStatus,
BuildConstants.RunnerPackage.Version,
VarUtil.OS,
VarUtil.OSArchitecture,
linkedCts.Token);
}
private bool IsGetNextMessageExceptionRetriable(Exception ex) private bool IsGetNextMessageExceptionRetriable(Exception ex)
{ {
if (ex is TaskAgentNotFoundException || if (ex is TaskAgentNotFoundException ||

View File

@@ -153,8 +153,8 @@ namespace GitHub.Runner.Listener.Configuration
registerToken = await GetRunnerTokenAsync(command, inputUrl, "registration"); 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.UseRunnerAdminFlow = authResult.UseRunnerAdminFlow; runnerSettings.UseV2Flow = authResult.UseV2Flow;
Trace.Info($"Using runner-admin flow: {runnerSettings.UseRunnerAdminFlow}"); Trace.Info($"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");
} }
@@ -211,7 +211,7 @@ namespace GitHub.Runner.Listener.Configuration
string poolName = null; string poolName = null;
TaskAgentPool agentPool = null; TaskAgentPool agentPool = null;
List<TaskAgentPool> agentPools; List<TaskAgentPool> agentPools;
if (runnerSettings.UseRunnerAdminFlow) if (runnerSettings.UseV2Flow)
{ {
agentPools = await _dotcomServer.GetRunnerGroupsAsync(runnerSettings.GitHubUrl, registerToken); agentPools = await _dotcomServer.GetRunnerGroupsAsync(runnerSettings.GitHubUrl, registerToken);
} }
@@ -259,7 +259,7 @@ namespace GitHub.Runner.Listener.Configuration
var userLabels = command.GetLabels(); var userLabels = command.GetLabels();
_term.WriteLine(); _term.WriteLine();
List<TaskAgent> agents; List<TaskAgent> agents;
if (runnerSettings.UseRunnerAdminFlow) if (runnerSettings.UseV2Flow)
{ {
agents = await _dotcomServer.GetRunnerByNameAsync(runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName); agents = await _dotcomServer.GetRunnerByNameAsync(runnerSettings.GitHubUrl, registerToken, runnerSettings.AgentName);
} }
@@ -280,7 +280,7 @@ namespace GitHub.Runner.Listener.Configuration
try try
{ {
if (runnerSettings.UseRunnerAdminFlow) if (runnerSettings.UseV2Flow)
{ {
var runner = await _dotcomServer.ReplaceRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML); var runner = await _dotcomServer.ReplaceRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML);
runnerSettings.ServerUrlV2 = runner.RunnerAuthorization.ServerUrl; runnerSettings.ServerUrlV2 = runner.RunnerAuthorization.ServerUrl;
@@ -330,7 +330,7 @@ namespace GitHub.Runner.Listener.Configuration
try try
{ {
if (runnerSettings.UseRunnerAdminFlow) if (runnerSettings.UseV2Flow)
{ {
var runner = await _dotcomServer.AddRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML); var runner = await _dotcomServer.AddRunnerAsync(runnerSettings.PoolId, agent, runnerSettings.GitHubUrl, registerToken, publicKeyXML);
runnerSettings.ServerUrlV2 = runner.RunnerAuthorization.ServerUrl; runnerSettings.ServerUrlV2 = runner.RunnerAuthorization.ServerUrl;
@@ -400,26 +400,13 @@ namespace GitHub.Runner.Listener.Configuration
} }
else else
{ {
throw new NotSupportedException("Message queue listen OAuth token."); throw new NotSupportedException("Message queue listen OAuth token.");
} }
// allow the server to override the serverUrlV2 and useV2Flow
if (agent.Properties.TryGetValue("ServerUrlV2", out string serverUrlV2) &&
!string.IsNullOrEmpty(serverUrlV2))
{
Trace.Info($"Service enforced serverUrlV2: {serverUrlV2}");
runnerSettings.ServerUrlV2 = serverUrlV2;
}
if (agent.Properties.TryGetValue("UseV2Flow", out bool useV2Flow) && useV2Flow)
{
Trace.Info($"Service enforced useV2Flow: {useV2Flow}");
runnerSettings.UseV2Flow = useV2Flow;
}
// Testing agent connection, detect any potential connection issue, like local clock skew that cause OAuth token expired. // Testing agent connection, detect any potential connection issue, like local clock skew that cause OAuth token expired.
if (!runnerSettings.UseV2Flow && !runnerSettings.UseRunnerAdminFlow) if (!runnerSettings.UseV2Flow)
{ {
var credMgr = HostContext.GetService<ICredentialManager>(); var credMgr = HostContext.GetService<ICredentialManager>();
VssCredentials credential = credMgr.LoadCredentials(allowAuthUrlV2: false); VssCredentials credential = credMgr.LoadCredentials(allowAuthUrlV2: false);
@@ -442,6 +429,20 @@ namespace GitHub.Runner.Listener.Configuration
} }
} }
// allow the server to override the serverUrlV2 and useV2Flow
if (agent.Properties.TryGetValue("ServerUrlV2", out string serverUrlV2) &&
!string.IsNullOrEmpty(serverUrlV2))
{
Trace.Info($"Service enforced serverUrlV2: {serverUrlV2}");
runnerSettings.ServerUrlV2 = serverUrlV2;
}
if (agent.Properties.TryGetValue("UseV2Flow", out bool useV2Flow) && useV2Flow)
{
Trace.Info($"Service enforced useV2Flow: {useV2Flow}");
runnerSettings.UseV2Flow = useV2Flow;
}
_term.WriteSection("Runner settings"); _term.WriteSection("Runner settings");
// We will Combine() what's stored with root. Defaults to string a relative path // We will Combine() what's stored with root. Defaults to string a relative path
@@ -537,7 +538,7 @@ namespace GitHub.Runner.Listener.Configuration
{ {
RunnerSettings settings = _store.GetSettings(); RunnerSettings settings = _store.GetSettings();
if (settings.UseRunnerAdminFlow) if (settings.UseV2Flow)
{ {
var deletionToken = await GetRunnerTokenAsync(command, settings.GitHubUrl, "remove"); var deletionToken = await GetRunnerTokenAsync(command, settings.GitHubUrl, "remove");
await _dotcomServer.DeleteRunnerAsync(settings.GitHubUrl, deletionToken, settings.AgentId); await _dotcomServer.DeleteRunnerAsync(settings.GitHubUrl, deletionToken, settings.AgentId);

View File

@@ -89,7 +89,7 @@ namespace GitHub.Runner.Listener.Configuration
public string Token { get; set; } public string Token { get; set; }
[DataMember(Name = "use_v2_flow")] [DataMember(Name = "use_v2_flow")]
public bool UseRunnerAdminFlow { get; set; } public bool UseV2Flow { get; set; }
public VssCredentials ToVssCredentials() public VssCredentials ToVssCredentials()
{ {

View File

@@ -32,7 +32,6 @@ 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);
Task AcknowledgeMessageAsync(string runnerRequestId, CancellationToken cancellationToken);
Task RefreshListenerTokenAsync(); Task RefreshListenerTokenAsync();
void OnJobStatus(object sender, JobStatusEventArgs e); void OnJobStatus(object sender, JobStatusEventArgs e);
@@ -53,7 +52,7 @@ namespace GitHub.Runner.Listener
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(); private readonly Dictionary<string, int> _sessionCreationExceptionTracker = new();
private TaskAgentStatus _runnerStatus = TaskAgentStatus.Online; private TaskAgentStatus runnerStatus = TaskAgentStatus.Online;
private CancellationTokenSource _getMessagesTokenSource; private CancellationTokenSource _getMessagesTokenSource;
private VssCredentials _creds; private VssCredentials _creds;
private VssCredentials _credsV2; private VssCredentials _credsV2;
@@ -218,7 +217,7 @@ namespace GitHub.Runner.Listener
public void OnJobStatus(object sender, JobStatusEventArgs e) public void OnJobStatus(object sender, JobStatusEventArgs e)
{ {
Trace.Info("Received job status event. JobState: {0}", e.Status); Trace.Info("Received job status event. JobState: {0}", e.Status);
_runnerStatus = e.Status; runnerStatus = e.Status;
try try
{ {
_getMessagesTokenSource?.Cancel(); _getMessagesTokenSource?.Cancel();
@@ -251,7 +250,7 @@ namespace GitHub.Runner.Listener
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId, message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
_session.SessionId, _session.SessionId,
_lastMessageId, _lastMessageId,
_runnerStatus, runnerStatus,
BuildConstants.RunnerPackage.Version, BuildConstants.RunnerPackage.Version,
VarUtil.OS, VarUtil.OS,
VarUtil.OSArchitecture, VarUtil.OSArchitecture,
@@ -275,7 +274,7 @@ namespace GitHub.Runner.Listener
} }
message = await _brokerServer.GetRunnerMessageAsync(_session.SessionId, message = await _brokerServer.GetRunnerMessageAsync(_session.SessionId,
_runnerStatus, runnerStatus,
BuildConstants.RunnerPackage.Version, BuildConstants.RunnerPackage.Version,
VarUtil.OS, VarUtil.OS,
VarUtil.OSArchitecture, VarUtil.OSArchitecture,
@@ -438,21 +437,6 @@ namespace GitHub.Runner.Listener
await _brokerServer.ForceRefreshConnection(_credsV2); await _brokerServer.ForceRefreshConnection(_credsV2);
} }
public async Task AcknowledgeMessageAsync(string runnerRequestId, CancellationToken cancellationToken)
{
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // Short timeout
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
Trace.Info($"Acknowledging runner request '{runnerRequestId}'.");
await _brokerServer.AcknowledgeRunnerRequestAsync(
runnerRequestId,
_session.SessionId,
_runnerStatus,
BuildConstants.RunnerPackage.Version,
VarUtil.OS,
VarUtil.OSArchitecture,
linkedCts.Token);
}
private TaskAgentMessage DecryptMessage(TaskAgentMessage message) private TaskAgentMessage DecryptMessage(TaskAgentMessage message)
{ {
if (_session.EncryptionKey == null || if (_session.EncryptionKey == null ||

View File

@@ -654,42 +654,22 @@ namespace GitHub.Runner.Listener
else else
{ {
var messageRef = StringUtil.ConvertFromJson<RunnerJobRequestRef>(message.Body); var messageRef = StringUtil.ConvertFromJson<RunnerJobRequestRef>(message.Body);
// Acknowledge (best-effort)
if (messageRef.ShouldAcknowledge) // Temporary feature flag
{
try
{
await _listener.AcknowledgeMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token);
}
catch (Exception ex)
{
Trace.Error($"Best-effort acknowledge failed for request '{messageRef.RunnerRequestId}'");
Trace.Error(ex);
}
}
Pipelines.AgentJobRequestMessage jobRequestMessage = null; Pipelines.AgentJobRequestMessage jobRequestMessage = null;
// Create connection
var credMgr = HostContext.GetService<ICredentialManager>();
if (string.IsNullOrEmpty(messageRef.RunServiceUrl)) if (string.IsNullOrEmpty(messageRef.RunServiceUrl))
{ {
// Connect
var credMgr = HostContext.GetService<ICredentialManager>();
var creds = credMgr.LoadCredentials(allowAuthUrlV2: false); var creds = credMgr.LoadCredentials(allowAuthUrlV2: false);
var actionsRunServer = HostContext.CreateService<IActionsRunServer>(); var actionsRunServer = HostContext.CreateService<IActionsRunServer>();
await actionsRunServer.ConnectAsync(new Uri(settings.ServerUrl), creds); await actionsRunServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
// Get job message
jobRequestMessage = await actionsRunServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token); jobRequestMessage = await actionsRunServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageQueueLoopTokenSource.Token);
} }
else else
{ {
// Connect
var credMgr = HostContext.GetService<ICredentialManager>();
var credsV2 = credMgr.LoadCredentials(allowAuthUrlV2: true); var credsV2 = credMgr.LoadCredentials(allowAuthUrlV2: true);
var runServer = HostContext.CreateService<IRunServer>(); var runServer = HostContext.CreateService<IRunServer>();
await runServer.ConnectAsync(new Uri(messageRef.RunServiceUrl), credsV2); await runServer.ConnectAsync(new Uri(messageRef.RunServiceUrl), credsV2);
// Get job message
try try
{ {
jobRequestMessage = await runServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageRef.BillingOwnerId, messageQueueLoopTokenSource.Token); jobRequestMessage = await runServer.GetJobMessageAsync(messageRef.RunnerRequestId, messageRef.BillingOwnerId, messageQueueLoopTokenSource.Token);
@@ -718,10 +698,7 @@ namespace GitHub.Runner.Listener
} }
} }
// Dispatch
jobDispatcher.Run(jobRequestMessage, runOnce); jobDispatcher.Run(jobRequestMessage, runOnce);
// Run once?
if (runOnce) if (runOnce)
{ {
Trace.Info("One time used runner received job message."); Trace.Info("One time used runner received job message.");

View File

@@ -10,9 +10,6 @@ namespace GitHub.Runner.Listener
[DataMember(Name = "runner_request_id")] [DataMember(Name = "runner_request_id")]
public string RunnerRequestId { get; set; } public string RunnerRequestId { get; set; }
[DataMember(Name = "should_acknowledge")]
public bool ShouldAcknowledge { get; set; }
[DataMember(Name = "run_service_url")] [DataMember(Name = "run_service_url")]
public string RunServiceUrl { get; set; } public string RunServiceUrl { get; set; }

View File

@@ -11,10 +11,5 @@ namespace GitHub.Runner.Worker
var isContainerHooksPathSet = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(Constants.Hooks.ContainerHooksPath)); var isContainerHooksPathSet = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(Constants.Hooks.ContainerHooksPath));
return isContainerHookFeatureFlagSet && isContainerHooksPathSet; return isContainerHookFeatureFlagSet && isContainerHooksPathSet;
} }
public static bool IsContainerActionRunnerTempEnabled(Variables variables)
{
return variables?.GetBoolean(Constants.Runner.Features.ContainerActionRunnerTemp) ?? false;
}
} }
} }

View File

@@ -191,19 +191,11 @@ namespace GitHub.Runner.Worker.Handlers
ArgUtil.Directory(tempWorkflowDirectory, nameof(tempWorkflowDirectory)); ArgUtil.Directory(tempWorkflowDirectory, nameof(tempWorkflowDirectory));
container.MountVolumes.Add(new MountVolume("/var/run/docker.sock", "/var/run/docker.sock")); container.MountVolumes.Add(new MountVolume("/var/run/docker.sock", "/var/run/docker.sock"));
if (FeatureManager.IsContainerActionRunnerTempEnabled(ExecutionContext.Global.Variables))
{
container.MountVolumes.Add(new MountVolume(tempDirectory, "/github/runner_temp"));
}
container.MountVolumes.Add(new MountVolume(tempHomeDirectory, "/github/home")); container.MountVolumes.Add(new MountVolume(tempHomeDirectory, "/github/home"));
container.MountVolumes.Add(new MountVolume(tempWorkflowDirectory, "/github/workflow")); container.MountVolumes.Add(new MountVolume(tempWorkflowDirectory, "/github/workflow"));
container.MountVolumes.Add(new MountVolume(tempFileCommandDirectory, "/github/file_commands")); container.MountVolumes.Add(new MountVolume(tempFileCommandDirectory, "/github/file_commands"));
container.MountVolumes.Add(new MountVolume(defaultWorkingDirectory, "/github/workspace")); container.MountVolumes.Add(new MountVolume(defaultWorkingDirectory, "/github/workspace"));
if (FeatureManager.IsContainerActionRunnerTempEnabled(ExecutionContext.Global.Variables))
{
container.AddPathTranslateMapping(tempDirectory, "/github/runner_temp");
}
container.AddPathTranslateMapping(tempHomeDirectory, "/github/home"); container.AddPathTranslateMapping(tempHomeDirectory, "/github/home");
container.AddPathTranslateMapping(tempWorkflowDirectory, "/github/workflow"); container.AddPathTranslateMapping(tempWorkflowDirectory, "/github/workflow");
container.AddPathTranslateMapping(tempFileCommandDirectory, "/github/file_commands"); container.AddPathTranslateMapping(tempFileCommandDirectory, "/github/file_commands");

View File

@@ -79,7 +79,6 @@ namespace GitHub.Actions.RunService.WebApi
{ {
queryParams.Add("status", status.Value.ToString()); queryParams.Add("status", status.Value.ToString());
} }
if (runnerVersion != null) if (runnerVersion != null)
{ {
queryParams.Add("runnerVersion", runnerVersion); queryParams.Add("runnerVersion", runnerVersion);
@@ -143,6 +142,7 @@ namespace GitHub.Actions.RunService.WebApi
} }
public async Task<TaskAgentSession> CreateSessionAsync( public async Task<TaskAgentSession> CreateSessionAsync(
TaskAgentSession session, TaskAgentSession session,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -191,76 +191,6 @@ namespace GitHub.Actions.RunService.WebApi
throw new Exception($"Failed to delete broker session: {result.Error}"); throw new Exception($"Failed to delete broker session: {result.Error}");
} }
public async Task AcknowledgeRunnerRequestAsync(
string runnerRequestId,
Guid? sessionId,
string runnerVersion,
TaskAgentStatus? status,
string os = null,
string architecture = null,
CancellationToken cancellationToken = default)
{
// URL
var requestUri = new Uri(Client.BaseAddress, "acknowledge");
// Query parameters
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
if (sessionId != null)
{
queryParams.Add("sessionId", sessionId.Value.ToString());
}
if (status != null)
{
queryParams.Add("status", status.Value.ToString());
}
if (runnerVersion != null)
{
queryParams.Add("runnerVersion", runnerVersion);
}
if (os != null)
{
queryParams.Add("os", os);
}
if (architecture != null)
{
queryParams.Add("architecture", architecture);
}
// Body
var payload = new Dictionary<string, string>
{
["runnerRequestId"] = runnerRequestId,
};
var requestContent = new ObjectContent<Dictionary<string, string>>(payload, new VssJsonMediaTypeFormatter(true));
// POST
var result = await SendAsync<object>(
new HttpMethod("POST"),
requestUri: requestUri,
queryParameters: queryParams,
content: requestContent,
readErrorBody: true,
cancellationToken: cancellationToken);
if (result.IsSuccess)
{
return;
}
if (TryParseErrorBody(result.ErrorBody, out BrokerError brokerError))
{
switch (brokerError.ErrorKind)
{
case BrokerErrorKind.RunnerNotFound:
throw new RunnerNotFoundException(brokerError.Message);
default:
break;
}
}
throw new Exception($"Failed to acknowledge runner request. Request to {requestUri} failed with status: {result.StatusCode}. Error message {result.Error}");
}
private static bool TryParseErrorBody(string errorBody, out BrokerError error) private static bool TryParseErrorBody(string errorBody, out BrokerError error)
{ {
if (!string.IsNullOrEmpty(errorBody)) if (!string.IsNullOrEmpty(errorBody))

View File

@@ -17,7 +17,7 @@ LAYOUT_DIR="$SCRIPT_DIR/../_layout"
DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x" DOWNLOAD_DIR="$SCRIPT_DIR/../_downloads/netcore2x"
PACKAGE_DIR="$SCRIPT_DIR/../_package" PACKAGE_DIR="$SCRIPT_DIR/../_package"
DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk" DOTNETSDK_ROOT="$SCRIPT_DIR/../_dotnetsdk"
DOTNETSDK_VERSION="8.0.413" DOTNETSDK_VERSION="8.0.412"
DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION" DOTNETSDK_INSTALLDIR="$DOTNETSDK_ROOT/$DOTNETSDK_VERSION"
RUNNER_VERSION=$(cat runnerversion) RUNNER_VERSION=$(cat runnerversion)

View File

@@ -1,5 +1,5 @@
{ {
"sdk": { "sdk": {
"version": "8.0.413" "version": "8.0.412"
} }
} }