Skip to content

Commit 02d2cb8

Browse files
authored
Lets allow up to 150 characters for services on linux/mac (#1710)
* Lets allow up to 150 characters on linux/mac, just to avoid some issues with runner naming * Add 4 randomized digits on mac/linux * fix pragma issue * fix test * �Address pr feedback * reduce complexity * lets make it cleaner! * fix test * fix logic
1 parent 0cbf335 commit 02d2cb8

File tree

2 files changed

+135
-83
lines changed

2 files changed

+135
-83
lines changed

src/Runner.Listener/Configuration/ServiceControlManager.cs

+16-6
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,12 @@ public void CalculateServiceName(RunnerSettings settings, string serviceNamePatt
4848
string repoOrOrgName = regex.Replace(settings.RepoOrOrgName, "-");
4949

5050
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgName, settings.AgentName);
51-
52-
if (serviceName.Length > 80)
51+
if (serviceName.Length > MaxServiceNameLength)
5352
{
54-
Trace.Verbose($"Calculated service name is too long (> 80 chars). Trying again by calculating a shorter name.");
55-
56-
int exceededCharLength = serviceName.Length - 80;
57-
string repoOrOrgNameSubstring = StringUtil.SubstringPrefix(repoOrOrgName, 45);
53+
Trace.Verbose($"Calculated service name is too long (> {MaxServiceNameLength} chars). Trying again by calculating a shorter name.");
54+
// Add 5 to add -xxxx random number on the end
55+
int exceededCharLength = serviceName.Length - MaxServiceNameLength + 5;
56+
string repoOrOrgNameSubstring = StringUtil.SubstringPrefix(repoOrOrgName, MaxRepoOrgCharacters);
5857

5958
exceededCharLength -= repoOrOrgName.Length - repoOrOrgNameSubstring.Length;
6059

@@ -66,12 +65,23 @@ public void CalculateServiceName(RunnerSettings settings, string serviceNamePatt
6665
runnerNameSubstring = StringUtil.SubstringPrefix(settings.AgentName, settings.AgentName.Length - exceededCharLength);
6766
}
6867

68+
// Lets add a suffix with a random number to reduce the chance of collisions between runner names once we truncate
69+
var random = new Random();
70+
var num = random.Next(1000, 9999).ToString();
71+
runnerNameSubstring +=$"-{num}";
6972
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring);
7073
}
7174

7275
serviceDisplayName = StringUtil.Format(serviceDisplayNamePattern, repoOrOrgName, settings.AgentName);
7376

7477
Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration.");
7578
}
79+
#if (OS_LINUX || OS_OSX)
80+
const int MaxServiceNameLength = 150;
81+
const int MaxRepoOrgCharacters = 70;
82+
#elif OS_WINDOWS
83+
const int MaxServiceNameLength = 80;
84+
const int MaxRepoOrgCharacters = 45;
85+
#endif
7686
}
7787
}

src/Test/L0/ServiceControlManagerL0.cs

+119-77
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Runtime.CompilerServices;
3+
using System.Text.RegularExpressions;
34
using GitHub.Runner.Common;
45
using GitHub.Runner.Listener.Configuration;
56
using Xunit;
@@ -15,7 +16,7 @@ public void CalculateServiceName()
1516
{
1617
RunnerSettings settings = new RunnerSettings();
1718

18-
settings.AgentName = "thisiskindofalongrunnername1";
19+
settings.AgentName = "thisiskindofalongrunnerabcde";
1920
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
2021
settings.GitHubUrl = "https://github.com/myorganizationexample/myrepoexample";
2122

@@ -43,7 +44,7 @@ public void CalculateServiceName()
4344
Assert.Equal("actions", serviceNameParts[0]);
4445
Assert.Equal("runner", serviceNameParts[1]);
4546
Assert.Equal("myorganizationexample-myrepoexample", serviceNameParts[2]); // '/' has been replaced with '-'
46-
Assert.Equal("thisiskindofalongrunnername1", serviceNameParts[3]);
47+
Assert.Equal("thisiskindofalongrunnerabcde", serviceNameParts[3]);
4748
}
4849
}
4950

@@ -54,7 +55,7 @@ public void CalculateServiceName80Chars()
5455
{
5556
RunnerSettings settings = new RunnerSettings();
5657

57-
settings.AgentName = "thisiskindofalongrunnername12";
58+
settings.AgentName = "thisiskindofalongrunnernabcde";
5859
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
5960
settings.GitHubUrl = "https://github.com/myorganizationexample/myrepoexample";
6061

@@ -82,88 +83,129 @@ public void CalculateServiceName80Chars()
8283
Assert.Equal("actions", serviceNameParts[0]);
8384
Assert.Equal("runner", serviceNameParts[1]);
8485
Assert.Equal("myorganizationexample-myrepoexample", serviceNameParts[2]); // '/' has been replaced with '-'
85-
Assert.Equal("thisiskindofalongrunnername12", serviceNameParts[3]);
86+
Assert.Equal("thisiskindofalongrunnernabcde", serviceNameParts[3]); // should not have random numbers unless we exceed 80
8687
}
8788
}
8889

89-
[Fact]
90-
[Trait("Level", "L0")]
91-
[Trait("Category", "Service")]
92-
public void CalculateServiceNameLimitsServiceNameTo80Chars()
93-
{
94-
RunnerSettings settings = new RunnerSettings();
95-
96-
settings.AgentName = "thisisareallyreallylongbutstillvalidagentname";
97-
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
98-
settings.GitHubUrl = "https://github.com/myreallylongorganizationexample/myreallylongrepoexample";
99-
100-
string serviceNamePattern = "actions.runner.{0}.{1}";
101-
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
102-
103-
using (TestHostContext hc = CreateTestContext())
90+
#if OS_WINDOWS
91+
[Fact]
92+
[Trait("Level", "L0")]
93+
[Trait("Category", "Service")]
94+
public void CalculateServiceNameLimitsServiceNameTo80Chars()
10495
{
105-
ServiceControlManager scm = new ServiceControlManager();
106-
107-
scm.Initialize(hc);
108-
scm.CalculateServiceName(
109-
settings,
110-
serviceNamePattern,
111-
serviceDisplayNamePattern,
112-
out string serviceName,
113-
out string serviceDisplayName);
114-
115-
// Verify name has been shortened to 80 characters
116-
Assert.Equal(80, serviceName.Length);
117-
118-
var serviceNameParts = serviceName.Split('.');
119-
120-
// Verify that each component has been shortened to a sensible length
121-
Assert.Equal("actions", serviceNameParts[0]); // Never shortened
122-
Assert.Equal("runner", serviceNameParts[1]); // Never shortened
123-
Assert.Equal("myreallylongorganizationexample-myreallylongr", serviceNameParts[2]); // First 45 chars, '/' has been replaced with '-'
124-
Assert.Equal("thisisareallyreally", serviceNameParts[3]); // Remainder of unused chars
96+
RunnerSettings settings = new RunnerSettings();
97+
98+
settings.AgentName = "thisisareallyreallylongbutstillvalidagentname";
99+
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
100+
settings.GitHubUrl = "https://github.com/myreallylongorganizationexample/myreallylongrepoexample";
101+
102+
string serviceNamePattern = "actions.runner.{0}.{1}";
103+
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
104+
105+
using (TestHostContext hc = CreateTestContext())
106+
{
107+
ServiceControlManager scm = new ServiceControlManager();
108+
109+
scm.Initialize(hc);
110+
scm.CalculateServiceName(
111+
settings,
112+
serviceNamePattern,
113+
serviceDisplayNamePattern,
114+
out string serviceName,
115+
out string serviceDisplayName);
116+
117+
// Verify name has been shortened to 80 characters
118+
Assert.Equal(80, serviceName.Length);
119+
120+
var serviceNameParts = serviceName.Split('.');
121+
122+
// Verify that each component has been shortened to a sensible length
123+
Assert.Equal("actions", serviceNameParts[0]); // Never shortened
124+
Assert.Equal("runner", serviceNameParts[1]); // Never shortened
125+
Assert.Equal("myreallylongorganizationexample-myreallylongr", serviceNameParts[2]); // First 45 chars, '/' has been replaced with '-'
126+
Assert.Matches(@"^(thisisareallyr-[0-9]{4})$", serviceNameParts[3]); // Remainder of unused chars, 4 random numbers added at the end
127+
}
125128
}
126-
}
127-
128-
// Special 'defensive' test that verifies we can gracefully handle creating service names
129-
// in case github.com changes its org/repo naming convention in the future,
130-
// and some of these characters may be invalid for service names
131-
// Not meant to test character set exhaustively -- it's just here to exercise the sanitizing logic
132-
[Fact]
133-
[Trait("Level", "L0")]
134-
[Trait("Category", "Service")]
135-
public void CalculateServiceNameSanitizeOutOfRangeChars()
136-
{
137-
RunnerSettings settings = new RunnerSettings();
138-
139-
settings.AgentName = "name";
140-
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
141-
settings.GitHubUrl = "https://github.com/org!@$*+[]()/repo!@$*+[]()";
142129

143-
string serviceNamePattern = "actions.runner.{0}.{1}";
144-
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
145-
146-
using (TestHostContext hc = CreateTestContext())
130+
// Special 'defensive' test that verifies we can gracefully handle creating service names
131+
// in case github.com changes its org/repo naming convention in the future,
132+
// and some of these characters may be invalid for service names
133+
// Not meant to test character set exhaustively -- it's just here to exercise the sanitizing logic
134+
[Fact]
135+
[Trait("Level", "L0")]
136+
[Trait("Category", "Service")]
137+
public void CalculateServiceNameSanitizeOutOfRangeChars()
147138
{
148-
ServiceControlManager scm = new ServiceControlManager();
149-
150-
scm.Initialize(hc);
151-
scm.CalculateServiceName(
152-
settings,
153-
serviceNamePattern,
154-
serviceDisplayNamePattern,
155-
out string serviceName,
156-
out string serviceDisplayName);
157-
158-
var serviceNameParts = serviceName.Split('.');
159-
160-
// Verify service name parts are sanitized correctly
161-
Assert.Equal("actions", serviceNameParts[0]);
162-
Assert.Equal("runner", serviceNameParts[1]);
163-
Assert.Equal("org----------repo---------", serviceNameParts[2]); // Chars replaced with '-'
164-
Assert.Equal("name", serviceNameParts[3]);
139+
RunnerSettings settings = new RunnerSettings();
140+
141+
settings.AgentName = "name";
142+
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
143+
settings.GitHubUrl = "https://github.com/org!@$*+[]()/repo!@$*+[]()";
144+
145+
string serviceNamePattern = "actions.runner.{0}.{1}";
146+
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
147+
148+
using (TestHostContext hc = CreateTestContext())
149+
{
150+
ServiceControlManager scm = new ServiceControlManager();
151+
152+
scm.Initialize(hc);
153+
scm.CalculateServiceName(
154+
settings,
155+
serviceNamePattern,
156+
serviceDisplayNamePattern,
157+
out string serviceName,
158+
out string serviceDisplayName);
159+
160+
var serviceNameParts = serviceName.Split('.');
161+
162+
// Verify service name parts are sanitized correctly
163+
Assert.Equal("actions", serviceNameParts[0]);
164+
Assert.Equal("runner", serviceNameParts[1]);
165+
Assert.Equal("org----------repo---------", serviceNameParts[2]); // Chars replaced with '-'
166+
Assert.Equal("name", serviceNameParts[3]);
167+
}
165168
}
166-
}
169+
#else
170+
[Fact]
171+
[Trait("Level", "L0")]
172+
[Trait("Category", "Service")]
173+
public void CalculateServiceNameLimitsServiceNameTo150Chars()
174+
{
175+
RunnerSettings settings = new RunnerSettings();
176+
177+
settings.AgentName = "thisisareallyreallylongbutstillvalidagentnameiamusingforthisexampletotestverylongnamelimits";
178+
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
179+
settings.GitHubUrl = "https://github.com/myreallylongorganizationexampleonlinux/myreallylongrepoexampleonlinux1234";
180+
181+
string serviceNamePattern = "actions.runner.{0}.{1}";
182+
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
183+
184+
using (TestHostContext hc = CreateTestContext())
185+
{
186+
ServiceControlManager scm = new ServiceControlManager();
187+
188+
scm.Initialize(hc);
189+
scm.CalculateServiceName(
190+
settings,
191+
serviceNamePattern,
192+
serviceDisplayNamePattern,
193+
out string serviceName,
194+
out string serviceDisplayName);
195+
196+
// Verify name has been shortened to 150
197+
Assert.Equal(150, serviceName.Length);
198+
199+
var serviceNameParts = serviceName.Split('.');
200+
201+
// Verify that each component has been shortened to a sensible length
202+
Assert.Equal("actions", serviceNameParts[0]); // Never shortened
203+
Assert.Equal("runner", serviceNameParts[1]); // Never shortened
204+
Assert.Equal("myreallylongorganizationexampleonlinux-myreallylongrepoexampleonlinux1", serviceNameParts[2]); // First 70 chars, '/' has been replaced with '-'
205+
Assert.Matches(@"^(thisisareallyreallylongbutstillvalidagentnameiamusingforthi-[0-9]{4})$", serviceNameParts[3]);
206+
}
207+
}
208+
#endif
167209

168210
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
169211
{

0 commit comments

Comments
 (0)