@@ -12,6 +12,7 @@ import { RunnerInputParameters } from './../aws/runners.d';
1212import ScaleError from './ScaleError' ;
1313import * as scaleUpModule from './scale-up' ;
1414import { getParameter } from '@aws-github-runner/aws-ssm-util' ;
15+ import { createSingleMetric } from '@aws-github-runner/aws-powertools-util' ;
1516import { describe , it , expect , beforeEach , vi } from 'vitest' ;
1617
1718const mockOctokit = {
@@ -33,6 +34,7 @@ const mockCreateRunner = vi.mocked(createRunner);
3334const mockListRunners = vi . mocked ( listEC2Runners ) ;
3435const mockSSMClient = mockClient ( SSMClient ) ;
3536const mockSSMgetParameter = vi . mocked ( getParameter ) ;
37+ const mockCreateSingleMetric = vi . mocked ( createSingleMetric ) ;
3638
3739vi . mock ( '@octokit/rest' , ( ) => ( {
3840 Octokit : vi . fn ( ) . mockImplementation ( ( ) => mockOctokit ) ,
@@ -61,6 +63,22 @@ vi.mock('@aws-github-runner/aws-ssm-util', async () => {
6163 } ;
6264} ) ;
6365
66+ vi . mock ( '@aws-github-runner/aws-powertools-util' , async ( ) => {
67+ const actual = ( await vi . importActual (
68+ '@aws-github-runner/aws-powertools-util' ,
69+ ) ) as typeof import ( '@aws-github-runner/aws-powertools-util' ) ;
70+
71+ return {
72+ ...actual ,
73+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
74+ createSingleMetric : vi . fn ( ( name : string , unit : string , value : number , dimensions ?: Record < string , string > ) => {
75+ return {
76+ addMetadata : vi . fn ( ) ,
77+ } ;
78+ } ) ,
79+ } ;
80+ } ) ;
81+
6482export type RunnerType = 'ephemeral' | 'non-ephemeral' ;
6583
6684// for ephemeral and non-ephemeral runners
@@ -183,6 +201,83 @@ describe('scaleUp with GHES', () => {
183201 expect ( listEC2Runners ) . not . toBeCalled ( ) ;
184202 } ) ;
185203
204+ describe ( 'pool sufficiency metrics' , ( ) => {
205+ beforeEach ( ( ) => {
206+ process . env . ENABLE_ORGANIZATION_RUNNERS = 'true' ;
207+ process . env . ENVIRONMENT = 'test-env' ;
208+ } ) ;
209+
210+ it ( 'records pool sufficiency metric as insufficient when scaling up' , async ( ) => {
211+ process . env . ENABLE_METRIC_POOL_SUFFICIENCY = 'true' ;
212+ process . env . RUNNERS_MAXIMUM_COUNT = '5' ;
213+
214+ mockListRunners . mockImplementation ( async ( ) => [
215+ {
216+ instanceId : 'i-1234' ,
217+ launchTime : new Date ( ) ,
218+ type : 'Org' ,
219+ owner : TEST_DATA . repositoryOwner ,
220+ } ,
221+ ] ) ;
222+
223+ await scaleUpModule . scaleUp ( 'aws:sqs' , TEST_DATA ) ;
224+
225+ expect ( mockCreateSingleMetric ) . toHaveBeenCalledWith ( 'SufficientPoolHosts' , 'Count' , 0.0 , {
226+ Environment : 'test-env' ,
227+ } ) ;
228+ } ) ;
229+
230+ it ( 'records pool sufficiency metric as sufficient when job is not queued' , async ( ) => {
231+ process . env . ENABLE_METRIC_POOL_SUFFICIENCY = 'true' ;
232+
233+ mockOctokit . actions . getJobForWorkflowRun . mockImplementation ( ( ) => ( {
234+ data : { status : 'completed' } ,
235+ } ) ) ;
236+
237+ await scaleUpModule . scaleUp ( 'aws:sqs' , TEST_DATA ) ;
238+
239+ expect ( mockCreateSingleMetric ) . toHaveBeenCalledWith ( 'SufficientPoolHosts' , 'Count' , 1.0 , {
240+ Environment : 'test-env' ,
241+ } ) ;
242+ } ) ;
243+
244+ it ( 'does not record pool sufficiency metric when disabled' , async ( ) => {
245+ process . env . ENABLE_METRIC_POOL_SUFFICIENCY = 'false' ;
246+ process . env . RUNNERS_MAXIMUM_COUNT = '5' ;
247+
248+ mockListRunners . mockImplementation ( async ( ) => [
249+ {
250+ instanceId : 'i-1234' ,
251+ launchTime : new Date ( ) ,
252+ type : 'Org' ,
253+ owner : TEST_DATA . repositoryOwner ,
254+ } ,
255+ ] ) ;
256+
257+ await scaleUpModule . scaleUp ( 'aws:sqs' , TEST_DATA ) ;
258+
259+ expect ( mockCreateSingleMetric ) . not . toHaveBeenCalled ( ) ;
260+ } ) ;
261+
262+ it ( 'does not record pool sufficiency metric when environment variable is undefined' , async ( ) => {
263+ delete process . env . ENABLE_METRIC_POOL_SUFFICIENCY ;
264+ process . env . RUNNERS_MAXIMUM_COUNT = '5' ;
265+
266+ mockListRunners . mockImplementation ( async ( ) => [
267+ {
268+ instanceId : 'i-1234' ,
269+ launchTime : new Date ( ) ,
270+ type : 'Org' ,
271+ owner : TEST_DATA . repositoryOwner ,
272+ } ,
273+ ] ) ;
274+
275+ await scaleUpModule . scaleUp ( 'aws:sqs' , TEST_DATA ) ;
276+
277+ expect ( mockCreateSingleMetric ) . not . toHaveBeenCalled ( ) ;
278+ } ) ;
279+ } ) ;
280+
186281 describe ( 'on org level' , ( ) => {
187282 beforeEach ( ( ) => {
188283 process . env . ENABLE_ORGANIZATION_RUNNERS = 'true' ;
0 commit comments