Skip to content

Commit

Permalink
Finish writing the action.
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthiasZepper committed Oct 5, 2023
1 parent 8de0d84 commit f67a30e
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 13 deletions.
12 changes: 8 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ inputs:
description: 'Action to take if the API limit is underrun: Sweep (fail) or sleep (wait for quota renewal).'
required: false
default: 'sweep'
quota:
description: 'Github API quota to use for the action: One of "core", "search", "graphql", "integration_manifest" or "code_scanning_upload"'
required: false
default: 'core'
lowerBound:
description: 'Minimum remaining API requests required to proceed.'
required: false
default: '50'
resource:
description: 'Github API quota to use for the action: One of "core", "search", "graphql", "integration_manifest" or "code_scanning_upload"'
required: false
default: 'core'
token:
description: 'Github API token to use for the action.'
required: false
default: '${{ secrets.GITHUB_TOKEN }}'

# Define your outputs here.
outputs:
Expand Down
74 changes: 65 additions & 9 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,80 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import { sleep } from './sleep'

interface Resource {
limit: number;

Check failure on line 6 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Delete `;`
remaining: number;

Check failure on line 7 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Delete `;`
reset: number;

Check failure on line 8 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Delete `;`
used: number;

Check failure on line 9 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Delete `;`
}

/**
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
*/
export async function run(): Promise<void> {
try {

Check failure on line 17 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Delete `⏎`
const ms: string = core.getInput('milliseconds')

// Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true
core.debug(`Waiting ${ms} milliseconds ...`)
let lowerBound: number = parseInt(core.getInput('lowerBound')) || 50

Check failure on line 19 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

'lowerBound' is never reassigned. Use 'const' instead
let actionToTake: string = core.getInput('actionToTake') || 'sweep'

Check failure on line 20 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

'actionToTake' is never reassigned. Use 'const' instead
let resource: string = core.getInput('resource') || 'core'

Check failure on line 21 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

'resource' is never reassigned. Use 'const' instead
let token: string = core.getInput('token') || String(process.env.GITHUB_TOKEN)

Check failure on line 22 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

'token' is never reassigned. Use 'const' instead

Check failure on line 22 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint Code Base

Replace `·core.getInput('token')·||·String(process.env.GITHUB_TOKEN)·` with `⏎······core.getInput('token')·||·String(process.env.GITHUB_TOKEN)`

// corroborate that resource is one of the valid resource types / quotas:
if (![ "core", "search", "graphql", "integration_manifest", "code_scanning_upload"].includes(resource)) {
core.setFailed(`The resource must be either core, graphql, search, integration_manifest, or code_scanning_upload.`)
}

if (!token) {
core.setFailed("Please provide a Github token")
}


// retrieve the number of remaining API requests
const octoKit = github.getOctokit(token)
const rateLimit = await octoKit.rest.rateLimit.get()
core.debug(JSON.stringify(rateLimit))

// retrieve the property of the rateLimit object that corresponds to the resource
const resourceData: Resource = rateLimit.data.resources[resource as keyof typeof rateLimit.data.resources] as Resource
const remaining: number = resourceData.remaining || -1
const reset: number = resourceData.reset || -1

if (remaining < 0 || reset < 0) {

core.setFailed("Github API rateLimit could not be retrieved.")

} else {

core.exportVariable('remaining', remaining)
core.setOutput('remaining', remaining)

if (remaining > lowerBound) {

core.info(`The API limit is plentiful: ${remaining} requests on ${resource} remain.`)

} else {

core.info(`The API limit is dangerously low: ${remaining} requests on ${resource} remain.`)

switch (actionToTake) {
case 'sleep':
// calculate the number of seconds until the rate limit resets (getTime() returns milliseconds, the API UTC epoch seconds)
const seconds_to_reset = reset - Math.round((new Date()).getTime() / 1000)
const minutes = Math.floor(seconds_to_reset / 60)

core.info(`The API limit will reset in ${minutes} minutes and ${(seconds_to_reset % 60)} seconds.`)

// Log the current timestamp, wait, then log the new timestamp
core.debug(new Date().toTimeString())
await sleep(parseInt(ms, 10))
core.debug(new Date().toTimeString())
// sleep n milliseconds + 5 seconds past the reset time to ensure the limit has been reset
await sleep(seconds_to_reset*1000+5000)

// Set outputs for other workflow steps to use
core.setOutput('time', new Date().toTimeString())
core.info(`The API limit has been reset. Farewell!`)
break
default:
core.setFailed(`The API limit of ${resource} was too low to proceed.`)
}
}
}
} catch (error) {
// Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message)
Expand Down

0 comments on commit f67a30e

Please sign in to comment.