-
Notifications
You must be signed in to change notification settings - Fork 10
feat: add support for GHES #387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a9ebec8
b07dd14
411c2b6
b06b2dd
1bec029
c285eb0
821b679
bcdbe1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,16 @@ | ||
| import * as core from '@actions/core' | ||
| import {context, getCurrentDeployment, getCurrentJob, getInput, PermissionError, run} from './lib/actions.js' | ||
| import {context, getCurrentDeployment, getInput, PermissionError, run} from './lib/actions.js' | ||
| import { getCurrentJob } from 'lib/jobs.js' | ||
| // see https://github.com/actions/toolkit for more GitHub actions libraries | ||
| import {fileURLToPath} from 'url' | ||
| import * as process from 'node:process' | ||
| import {sleep} from "./lib/common.js"; | ||
| import * as github from "@actions/github"; | ||
|
|
||
| if(!process.env.GITHUB_API_URL && process.env.GITHUB_SERVER_URL) { | ||
| process.env.GITHUB_API_URL = `${process.env.GITHUB_SERVER_URL.replace(/\/$/, '')}/api/v3` | ||
| } | ||
|
|
||
| export const action = run(async () => { | ||
|
|
||
| const inputs = { | ||
|
|
@@ -26,7 +31,12 @@ export const action = run(async () => { | |
| core.setOutput('run_html_url', runHtmlUrl) | ||
| core.exportVariable('GITHUB_RUN_HTML_URL', runHtmlUrl) | ||
|
|
||
| await getCurrentJob(octokit).then((job) => { | ||
| await getCurrentJob(octokit, context).then((job) => { | ||
| if (job === undefined) { | ||
| core.warning('Current job not found for runner: ' + context.runnerName) | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. possibly raise an error? but should never happen |
||
| return null | ||
| } | ||
|
|
||
| if (core.isDebug()) { | ||
| core.debug(JSON.stringify(job)); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import {z} from "zod"; | ||
| import YAML from "yaml"; | ||
| import {Context} from '@actions/github/lib/context'; | ||
|
|
||
| export type JsonLiteral = string | number | boolean | null | ||
| // eslint-disable-next-line @typescript-eslint/consistent-type-definitions | ||
|
|
@@ -59,3 +60,48 @@ export function getFlatValues(values: unknown): unknown[] { | |
| export function _throw(error: unknown): never { | ||
| throw error | ||
| } | ||
|
|
||
| // --- Enhanced GitHub Action Context -------------------------------------------------- | ||
|
|
||
| export class EnhancedContext extends Context { | ||
|
|
||
| get repository() { | ||
| return `${this.repo.owner}/${this.repo.repo}`; | ||
| } | ||
|
|
||
| get isGithubEnterprise() { | ||
| return process.env.GITHUB_API_URL != 'https://api.github.com' | ||
| } | ||
|
Comment on lines
+72
to
+74
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the only addition to the class |
||
|
|
||
| get jobCheckRunId() { | ||
| return parseInt(process.env.JOB_CHECK_RUN_ID | ||
| // WORKAROUND until https://github.com/actions/runner/pull/4053 is merged and released | ||
| ?? process.env.INPUT__JOB_CHECK_RUN_ID | ||
| ?? _throw(new Error('Missing environment variable: JOB_CHECK_RUN_ID'))); | ||
| } | ||
|
|
||
| get workflowRef() { | ||
| return process.env.GITHUB_WORKFLOW_REF | ||
| ?? _throw(new Error('Missing environment variable: GITHUB_WORKFLOW_REF')); | ||
| } | ||
|
|
||
| get workflowSha() { | ||
| return process.env.GITHUB_WORKFLOW_SHA | ||
| ?? _throw(new Error('Missing environment variable: GITHUB_WORKFLOW_SHA')); | ||
| } | ||
|
|
||
| get runHtmlUrl() { | ||
| return process.env.GITHUB_RUN_HTML_URL ?? `${this.serverUrl}/${this.repository}` + `/actions/runs/${this.runId}` + | ||
| (this.runAttempt ? `/attempts/${this.runAttempt}` : ''); | ||
| } | ||
|
|
||
| get runnerName() { | ||
| return process.env.RUNNER_NAME | ||
| ?? _throw(new Error('Missing environment variable: RUNNER_NAME')); | ||
| } | ||
|
|
||
| get runnerTempDir() { | ||
| return process.env.RUNNER_TEMP | ||
| ?? _throw(new Error('Missing environment variable: RUNNER_TEMP')); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import { GitHub } from "@actions/github/lib/utils"; | ||
| import { context, throwPermissionError } from "./actions"; | ||
| import { EnhancedContext } from "./common"; | ||
| import * as core from '@actions/core' | ||
| import type { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"; | ||
|
|
||
| // type alias for job object returned by octokit.rest.actions.getJobForWorkflowRun | ||
| type Job = RestEndpointMethodTypes["actions"]["getJobForWorkflowRun"]["response"]["data"]; | ||
|
|
||
| // cache of getCurrentJob result | ||
| let _currentJob: Job | undefined = undefined | ||
|
|
||
| /** | ||
| * Get the job for the current runner from the workflow run using Octokit REST API. | ||
| * Equivalent to: | ||
| * jobs=`curl .../actions/runs/${run_id}/jobs` | ||
| * job=$(echo $jobs | jq -r '.jobs[] | select(.runner_name=="${{ runner.name }}")') | ||
| * @param octokit - An authenticated Octokit instance | ||
| * @param context - The enhanced GitHub Actions context | ||
| * @returns The job for the current runner, or undefined if not found | ||
| */ | ||
| export async function getCurrentJobByRunner( | ||
| octokit: InstanceType<typeof GitHub>, | ||
| context: EnhancedContext | ||
| ): Promise<Job | undefined> { | ||
| const runId = context.runId; | ||
| const runnerName = context.runnerName; | ||
| const { owner, repo } = context.repo; | ||
| const jobsResponse = await octokit.rest.actions.listJobsForWorkflowRun({ | ||
| owner: owner, | ||
| repo: repo, | ||
| run_id: runId, | ||
| per_page: 100, | ||
| }); | ||
| const job: Job | undefined = jobsResponse.data.jobs.find(j => j.runner_name === runnerName); | ||
| return job; | ||
| } | ||
|
|
||
| /** | ||
| * Get the job object for the current runner from the workflow run using Octokit REST API. | ||
| * @param octokit - An authenticated Octokit instance | ||
| * @param context - The enhanced GitHub Actions context | ||
| * @returns The job object for the current runner | ||
| */ | ||
| export async function getCurrentJob(octokit: InstanceType<typeof GitHub>, context: EnhancedContext | ||
| ) : Promise<Job | undefined>{ | ||
| // Return cached job if available | ||
| if (_currentJob != undefined) return _currentJob | ||
|
|
||
| // For GitHub Enterprise we need a workaround | ||
| if (context.isGithubEnterprise) { | ||
| core.warning( | ||
| 'Running in GitHub Enterprise environment, we currently need to use a workaround until ' + | ||
| 'this functionality is natively supported: https://github.blog/changelog/2025-11-13-github-actions-oidc-token-claims-now-include-check_run_id/' | ||
| ) | ||
| const currentJob = await getCurrentJobByRunner(octokit, context) | ||
| return _currentJob = currentJob | ||
| } | ||
|
|
||
| // For GitHub.com we can directly get the job by using the check_run_id | ||
| const currentJob = await octokit.rest.actions.getJobForWorkflowRun({ | ||
| ...context.repo, | ||
| job_id: context.jobCheckRunId, | ||
| }).catch((error) => { | ||
| if (error.status === 403) { | ||
| throwPermissionError({scope: 'actions', permission: 'read'}, error) | ||
| } | ||
| throw error | ||
| }).then((res) => res.data) | ||
| return _currentJob = currentJob | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not an expert of js/ts, once the
process.envis modified here, will it stay up-to-date for the entire process life?if not, the
EnhancedContext::isGithubEnterprise()method impl is wrong, else is ok