diff --git a/releaseNote.md b/releaseNote.md index b75e056e3..48d725bc5 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -1,14 +1,18 @@ ## Features - - N/A + - Resolve action download info from server (#508, #515, #550) + - Print runner and machine name to log. (#539) ## Bugs - - Handle `jq` returns "null" if the field does not exist in create-latest-svc.sh (#478) - - Switch GITHUB_URL to GITHUB_SERVER_URL (#482) - - Fix problem matcher for GHES (#488) - - Fix container action inputs validation warning (#490) - - Fix post step display name (#490) - - Fix worker crash due to exception from evaluating step.env (#490) + - Reduce input validation warnings (#506) + - Fix null ref exception in SecretMasker caused by `hashfiles` timeout. (#516) + - Add libicu66 to `./installDependencies.sh` for Ubuntu 20.04 (#535) + - Fix DataContract with Token service (#532) + - Skip search $PATH on command with fully qualified path (#526) + - Restore SELinux context on service file when SELinux is enabled (#525) ## Misc - - N/A + - Remove SPS/Token migration code. Remove GHES url manipulate code. (#513) + - Add sub-step for developer flow for clarity (#523) + - Update Links and Language to Git + VSCode (#522) + - Update runner configuration exception message (#540) ## 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. diff --git a/src/Misc/layoutbin/installdependencies.sh b/src/Misc/layoutbin/installdependencies.sh index 50a19982e..786714925 100755 --- a/src/Misc/layoutbin/installdependencies.sh +++ b/src/Misc/layoutbin/installdependencies.sh @@ -70,8 +70,8 @@ then exit 1 fi - # libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52 - apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52 + # libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52 + apt install -y libicu66 || apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52 if [ $? -ne 0 ] then echo "'apt' failed with exit code '$?'" @@ -99,8 +99,8 @@ then exit 1 fi - # libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52 - apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52 + # libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52 + apt-get install -y libicu66 || apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52 if [ $? -ne 0 ] then echo "'apt-get' failed with exit code '$?'" diff --git a/src/Misc/layoutbin/systemd.svc.sh.template b/src/Misc/layoutbin/systemd.svc.sh.template index cbec33197..bdbc998f7 100644 --- a/src/Misc/layoutbin/systemd.svc.sh.template +++ b/src/Misc/layoutbin/systemd.svc.sh.template @@ -63,12 +63,25 @@ function install() sed "s/{{User}}/${run_as_user}/g; s/{{Description}}/$(echo ${SVC_DESCRIPTION} | sed -e 's/[\/&]/\\&/g')/g; s/{{RunnerRoot}}/$(echo ${RUNNER_ROOT} | sed -e 's/[\/&]/\\&/g')/g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file" mv "${TEMP_PATH}" "${UNIT_PATH}" || failed "failed to copy unit file" + + # Recent Fedora based Linux (CentOS/Redhat) has SELinux enabled by default + # We need to restore security context on the unit file we added otherwise SystemD have no access to it. + command -v getenforce > /dev/null + if [ $? -eq 0 ] + then + selinuxEnabled=$(getenforce) + if [[ $selinuxEnabled == "Enforcing" ]] + then + # SELinux is enabled, we will need to Restore SELinux Context for the service file + restorecon -r -v "${UNIT_PATH}" || failed "failed to restore SELinux context on ${UNIT_PATH}" + fi + fi # unit file should not be executable and world writable - chmod 664 ${UNIT_PATH} || failed "failed to set permissions on ${UNIT_PATH}" + chmod 664 "${UNIT_PATH}" || failed "failed to set permissions on ${UNIT_PATH}" systemctl daemon-reload || failed "failed to reload daemons" - # Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user. + # Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user. cp ./bin/runsvc.sh ./runsvc.sh || failed "failed to copy runsvc.sh" chown ${run_as_uid}:${run_as_gid} ./runsvc.sh || failed "failed to set owner for runsvc.sh" chmod 755 ./runsvc.sh || failed "failed to set permission for runsvc.sh" diff --git a/src/Runner.Listener/Configuration/ConfigurationManager.cs b/src/Runner.Listener/Configuration/ConfigurationManager.cs index 7d634067f..ce0863e1a 100644 --- a/src/Runner.Listener/Configuration/ConfigurationManager.cs +++ b/src/Runner.Listener/Configuration/ConfigurationManager.cs @@ -210,7 +210,7 @@ namespace GitHub.Runner.Listener.Configuration else if (command.Unattended) { // if not replace and it is unattended config. - throw new TaskAgentExistsException($"Pool {runnerSettings.PoolId} already contains a runner with name {runnerSettings.AgentName}."); + throw new TaskAgentExistsException($"A runner exists with the same name {runnerSettings.AgentName}."); } } else diff --git a/src/Runner.Sdk/ProcessInvoker.cs b/src/Runner.Sdk/ProcessInvoker.cs index 4ed4ce3b0..78a9f2dd2 100644 --- a/src/Runner.Sdk/ProcessInvoker.cs +++ b/src/Runner.Sdk/ProcessInvoker.cs @@ -346,14 +346,14 @@ namespace GitHub.Runner.Sdk // data buffers one last time before returning ProcessOutput(); - Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}."); - } + if (cancellationToken.IsCancellationRequested) + { + // Ensure cancellation also finish on the cancellationToken.Register thread. + await cancellationFinished.Task; + Trace.Info($"Process Cancellation finished."); + } - if (cancellationToken.IsCancellationRequested) - { - // Ensure cancellation also finish on the cancellationToken.Register thread. - await cancellationFinished.Task; - Trace.Info($"Process Cancellation finished."); + Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}."); } cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Runner.Sdk/Util/WhichUtil.cs b/src/Runner.Sdk/Util/WhichUtil.cs index 71acd92d9..b4d94e513 100644 --- a/src/Runner.Sdk/Util/WhichUtil.cs +++ b/src/Runner.Sdk/Util/WhichUtil.cs @@ -11,6 +11,11 @@ namespace GitHub.Runner.Sdk { ArgUtil.NotNullOrEmpty(command, nameof(command)); trace?.Info($"Which: '{command}'"); + if (Path.IsPathFullyQualified(command) && File.Exists(command)) + { + trace?.Info($"Fully qualified path: '{command}'"); + return command; + } string path = Environment.GetEnvironmentVariable(PathUtil.PathVariable); if (string.IsNullOrEmpty(path)) { diff --git a/src/Runner.Worker/ActionManager.cs b/src/Runner.Worker/ActionManager.cs index 2dbef6fb5..242ab79e0 100644 --- a/src/Runner.Worker/ActionManager.cs +++ b/src/Runner.Worker/ActionManager.cs @@ -552,56 +552,6 @@ namespace GitHub.Runner.Worker } } - // This implementation is temporary and will be removed when we switch to a REST API call to the service to resolve the download info - private async Task RepoExistsAsync(IExecutionContext executionContext, WebApi.ActionDownloadInfo actionDownloadInfo, string token) - { - var apiUrl = GetApiUrl(executionContext); - var repoUrl = $"{apiUrl}/repos/{actionDownloadInfo.NameWithOwner}"; - for (var attempt = 1; attempt <= 3; attempt++) - { - executionContext.Debug($"Checking whether repo exists: {repoUrl}"); - try - { - using (var httpClientHandler = HostContext.CreateHttpClientHandler()) - using (var httpClient = new HttpClient(httpClientHandler)) - { - httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(token); - httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents); - using (var response = await httpClient.GetAsync(repoUrl)) - { - if (response.IsSuccessStatusCode) - { - return true; - } - else if (response.StatusCode == HttpStatusCode.NotFound) - { - return false; - } - else - { - // Throw - response.EnsureSuccessStatusCode(); - } - } - } - } - catch (Exception ex) - { - if (attempt < 3) - { - executionContext.Debug($"Failed checking whether repo '{actionDownloadInfo.NameWithOwner}' exists: {ex.Message}"); - } - else - { - executionContext.Error($"Failed checking whether repo '{actionDownloadInfo.NameWithOwner}' exists: {ex.Message}"); - throw; - } - } - } - - return false; // Never reaches here - } - // This implementation is temporary and will be replaced with a REST API call to the service to resolve private async Task> GetDownloadInfoAsync(IExecutionContext executionContext, List actions) { @@ -665,23 +615,10 @@ namespace GitHub.Runner.Worker // Add secret HostContext.SecretMasker.AddValue(actionDownloadInfo.Authentication?.Token); - // Temporary code: Fix token and download URL - if (runnerSettings.IsHostedServer) + // Default auth token + if (string.IsNullOrEmpty(actionDownloadInfo.Authentication?.Token)) { actionDownloadInfo.Authentication = new WebApi.ActionDownloadAuthentication { Token = defaultAccessToken }; - actionDownloadInfo.TarballUrl = actionDownloadInfo.TarballUrl.Replace("", apiUrl); - actionDownloadInfo.ZipballUrl = actionDownloadInfo.ZipballUrl.Replace("", apiUrl); - } - else if (await RepoExistsAsync(executionContext, actionDownloadInfo, defaultAccessToken)) - { - actionDownloadInfo.Authentication = new WebApi.ActionDownloadAuthentication { Token = defaultAccessToken }; - actionDownloadInfo.TarballUrl = actionDownloadInfo.TarballUrl.Replace("", apiUrl); - actionDownloadInfo.ZipballUrl = actionDownloadInfo.ZipballUrl.Replace("", apiUrl); - } - else - { - actionDownloadInfo.TarballUrl = actionDownloadInfo.TarballUrl.Replace("", "https://api.github.com"); - actionDownloadInfo.ZipballUrl = actionDownloadInfo.ZipballUrl.Replace("", "https://api.github.com"); } } diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index 235cc9063..61f080c71 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -64,6 +64,20 @@ namespace GitHub.Runner.Worker context.Debug($"Starting: Set up job"); context.Output($"Current runner version: '{BuildConstants.RunnerPackage.Version}'"); + var setting = HostContext.GetService().GetSettings(); + var credFile = HostContext.GetConfigFile(WellKnownConfigFile.Credentials); + if (File.Exists(credFile)) + { + var credData = IOUtil.LoadObject(credFile); + if (credData != null && + credData.Data.TryGetValue("clientId", out var clientId)) + { + // print out HostName for self-hosted runner + context.Output($"Runner name: '{setting.AgentName}'"); + context.Output($"Machine name: '{Environment.MachineName}'"); + } + } + var setupInfoFile = HostContext.GetConfigFile(WellKnownConfigFile.SetupInfo); if (File.Exists(setupInfoFile)) { diff --git a/src/Sdk/DTPipelines/Pipelines/ContextData/NumberContextData.cs b/src/Sdk/DTPipelines/Pipelines/ContextData/NumberContextData.cs index 07d2172bc..82ad590b1 100644 --- a/src/Sdk/DTPipelines/Pipelines/ContextData/NumberContextData.cs +++ b/src/Sdk/DTPipelines/Pipelines/ContextData/NumberContextData.cs @@ -42,7 +42,12 @@ namespace GitHub.DistributedTask.Pipelines.ContextData var floored = Math.Floor(m_value); if (m_value == floored && m_value <= (Double)Int32.MaxValue && m_value >= (Double)Int32.MinValue) { - Int32 flooredInt = (Int32)floored; + var flooredInt = (Int32)floored; + return (JToken)flooredInt; + } + else if (m_value == floored && m_value <= (Double)Int64.MaxValue && m_value >= (Double)Int64.MinValue) + { + var flooredInt = (Int64)floored; return (JToken)flooredInt; } else diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs index fab331726..8ecf34271 100644 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs +++ b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs @@ -39,7 +39,7 @@ namespace GitHub.Services.OAuth /// /// Gets or sets the error description for the response. /// - [DataMember(Name = "errordescription", EmitDefaultValue = false)] + [DataMember(Name = "error_description", EmitDefaultValue = false)] public String ErrorDescription { get; diff --git a/src/Test/L0/Util/WhichUtilL0.cs b/src/Test/L0/Util/WhichUtilL0.cs index 99e4a92a5..7271bc283 100644 --- a/src/Test/L0/Util/WhichUtilL0.cs +++ b/src/Test/L0/Util/WhichUtilL0.cs @@ -70,5 +70,24 @@ namespace GitHub.Runner.Common.Tests.Util } } } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Common")] + public void WhichHandleFullyQualifiedPath() + { + using (TestHostContext hc = new TestHostContext(this)) + { + //Arrange + Tracing trace = hc.GetTrace(); + + // Act. + var gitPath = WhichUtil.Which("git", require: true, trace: trace); + var gitPath2 = WhichUtil.Which(gitPath, require: true, trace: trace); + + // Assert. + Assert.Equal(gitPath, gitPath2); + } + } } } diff --git a/src/Test/L0/Worker/ActionManagerL0.cs b/src/Test/L0/Worker/ActionManagerL0.cs index 85851a55a..58ffea5aa 100644 --- a/src/Test/L0/Worker/ActionManagerL0.cs +++ b/src/Test/L0/Worker/ActionManagerL0.cs @@ -3607,8 +3607,8 @@ runs: { NameWithOwner = action.NameWithOwner, Ref = action.Ref, - TarballUrl = $"/repos/{action.NameWithOwner}/tarball/{action.Ref}", - ZipballUrl = $"/repos/{action.NameWithOwner}/zipball/{action.Ref}", + TarballUrl = $"https://api.github.com/repos/{action.NameWithOwner}/tarball/{action.Ref}", + ZipballUrl = $"https://api.github.com/repos/{action.NameWithOwner}/zipball/{action.Ref}", }; } return Task.FromResult(result); diff --git a/src/runnerversion b/src/runnerversion index f9d36d71d..58301aa10 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.263.0 +2.267.0