Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e737293
refactor(compute-providers): isolate EC2 provider handling
edersonbrilhante Aug 6, 2026
a4ad8f5
refactor(compute-providers): resolve provider types strictly
edersonbrilhante Aug 6, 2026
b6084a3
refactor(compute-providers): centralize dynamic label selection
edersonbrilhante Aug 12, 2026
4db3888
test(compute-providers): cover dynamic label selection
edersonbrilhante Aug 14, 2026
383d921
test(compute-providers): share webhook provider contract
edersonbrilhante Aug 14, 2026
98e1597
refactor(compute-providers): simplify provider label filtering
edersonbrilhante Aug 14, 2026
a301a7d
test(compute-providers): cover disabled dynamic labels
edersonbrilhante Aug 14, 2026
3602f48
test(compute-providers): cover AWS dynamic label policy
edersonbrilhante Aug 14, 2026
ac35170
test(compute-providers): cover restricted AWS policy
edersonbrilhante Aug 14, 2026
b38c721
feat(compute-providers): add MicroVM API foundations
edersonbrilhante Aug 6, 2026
7bd9656
feat(compute-providers): add MicroVM control-plane provider
edersonbrilhante Aug 6, 2026
a8d59f6
feat(compute-providers): add MicroVM webhook routing
edersonbrilhante Aug 6, 2026
979c88d
docs(compute-providers): document Lambda MicroVM provider
edersonbrilhante Aug 6, 2026
f10a155
fix(compute-providers): replace unsupported MicroVM tags
edersonbrilhante Aug 19, 2026
a000a3f
fix(compute-providers): make metadata cleanup idempotent
edersonbrilhante Aug 19, 2026
9bf444e
fix(compute-providers): remove MicroVM duration label
edersonbrilhante Aug 19, 2026
fbf3556
fix(compute-providers): fix MicroVM lifetime at eight hours
edersonbrilhante Aug 20, 2026
2b086a8
feat(microvm): tag runner metadata
edersonbrilhante Aug 21, 2026
7b9f2e7
feat(microvm): add runner config ARN to hook payload
edersonbrilhante Aug 21, 2026
00e06ab
fix(microvm): reuse runner configuration path
edersonbrilhante Aug 21, 2026
a63113c
feat(microvm): extend runner lifecycle metadata
edersonbrilhante Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lambdas/functions/control-plane/src/pool/pool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ describe('Test simple pool.', () => {
});

it('Rejects unsupported pool provider types.', async () => {
await expect(adjust({ poolSize: 10, type: 'microvm' })).rejects.toThrow(
"Unsupported compute provider type 'microvm'",
await expect(adjust({ poolSize: 10, type: 'unsupported-provider' })).rejects.toThrow(
"Unsupported compute provider type 'unsupported-provider'",
);
expect(mockListRunners).not.toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { putParameter } from '@aws-github-runner/aws-ssm-util';
import type { Octokit } from '@octokit/rest';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { createStartRunnerConfig } from './github-runner';
import type { CreateGitHubRunnerConfig } from './types';

vi.mock('@aws-github-runner/aws-ssm-util', () => ({
getParameter: vi.fn(),
putParameter: vi.fn(),
}));

const githubRunnerConfig: CreateGitHubRunnerConfig = {
disableAutoUpdate: true,
enableJitConfig: true,
ephemeral: true,
runnerGroup: 'Default',
runnerLabels: 'self-hosted,linux',
runnerNamePrefix: 'runner-',
runnerOwner: 'octocat/runner',
runnerType: 'Repo',
ssmConfigPath: '/github-action-runners/test/config',
ssmParameterStoreTags: [],
ssmTokenPath: '/github-action-runners/test/tokens',
};

const generateRunnerJitconfigForRepo = vi.fn();
const githubClient = {
actions: { generateRunnerJitconfigForRepo },
} as unknown as Octokit;

beforeEach(() => {
vi.clearAllMocks();
vi.mocked(putParameter).mockResolvedValue();
generateRunnerJitconfigForRepo.mockResolvedValue({
data: {
encoded_jit_config: 'encoded-jit-config',
runner: { id: 42 },
},
headers: {},
});
});

describe('createStartRunnerConfig', () => {
it('persists JIT configuration before notifying the provider', async () => {
const onJitConfigCreated = vi.fn(async () => {
expect(putParameter).toHaveBeenCalledWith(
'/github-action-runners/test/tokens/microvm-1',
'encoded-jit-config',
true,
{ tags: [] },
);
});

await expect(
createStartRunnerConfig(githubRunnerConfig, ['microvm-1'], githubClient, { onJitConfigCreated }),
).resolves.toEqual([]);
expect(onJitConfigCreated).toHaveBeenCalledWith('microvm-1', {
githubRunnerId: '42',
runnerLabels: ['self-hosted', 'linux'],
});
});

it('reports provider post-write fencing failures while leaving cleanup to the provider', async () => {
const onJitConfigCreated = vi.fn().mockRejectedValue(new Error('cleanup already requested'));

await expect(
createStartRunnerConfig(githubRunnerConfig, ['microvm-1'], githubClient, { onJitConfigCreated }),
).resolves.toEqual(['microvm-1']);
expect(putParameter).toHaveBeenCalledOnce();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ function addDelay(runnerIds: string[]) {
return { isDelay, delay };
}

function mergeSsmParameterTags(
configuredTags: CreateGitHubRunnerConfig['ssmParameterStoreTags'],
providerTags: CreateGitHubRunnerConfig['ssmParameterStoreTags'],
): CreateGitHubRunnerConfig['ssmParameterStoreTags'] {
const tagsByKey = new Map(configuredTags.map(({ Key, Value }) => [Key, Value]));
for (const { Key, Value } of providerTags) tagsByKey.set(Key, Value);
return [...tagsByKey].map(([Key, Value]) => ({ Key, Value }));
}

/**
* Creates registration token configuration for non-ephemeral runners.
*
Expand All @@ -285,7 +294,10 @@ async function createRegistrationTokenConfig(

for (const runnerId of runnerIds) {
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${runnerId}`, runnerServiceConfig.join(' '), true, {
tags: [...(options.getSsmParameterTags?.(runnerId) ?? []), ...githubRunnerConfig.ssmParameterStoreTags],
tags: mergeSsmParameterTags(
githubRunnerConfig.ssmParameterStoreTags,
options.getSsmParameterTags?.(runnerId) ?? [],
),
});
if (isDelay) {
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
Expand Down Expand Up @@ -342,17 +354,19 @@ async function createJitConfig(

metricGitHubAppRateLimit(runnerConfig.headers, githubRunnerConfig.appIndex);

await options.onJitConfigCreated?.(runnerId, {
githubRunnerId: runnerConfig.data.runner.id.toString(),
runnerLabels,
});

// store jit config in ssm parameter store
logger.debug('Runner JIT config for ephemeral runner generated.', {
instance: runnerId,
});
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${runnerId}`, runnerConfig.data.encoded_jit_config, true, {
tags: [...(options.getSsmParameterTags?.(runnerId) ?? []), ...githubRunnerConfig.ssmParameterStoreTags],
tags: mergeSsmParameterTags(
githubRunnerConfig.ssmParameterStoreTags,
options.getSsmParameterTags?.(runnerId) ?? [],
),
});
await options.onJitConfigCreated?.(runnerId, {
githubRunnerId: runnerConfig.data.runner.id.toString(),
runnerLabels,
});
if (isDelay) {
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,25 @@ describe('scaleUp with GHES', () => {
});
});

it.each([true, false])(
'keeps the provider runner identity tag authoritative for ephemeral=%s',
async (ephemeral) => {
process.env.ENABLE_EPHEMERAL_RUNNERS = String(ephemeral);
process.env.RUNNERS_MAXIMUM_COUNT = '2';
process.env.SSM_PARAMETER_STORE_TAGS = JSON.stringify([
{ Key: 'RunnerId', Value: 'configured-value-cannot-win' },
{ Key: 'CostCenter', Value: '1234' },
]);

await scaleUpModule.scaleUp(TEST_DATA);

expect(mockSSMClient.commandCalls(PutParameterCommand)[0].args[0].input.Tags).toEqual([
{ Key: 'RunnerId', Value: 'i-12345' },
{ Key: 'CostCenter', Value: '1234' },
]);
},
);

it('quotes runner labels with semicolon separators in non-ephemeral runner config', async () => {
process.env.ENABLE_EPHEMERAL_RUNNERS = 'false';
process.env.RUNNERS_MAXIMUM_COUNT = '2';
Expand Down Expand Up @@ -2157,9 +2176,11 @@ describe('compute provider selection', () => {
});

it('rejects unsupported scale-up provider types', async () => {
process.env.COMPUTE_PROVIDER_TYPE = 'microvm';
process.env.COMPUTE_PROVIDER_TYPE = 'unsupported-provider';

await expect(scaleUpModule.scaleUp(TEST_DATA)).rejects.toThrow("Unsupported compute provider type 'microvm'");
await expect(scaleUpModule.scaleUp(TEST_DATA)).rejects.toThrow(
"Unsupported compute provider type 'unsupported-provider'",
);
expect(mockedAppAuth).not.toHaveBeenCalled();
});
});
Expand Down

This file was deleted.

This file was deleted.

29 changes: 0 additions & 29 deletions lambdas/functions/webhook/src/runners/aws-dynamic-labels.ts

This file was deleted.

Loading