diff --git a/.github/workflows/cloud-runner-ci-pipeline.yml b/.github/workflows/cloud-runner-ci-pipeline.yml index 918dd472..2613a58a 100644 --- a/.github/workflows/cloud-runner-ci-pipeline.yml +++ b/.github/workflows/cloud-runner-ci-pipeline.yml @@ -3,6 +3,11 @@ name: Cloud Runner CI Pipeline on: push: { branches: [cloud-runner-develop, cloud-runner-preview, main] } workflow_dispatch: + inputs: + runGithubIntegrationTests: + description: 'Run GitHub Checks integration tests' + required: false + default: 'false' permissions: checks: write @@ -207,3 +212,20 @@ jobs: name: ${{ matrix.providerStrategy }} Build (${{ matrix.targetPlatform }}) path: ${{ steps.unity-build.outputs.BUILD_ARTIFACT }} retention-days: 14 + + githubChecksIntegration: + name: GitHub Checks Integration + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' && github.event.inputs.runGithubIntegrationTests == 'true' + env: + RUN_GITHUB_INTEGRATION_TESTS: true + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'yarn' + - run: yarn install --frozen-lockfile + - run: yarn test cloud-runner-github-checks-integration-test --detectOpenHandles --forceExit --runInBand + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/jest.config.js b/jest.config.js index be54f49e..44abf35b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -25,6 +25,8 @@ module.exports = { // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader modulePathIgnorePatterns: ['/lib/', '/dist/'], - // A list of paths to modules that run some code to configure or set up the testing framework before each test + // Files that will be run before Jest is loaded to set globals like fetch + setupFiles: ['/src/jest.globals.ts'], + // A list of paths to modules that run some code to configure or set up the testing framework after the environment is ready setupFilesAfterEnv: ['/src/jest.setup.ts'], }; diff --git a/src/integration/cloud-runner-github-checks-integration-test.ts b/src/integration/cloud-runner-github-checks-integration-test.ts new file mode 100644 index 00000000..be5a70b5 --- /dev/null +++ b/src/integration/cloud-runner-github-checks-integration-test.ts @@ -0,0 +1,29 @@ +// Integration test for exercising real GitHub check creation and updates. +import CloudRunner from '../model/cloud-runner/cloud-runner'; +import UnityVersioning from '../model/unity-versioning'; +import GitHub from '../model/github'; +import { TIMEOUT_INFINITE, createParameters } from '../test-utils/cloud-runner-test-helpers'; + +const runIntegration = process.env.RUN_GITHUB_INTEGRATION_TESTS === 'true'; +const describeOrSkip = runIntegration ? describe : describe.skip; + +describeOrSkip('Cloud Runner Github Checks Integration', () => { + it( + 'creates and updates a real GitHub check', + async () => { + const buildParameter = await createParameters({ + versioning: 'None', + projectPath: 'test-project', + unityVersion: UnityVersioning.read('test-project'), + asyncCloudRunner: `true`, + githubChecks: `true`, + }); + await CloudRunner.setup(buildParameter); + const checkId = await GitHub.createGitHubCheck(`integration create`); + expect(checkId).not.toEqual(''); + await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `integration`); + await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `integration`, `success`, `completed`); + }, + TIMEOUT_INFINITE, + ); +}); diff --git a/src/jest.globals.ts b/src/jest.globals.ts new file mode 100644 index 00000000..b3905158 --- /dev/null +++ b/src/jest.globals.ts @@ -0,0 +1,3 @@ +import { fetch as undiciFetch, Headers, Request, Response } from 'undici'; + +Object.assign(globalThis, { fetch: undiciFetch, Headers, Request, Response }); diff --git a/src/model/cloud-runner/tests/cloud-runner-github-checks.test.ts b/src/model/cloud-runner/tests/cloud-runner-github-checks.test.ts index adb5b4b6..dbae58cf 100644 --- a/src/model/cloud-runner/tests/cloud-runner-github-checks.test.ts +++ b/src/model/cloud-runner/tests/cloud-runner-github-checks.test.ts @@ -1,59 +1,65 @@ -import { BuildParameters } from '../..'; import CloudRunner from '../cloud-runner'; import UnityVersioning from '../../unity-versioning'; -import { Cli } from '../../cli/cli'; -import CloudRunnerOptions from '../options/cloud-runner-options'; import setups from './cloud-runner-suite.test'; -import { OptionValues } from 'commander'; import GitHub from '../../github'; -export const TIMEOUT_INFINITE = 1e9; -async function CreateParameters(overrides: OptionValues | undefined) { - if (overrides) Cli.options = overrides; - - return BuildParameters.create(); -} +import { TIMEOUT_INFINITE, createParameters } from '../../../test-utils/cloud-runner-test-helpers'; describe('Cloud Runner Github Checks', () => { setups(); it('Responds', () => {}); - if (CloudRunnerOptions.cloudRunnerDebug) { - it( - 'Check Handling Direct', - async () => { - // Setup parameters - const buildParameter = await CreateParameters({ - versioning: 'None', - projectPath: 'test-project', - unityVersion: UnityVersioning.read('test-project'), - asyncCloudRunner: `true`, - githubChecks: `true`, - }); - await CloudRunner.setup(buildParameter); - CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`direct create`); - await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `direct`); - await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `direct`, `success`, `completed`); - }, - TIMEOUT_INFINITE, - ); - it( - 'Check Handling Via Async Workflow', - async () => { - // Setup parameters - const buildParameter = await CreateParameters({ - versioning: 'None', - projectPath: 'test-project', - unityVersion: UnityVersioning.read('test-project'), - asyncCloudRunner: `true`, - githubChecks: `true`, - }); - GitHub.forceAsyncTest = true; - await CloudRunner.setup(buildParameter); - CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`async create`); - await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `async`); - await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `async`, `success`, `completed`); - GitHub.forceAsyncTest = false; - }, - TIMEOUT_INFINITE, - ); - } + beforeEach(() => { + // Mock GitHub API requests to avoid real network calls + jest.spyOn(GitHub as any, 'createGitHubCheckRequest').mockResolvedValue({ + status: 201, + data: { id: '1' }, + }); + jest.spyOn(GitHub as any, 'updateGitHubCheckRequest').mockResolvedValue({ + status: 200, + data: {}, + }); + jest.spyOn(GitHub as any, 'runUpdateAsyncChecksWorkflow').mockResolvedValue(undefined); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it( + 'Check Handling Direct', + async () => { + // Setup parameters + const buildParameter = await createParameters({ + versioning: 'None', + projectPath: 'test-project', + unityVersion: UnityVersioning.read('test-project'), + asyncCloudRunner: `true`, + githubChecks: `true`, + }); + await CloudRunner.setup(buildParameter); + CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`direct create`); + await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `direct`); + await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `direct`, `success`, `completed`); + }, + TIMEOUT_INFINITE, + ); + it( + 'Check Handling Via Async Workflow', + async () => { + // Setup parameters + const buildParameter = await createParameters({ + versioning: 'None', + projectPath: 'test-project', + unityVersion: UnityVersioning.read('test-project'), + asyncCloudRunner: `true`, + githubChecks: `true`, + }); + GitHub.forceAsyncTest = true; + await CloudRunner.setup(buildParameter); + CloudRunner.buildParameters.githubCheckId = await GitHub.createGitHubCheck(`async create`); + await GitHub.updateGitHubCheck(`1 ${new Date().toISOString()}`, `async`); + await GitHub.updateGitHubCheck(`2 ${new Date().toISOString()}`, `async`, `success`, `completed`); + GitHub.forceAsyncTest = false; + }, + TIMEOUT_INFINITE, + ); }); diff --git a/src/test-utils/cloud-runner-test-helpers.ts b/src/test-utils/cloud-runner-test-helpers.ts new file mode 100644 index 00000000..4fd6bba6 --- /dev/null +++ b/src/test-utils/cloud-runner-test-helpers.ts @@ -0,0 +1,11 @@ +import { BuildParameters } from '../model'; +import { Cli } from '../model/cli/cli'; +import { OptionValues } from 'commander'; + +export const TIMEOUT_INFINITE = 1e9; + +export async function createParameters(overrides?: OptionValues) { + if (overrides) Cli.options = overrides; + + return BuildParameters.create(); +}