Skip to content

Commit 8650bc1

Browse files
committed
Add the ability to add services for GitHub runner
1 parent 446da4e commit 8650bc1

File tree

3 files changed

+70
-15
lines changed

3 files changed

+70
-15
lines changed

packages/k8s/src/hooks/prepare-job.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ import {
3434
SCRIPT_EXECUTOR_ENTRY_POINT,
3535
SCRIPT_EXECUTOR_ENTRY_POINT_ARGS,
3636
getNumberOfHost,
37-
sleep
37+
sleep,
38+
generateServicesName
3839
} from '../k8s/utils'
3940
import {
4041
CONTAINER_EXTENSION_PREFIX,
@@ -68,6 +69,7 @@ export async function prepareJob(
6869

6970
let services: k8s.V1Container[] = []
7071
if (args.services?.length) {
72+
generateServicesName(args.services)
7173
services = args.services.map(service => {
7274
core.debug(`Adding service '${service.image}' to pod definition`)
7375
return createContainerSpec(
@@ -288,19 +290,19 @@ export function createContainerSpec(
288290
if (!container.entryPoint && jobContainer) {
289291
container.entryPoint = DEFAULT_CONTAINER_ENTRY_POINT
290292
container.entryPointArgs = DEFAULT_CONTAINER_ENTRY_POINT_ARGS
291-
}
292293

293-
if (useScriptExecutor()) {
294-
core.debug('starting script executor server')
295-
// Starting the server.
296-
container.entryPoint =
297-
process.env['ACTIONS_RUNNER_SCRIPT_EXECUTOR_ENTRY_POINT'] ||
298-
SCRIPT_EXECUTOR_ENTRY_POINT
299-
container.entryPointArgs = process.env[
300-
'ACTIONS_RUNNER_SCRIPT_EXECUTOR_ARGS'
301-
]
302-
? process.env['ACTIONS_RUNNER_SCRIPT_EXECUTOR_ARGS'].split(' ')
303-
: SCRIPT_EXECUTOR_ENTRY_POINT_ARGS
294+
if (useScriptExecutor()) {
295+
core.debug('starting script executor server')
296+
// Starting the server.
297+
container.entryPoint =
298+
process.env['ACTIONS_RUNNER_SCRIPT_EXECUTOR_ENTRY_POINT'] ||
299+
SCRIPT_EXECUTOR_ENTRY_POINT
300+
container.entryPointArgs = process.env[
301+
'ACTIONS_RUNNER_SCRIPT_EXECUTOR_ARGS'
302+
]
303+
? process.env['ACTIONS_RUNNER_SCRIPT_EXECUTOR_ARGS'].split(' ')
304+
: SCRIPT_EXECUTOR_ENTRY_POINT_ARGS
305+
}
304306
}
305307

306308
const podContainer = {

packages/k8s/src/k8s/utils.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export function writeEntryPointScript(
197197
}
198198

199199
export function generateContainerName(image: string): string {
200-
const nameWithTag = image.split('/').pop()
200+
const nameWithTag = image.replace('_', '-').split('/').pop()
201201
const name = nameWithTag?.split(':').at(0)
202202

203203
if (!name) {
@@ -263,6 +263,27 @@ export function mergePodSpecWithOptions(
263263
}
264264
}
265265

266+
// If there are multiple service containers with the same image name, append a number
267+
// to uniquely identify them. Otherwise we won't be able to create it.
268+
export function generateServicesName(
269+
services: { [key: string]: string }[]
270+
): void {
271+
const servicesSeen: { [key: string]: number } = {}
272+
for (const service of services) {
273+
if (servicesSeen[service.image] === undefined) {
274+
servicesSeen[service.image] = 0
275+
service.name = generateContainerName(service.image)
276+
continue
277+
}
278+
servicesSeen[service.image] += 1
279+
service.name = `${generateContainerName(service.image)}-${
280+
servicesSeen[service.image]
281+
}`
282+
}
283+
284+
core.debug(`services are ${JSON.stringify(services)}`)
285+
}
286+
266287
export function mergeObjectMeta(
267288
base: { metadata?: k8s.V1ObjectMeta },
268289
from: k8s.V1ObjectMeta

packages/k8s/tests/k8s-utils-test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
ENV_HOOK_TEMPLATE_PATH,
1212
createScriptExecutorContainer,
1313
getNumberOfHost,
14-
ENV_NUMBER_OF_HOSTS
14+
ENV_NUMBER_OF_HOSTS,
15+
generateServicesName
1516
} from '../src/k8s/utils'
1617
import * as k8s from '@kubernetes/client-node'
1718
import { TestHelper } from './test-setup'
@@ -344,6 +345,12 @@ describe('k8s utils', () => {
344345
)
345346
})
346347

348+
it('should replace - with _', () => {
349+
expect(
350+
generateContainerName('public.ecr.aws/localstack/local_stack')
351+
).toEqual('local-stack')
352+
})
353+
347354
it('should throw on invalid image string', () => {
348355
expect(() =>
349356
generateContainerName('localstack/localstack/:latest')
@@ -352,6 +359,31 @@ describe('k8s utils', () => {
352359
})
353360
})
354361

362+
describe('generateServicesName', () => {
363+
it('should generate services name for multiple identical image', () => {
364+
const services = [
365+
{
366+
image: 'foo'
367+
},
368+
{
369+
image: 'foo'
370+
}
371+
]
372+
generateServicesName(services)
373+
expect.arrayContaining([
374+
expect.objectContaining({
375+
name: 'commonName',
376+
value: CertCommonName.ROOT
377+
})
378+
])
379+
380+
expect(services).toEqual([
381+
{ image: 'foo', name: 'foo' },
382+
{ image: 'foo', name: 'foo-1' }
383+
])
384+
})
385+
})
386+
355387
describe('create script executor container', () => {
356388
it('should install script executor at the volume mount location', () => {
357389
const executorVolumeMount = new k8s.V1VolumeMount()

0 commit comments

Comments
 (0)