Skip to content

Commit 1fc78c4

Browse files
refactor(runner-providers): resolve provider types strictly
1 parent 527e07f commit 1fc78c4

4 files changed

Lines changed: 29 additions & 72 deletions

File tree

lambdas/libs/runner-providers/provider-types.test.ts

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,28 @@
11
import { describe, expect, it } from 'vitest';
22

3-
import {
4-
defaultRunnerProvider,
5-
normalizeRunnerProviderType,
6-
resolveRunnerProviderType,
7-
runnerProviderTypes,
8-
} from './provider-types';
3+
import { defaultRunnerProvider, resolveRunnerProviderType, runnerProviderTypes } from './provider-types';
4+
5+
const defaultProviderInputs = [undefined, '', ' '] as const;
6+
const supportedProviderCases = runnerProviderTypes.flatMap(
7+
(provider) =>
8+
[
9+
[provider, provider],
10+
[` ${provider.toUpperCase()} `, provider],
11+
] as const,
12+
);
913

1014
describe('runner provider configuration', () => {
1115
it('defines an explicit default provider', () => {
1216
expect(runnerProviderTypes).toContain(defaultRunnerProvider);
1317
});
1418
});
1519

16-
describe('runner provider normalization', () => {
17-
it.each([
18-
[undefined, 'ec2'],
19-
['', 'ec2'],
20-
[' ', 'ec2'],
21-
[' EC2 ', 'ec2'],
22-
])('normalizes provider type %j to %j', (type, expected) => {
23-
expect(normalizeRunnerProviderType(type)).toBe(expected);
20+
describe('runner provider resolution', () => {
21+
it.each(defaultProviderInputs)('resolves default provider input %j', (type) => {
22+
expect(resolveRunnerProviderType(type)).toBe(defaultRunnerProvider);
2423
});
2524

26-
it.each([[' Unknown '], ['unsupported-provider'], [null], [1]])(
27-
'returns undefined for unsupported provider type %j',
28-
(type) => {
29-
expect(normalizeRunnerProviderType(type)).toBeUndefined();
30-
},
31-
);
32-
});
33-
34-
describe('runner provider resolution', () => {
35-
it.each([
36-
[undefined, 'ec2'],
37-
['', 'ec2'],
38-
[' ', 'ec2'],
39-
[' EC2 ', 'ec2'],
40-
])('resolves provider type %j to %j', (type, expected) => {
25+
it.each(supportedProviderCases)('resolves provider type %j to %j', (type, expected) => {
4126
expect(resolveRunnerProviderType(type)).toBe(expected);
4227
});
4328

lambdas/libs/runner-providers/provider-types.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@ export type RunnerProviderType = (typeof runnerProviderTypes)[number];
44

55
export const defaultRunnerProvider = 'ec2' satisfies RunnerProviderType;
66

7-
export function normalizeRunnerProviderType(type: unknown): RunnerProviderType | undefined {
7+
export function resolveRunnerProviderType(type: unknown): RunnerProviderType {
88
if (type === undefined) return defaultRunnerProvider;
9-
if (typeof type !== 'string') return undefined;
9+
if (typeof type !== 'string') {
10+
throw new Error(`Unsupported runner provider type '${String(type)}'`);
11+
}
1012

1113
const normalizedType = type.trim().toLowerCase();
1214
if (!normalizedType) return defaultRunnerProvider;
1315

14-
return runnerProviderTypes.find((runnerProviderType) => runnerProviderType === normalizedType);
15-
}
16-
17-
export function resolveRunnerProviderType(type: unknown): RunnerProviderType {
18-
const normalizedType = normalizeRunnerProviderType(type);
19-
if (!normalizedType) {
16+
const runnerProviderType = runnerProviderTypes.find((provider) => provider === normalizedType);
17+
if (!runnerProviderType) {
2018
throw new Error(`Unsupported runner provider type '${String(type)}'`);
2119
}
2220

23-
return normalizedType;
21+
return runnerProviderType;
2422
}

lambdas/libs/runner-providers/webhook.test.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,13 @@ describe('selectDynamicLabelQueue', () => {
2424
});
2525
});
2626

27-
it('skips an unsupported provider strategy and selects the next supported queue', () => {
28-
const unsupportedQueue = runnerQueue('unsupported-provider');
29-
(unsupportedQueue as unknown as { runnerProvider: string }).runnerProvider = 'unsupported';
30-
const ec2Queue = runnerQueue('ec2');
27+
it.each([['unsupported'], [42]])('throws for unsupported runner provider %j', (runnerProvider) => {
28+
const queue = runnerQueue('unsupported-provider');
29+
(queue as unknown as { runnerProvider: unknown }).runnerProvider = runnerProvider;
3130

32-
expect(
33-
selectDynamicLabelQueue(
34-
[unsupportedQueue, ec2Queue],
35-
['self-hosted', 'linux'],
36-
['ghr-ec2-instance-type:t3.large'],
37-
),
38-
).toEqual({
39-
queue: ec2Queue,
40-
labels: ['self-hosted', 'linux', 'ghr-ec2-instance-type:t3.large'],
41-
});
42-
});
43-
44-
it('rejects a malformed non-string runner provider without throwing', () => {
45-
const queue = runnerQueue('malformed-provider');
46-
(queue as unknown as { runnerProvider: number }).runnerProvider = 42;
47-
48-
expect(
31+
expect(() =>
4932
selectDynamicLabelQueue([queue], ['self-hosted', 'linux'], ['ghr-ec2-instance-type:t3.large']),
50-
).toBeUndefined();
33+
).toThrow(`Unsupported runner provider type '${String(runnerProvider)}'`);
5134
});
5235
});
5336

lambdas/libs/runner-providers/webhook.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { createChildLogger } from '@aws-github-runner/aws-powertools-util';
2-
31
import { createRunnerProviderRegistry } from './core';
42

53
import type { DynamicLabelDispatchTarget, RunnerMatcherConfig, WebhookProviderCapabilities } from './contracts';
6-
import { normalizeRunnerProviderType } from './provider-types';
4+
import { resolveRunnerProviderType } from './provider-types';
75
import { enabledWebhookProviders } from './providers.config.webhook';
86

9-
const logger = createChildLogger('runner-provider-webhook');
10-
117
export const webhookProviderRegistry = createRunnerProviderRegistry<WebhookProviderCapabilities>(
128
enabledWebhookProviders.map((provider) => provider.createPlugin()),
139
);
@@ -18,13 +14,8 @@ export function selectDynamicLabelQueue(
1814
sanitizedGhrLabels: string[],
1915
): DynamicLabelDispatchTarget | undefined {
2016
for (const queue of matches) {
21-
const provider = normalizeRunnerProviderType(queue.runnerProvider);
22-
const dynamicLabels = provider ? webhookProviderRegistry.capability(provider, 'dynamicLabels') : undefined;
23-
24-
if (!dynamicLabels) {
25-
logger.warn(`Queue ${queue.id} has unsupported runner provider '${provider ?? String(queue.runnerProvider)}'`);
26-
continue;
27-
}
17+
const provider = resolveRunnerProviderType(queue.runnerProvider);
18+
const dynamicLabels = webhookProviderRegistry.capability(provider, 'dynamicLabels');
2819

2920
const target = dynamicLabels.selectQueue({ queue, nonGhrLabels, sanitizedGhrLabels });
3021
if (target) return target;

0 commit comments

Comments
 (0)