Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const githubClient = {

const cleanEnv = process.env;

const lanes = providerTypes.map((type) => ({
const computeProviders = providerTypes.map((type) => ({
provider: {
type,
listRunners: vi.fn(),
Expand Down Expand Up @@ -68,7 +68,7 @@ beforeEach(() => {

definePoolContractTests<RunnerProviderType>({
adjust,
computeProviders,
githubInstallationClient: githubClient,
lanes,
resolveCapability: mockedResolveCapability,
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const mockedResolveCapability = vi.spyOn(controlPlaneProviderRegistry, 'capabili

const cleanEnv = process.env;

const lanes = providerTypes.map((type) => ({
const computeProviders = providerTypes.map((type) => ({
provider: {
type,
list: vi.fn(),
Expand All @@ -28,7 +28,7 @@ beforeEach(() => {
});

defineScaleDownContractTests<RunnerProviderType>({
lanes,
computeProviders,
resolveCapability: mockedResolveCapability,
scaleDown,
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ const payloads: ActionRequestMessageSQS[] = [

const cleanEnv = process.env;

const lanes = providerTypes.map((type) => ({
const computeProviders = providerTypes.map((type) => ({
provider: {
type,
prepareGroup: vi.fn(),
getCurrentRunners: vi.fn(),
createRunners: vi.fn(),
} satisfies ScaleUpRunnerProvider,
state: { lane: type },
state: { computeProvider: type },
}));

beforeEach(() => {
Expand All @@ -76,9 +76,9 @@ beforeEach(() => {
});

defineScaleUpContractTests({
computeProviders,
createPayloads: () => structuredClone(payloads),
githubInstallationClient: githubClient,
lanes,
resolveCapability: mockedResolveCapability,
scaleUp,
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ import type { PoolRunnerProvider } from '../../pool/pool-provider';

type TestPoolProvider<TType extends string> = Omit<PoolRunnerProvider, 'type'> & { type: TType };

export interface PoolContractLane<TType extends string> {
export interface PoolContractProvider<TType extends string> {
provider: TestPoolProvider<TType>;
}

interface PoolContractOptions<TType extends string> {
adjust: (event: PoolEvent) => Promise<void>;
githubInstallationClient: Octokit;
lanes: readonly PoolContractLane<TType>[];
computeProviders: readonly PoolContractProvider<TType>[];
resolveCapability: MockInstance<(type: TType, capability: 'pool') => () => Omit<TestPoolProvider<TType>, 'type'>>;
}

export function definePoolContractTests<TType extends string>({
adjust,
computeProviders,
githubInstallationClient,
lanes,
resolveCapability,
}: PoolContractOptions<TType>): void {
describe.each(lanes.map((lane) => [lane.provider.type, lane] as const))(
describe.each(computeProviders.map((computeProvider) => [computeProvider.provider.type, computeProvider] as const))(
'%s pool orchestration contract',
(_, { provider }) => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ import type { ScaleDownRunnerProvider } from '../../scale-runners/scale-down-pro

type TestScaleDownProvider<TType extends string> = Omit<ScaleDownRunnerProvider, 'type'> & { type: TType };

export interface ScaleDownContractLane<TType extends string> {
export interface ScaleDownContractProvider<TType extends string> {
provider: TestScaleDownProvider<TType>;
}

interface ScaleDownContractOptions<TType extends string> {
lanes: readonly ScaleDownContractLane<TType>[];
computeProviders: readonly ScaleDownContractProvider<TType>[];
resolveCapability: MockInstance<
(type: TType, capability: 'scaleDown') => () => Omit<TestScaleDownProvider<TType>, 'type'>
>;
scaleDown: () => Promise<void>;
}

export function defineScaleDownContractTests<TType extends string>({
lanes,
computeProviders,
resolveCapability,
scaleDown,
}: ScaleDownContractOptions<TType>): void {
describe.each(lanes.map((lane) => [lane.provider.type, lane] as const))(
describe.each(computeProviders.map((computeProvider) => [computeProvider.provider.type, computeProvider] as const))(
'%s scale-down orchestration contract',
(_, { provider }) => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import type { ActionRequestMessageSQS } from '../../scale-runners/types';

type TestScaleUpProvider<TType extends string> = Omit<ScaleUpRunnerProvider, 'type'> & { type: TType };

export interface ScaleUpContractLane<TType extends string> {
export interface ScaleUpContractProvider<TType extends string> {
provider: TestScaleUpProvider<TType>;
state: unknown;
}

interface ScaleUpContractOptions<TType extends string> {
createPayloads: () => ActionRequestMessageSQS[];
computeProviders: readonly ScaleUpContractProvider<TType>[];
githubInstallationClient: Octokit;
lanes: readonly ScaleUpContractLane<TType>[];
resolveCapability: MockInstance<
(type: TType, capability: 'scaleUp') => () => Omit<TestScaleUpProvider<TType>, 'type'>
>;
Expand All @@ -28,13 +28,13 @@ const createResult = {
};

export function defineScaleUpContractTests<TType extends string>({
computeProviders,
createPayloads,
githubInstallationClient,
lanes,
resolveCapability,
scaleUp,
}: ScaleUpContractOptions<TType>): void {
describe.each(lanes.map((lane) => [lane.provider.type, lane] as const))(
describe.each(computeProviders.map((computeProvider) => [computeProvider.provider.type, computeProvider] as const))(
'%s scale-up orchestration contract',
(_, { provider, state }) => {
beforeEach(() => {
Expand All @@ -48,14 +48,14 @@ export function defineScaleUpContractTests<TType extends string>({
vi.mocked(provider.createRunners).mockResolvedValue(createResult);
});

it('forwards the prepared lane state through runner lookup and creation', async () => {
it('forwards the prepared compute-provider state through runner lookup and creation', async () => {
const payloads = createPayloads();
payloads[0].labels = ['lane-label'];
payloads[0].labels = ['compute-provider-label'];

await scaleUp(payloads);

expect(resolveCapability).toHaveBeenCalledWith(provider.type, 'scaleUp');
expect(provider.prepareGroup).toHaveBeenCalledWith(['lane-label']);
expect(provider.prepareGroup).toHaveBeenCalledWith(['compute-provider-label']);
expect(provider.getCurrentRunners).toHaveBeenCalledWith(state, {
runnerOwner: payloads[0].repositoryOwner,
runnerType: 'Org',
Expand All @@ -69,7 +69,7 @@ export function defineScaleUpContractTests<TType extends string>({
);
});

it('does not query current runners when the lane has unlimited capacity', async () => {
it('does not query current runners when the compute provider has unlimited capacity', async () => {
process.env.RUNNERS_MAXIMUM_COUNT = '-1';
const payloads = createPayloads();
payloads.push({ ...payloads[0], id: 2, messageId: 'message-2' });
Expand All @@ -80,7 +80,7 @@ export function defineScaleUpContractTests<TType extends string>({
expect(provider.createRunners).toHaveBeenCalledWith(expect.objectContaining({ numberOfRunners: 2 }));
});

it('does not create runners when the lane has reached maximum capacity', async () => {
it('does not create runners when the compute provider has reached maximum capacity', async () => {
process.env.RUNNERS_MAXIMUM_COUNT = '1';
vi.mocked(provider.getCurrentRunners).mockResolvedValue(1);

Expand Down
8 changes: 4 additions & 4 deletions lambdas/libs/runner-providers/templates/provider/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Runner provider template

Copy this directory to the appropriate provider namespace, for example
`aws/codebuild`, and replace `template` with the new lane type.
`aws/codebuild`, and replace `template` with the new compute-provider type.

The template is compile-checked but intentionally not registered. A provider
has separate webhook and control-plane entry points so each Lambda bundles only
the code it uses. To enable a completed provider, add its lane type to
the code it uses. To enable a completed provider, add its compute-provider type to
`provider-types.ts`, then register each entry point in its matching file:

- `providers.config.webhook.ts`
- `providers.config.control-plane.ts`

Each entry point exports its module as `provider`. Alias that export to the lane
Each entry point exports its module as `provider`. Alias that export to the compute-provider
name when enabling it, for example:

```ts
Expand All @@ -21,7 +21,7 @@ import { provider as codebuild } from './aws/codebuild/webhook';
Implement every capability before registering the provider:

- `pool`: list managed runners, count available runners, and create runners.
- `scaleUp`: prepare lane state, count current runners, and create runners.
- `scaleUp`: prepare compute-provider state, count current runners, and create runners.
- `scaleDown`: list, inspect, mark, unmark, and terminate runners.
- `dynamicLabels`: select a webhook dispatch target for supported labels.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { expect, it, vi } from 'vitest';
import { provider as controlPlaneProvider } from './control-plane';
import { provider as webhookProvider } from './webhook';

it('exposes every runner provider capability from its lane entry point', () => {
it('exposes every runner provider capability from its compute-provider entry point', () => {
const controlPlanePlugin = controlPlaneProvider.createPlugin(vi.fn(async () => []));
const pool = controlPlanePlugin.capabilities.pool();
const scaleUp = controlPlanePlugin.capabilities.scaleUp();
Expand Down