From 0dffa6a36597f21d32bc9c488c16df7b1b25a8c0 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Mon, 12 Aug 2024 20:12:37 -0400 Subject: [PATCH] Improve integration test with unique values to ensure they are overwritten --- .github/workflows/integration.yml | 17 +++- .github/workflows/unit.yml | 6 +- tests/client.test.ts | 126 ++++++++++++++++++++---------- tests/e2e/e2e.test.ts | 42 ---------- 4 files changed, 104 insertions(+), 87 deletions(-) delete mode 100644 tests/e2e/e2e.test.ts diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6f67d91..2d9dff4 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -40,12 +40,25 @@ jobs: - id: 'deploy' uses: './' with: - name: 'https-trigger-${{ github.run_number }}' + name: 'integration-https-trigger-${{ github.run_number }}-${{ github.run_attempt }}' runtime: 'nodejs22' entry_point: 'helloWorld' source_dir: './tests/test-node-func/' service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' + - id: 'auth' + uses: 'google-github-actions/auth@v2' + with: + project_id: '${{ vars.PROJECT_ID }}' + workload_identity_provider: '${{ vars.WIF_PROVIDER_NAME }}' + + - name: 'test' + run: |- + curl "${{ steps.deploy.outputs.url }}" \ + --silent \ + --fail-with-body \ + --header "Authorization: Bearer ${{ steps.auth.outputs.auth_token }}" + event_trigger: timeout-minutes: 10 permissions: @@ -70,7 +83,7 @@ jobs: - id: 'deploy' uses: './' with: - name: 'event-trigger-${{ github.run_number }}' + name: 'integration-event-trigger-${{ github.run_number }}-${{ github.run_attempt }}' runtime: 'nodejs22' entry_point: 'helloWorld' source_dir: './tests/test-node-func/' diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 36341b2..9cdd492 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -46,14 +46,16 @@ jobs: if: ${{ matrix.os == 'ubuntu-latest' }} run: 'npm run lint' - - uses: 'google-github-actions/auth@v2' + - id: 'auth' + uses: 'google-github-actions/auth@v2' if: ${{ github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name && github.actor != 'dependabot[bot]' }} with: + project_id: '${{ vars.PROJECT_ID }}' workload_identity_provider: '${{ vars.WIF_PROVIDER_NAME }}' - service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' - name: 'npm test' env: + TEST_AUTHENTICATED: '${{ !!steps.auth.outputs.auth_token }}' TEST_PROJECT_ID: '${{ vars.PROJECT_ID }}' TEST_SERVICE_ACCOUNT_EMAIL: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' TEST_SECRET_VERSION_NAME: '${{ vars.SECRET_VERSION_NAME }}' diff --git a/tests/client.test.ts b/tests/client.test.ts index dbe9713..65b01d9 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -29,13 +29,15 @@ import { zipDir } from '../src/util'; const { TEST_PROJECT_ID, TEST_SERVICE_ACCOUNT_EMAIL, TEST_SECRET_VERSION_NAME } = process.env; const TEST_LOCATION = 'us-central1'; -const TEST_FUNCTION_NAME = 'test-' + crypto.randomBytes(12).toString('hex'); +const TEST_SEED = crypto.randomBytes(12).toString('hex').toLowerCase(); +const TEST_SEED_UPPER = TEST_SEED.toUpperCase(); +const TEST_FUNCTION_NAME = `unit-${TEST_SEED}`; test( 'lifecycle', { concurrency: true, - skip: skipIfMissingEnv('TEST_PROJECT_ID', 'TEST_LOCATION'), + skip: skipIfMissingEnv('TEST_AUTHENTICATED'), }, async (suite) => { // Always try to delete the function @@ -52,7 +54,7 @@ test( } }); - suite.test('can create, read, update, and delete', async () => { + await suite.test('can create, read, update, and delete', async () => { const secret = new SecretName(TEST_SECRET_VERSION_NAME); const client = new CloudFunctionsClient({ @@ -75,26 +77,37 @@ test( name: TEST_FUNCTION_NAME, description: 'test function', environment: Environment.GEN_2, - labels: { key1: 'value1', key2: 'value2' }, + labels: { + [`label1-${TEST_SEED}`]: `value1_${TEST_SEED}`, + [`label2-${TEST_SEED}`]: `value2_${TEST_SEED}`, + }, buildConfig: { runtime: 'nodejs22', entryPoint: 'helloWorld', - source: sourceUploadResp, - environmentVariables: { BUILDKEY1: 'VALUE1', BUILDKEY2: 'VALUE2' }, + source: { + storageSource: sourceUploadResp.storageSource, + }, + environmentVariables: { + [`BUILD_ENV_KEY1_${TEST_SEED_UPPER}`]: `VALUE1_${TEST_SEED}`, + [`BUILD_ENV_KEY2_${TEST_SEED_UPPER}`]: `VALUE2_${TEST_SEED}`, + }, }, serviceConfig: { allTrafficOnLatestRevision: true, availableCpu: '1', - availableMemory: '512m', - environmentVariables: { KEY1: 'VALUE1', KEY2: 'VALUE2' }, + availableMemory: '512Mi', + environmentVariables: { + [`SERVICE_ENV_KEY1_${TEST_SEED_UPPER}`]: `VALUE1_${TEST_SEED}`, + [`SERVICE_ENV_KEY2_${TEST_SEED_UPPER}`]: `VALUE2_${TEST_SEED}`, + }, ingressSettings: IngressSettings.ALLOW_ALL, maxInstanceCount: 5, minInstanceCount: 2, secretEnvironmentVariables: [ { - key: 'SECRET1', + key: `SECRET1_${TEST_SEED_UPPER}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -102,12 +115,12 @@ test( ], secretVolumes: [ { - mountPath: '/etc/secrets/one', + mountPath: `/etc/secrets/one_${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ { - path: '/value1', + path: 'value1', version: secret.version, }, ], @@ -119,32 +132,42 @@ test( }; // Create - const createResp = await client.create(cf); + const createResp = await client.create(cf, { + onDebug: (f) => { + process.stdout.write('\n\n\n\n'); + process.stdout.write(f()); + process.stdout.write('\n\n\n\n'); + }, + }); assert.ok(createResp?.url); // Read const getResp = await client.get(cf.name); assert.ok(getResp.name.endsWith(TEST_FUNCTION_NAME)); // The response is the fully-qualified name assert.deepStrictEqual(getResp.description, 'test function'); - assert.deepStrictEqual(getResp.labels, { key1: 'value1', key2: 'value2' }); - assert.deepStrictEqual(getResp.buildConfig.runtime, 'nodejs20'); + assert.deepStrictEqual(getResp.labels, { + [`label1-${TEST_SEED}`]: `value1_${TEST_SEED}`, + [`label2-${TEST_SEED}`]: `value2_${TEST_SEED}`, + }); + assert.deepStrictEqual(getResp.buildConfig.runtime, 'nodejs22'); assert.deepStrictEqual(getResp.buildConfig.environmentVariables, { - BUILDKEY1: 'VALUE1', - BUILDKEY2: 'VALUE2', + [`BUILD_ENV_KEY1_${TEST_SEED_UPPER}`]: `VALUE1_${TEST_SEED}`, + [`BUILD_ENV_KEY2_${TEST_SEED_UPPER}`]: `VALUE2_${TEST_SEED}`, }); assert.deepStrictEqual(getResp.buildConfig.entryPoint, 'helloWorld'); - assert.deepStrictEqual(getResp.serviceConfig.availableCpu, 1); - assert.deepStrictEqual(getResp.serviceConfig.availableMemory, 512); + assert.deepStrictEqual(getResp.serviceConfig.availableCpu, '1'); + assert.deepStrictEqual(getResp.serviceConfig.availableMemory, '512Mi'); assert.deepStrictEqual(getResp.serviceConfig.environmentVariables, { - KEY1: 'VALUE1', - KEY2: 'VALUE2', + LOG_EXECUTION_ID: 'true', // inserted by GCP + [`SERVICE_ENV_KEY1_${TEST_SEED_UPPER}`]: `VALUE1_${TEST_SEED}`, + [`SERVICE_ENV_KEY2_${TEST_SEED_UPPER}`]: `VALUE2_${TEST_SEED}`, }); assert.deepStrictEqual(getResp.serviceConfig.ingressSettings, 'ALLOW_ALL'); assert.deepStrictEqual(getResp.serviceConfig.maxInstanceCount, 5); assert.deepStrictEqual(getResp.serviceConfig.minInstanceCount, 2); assert.deepStrictEqual(getResp.serviceConfig.secretEnvironmentVariables, [ { - key: 'SECRET1', + key: `SECRET1_${TEST_SEED_UPPER}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -152,12 +175,12 @@ test( ]); assert.deepStrictEqual(getResp.serviceConfig.secretVolumes, [ { - mountPath: '/etc/secrets/one', + mountPath: `/etc/secrets/one_${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ { - path: '/value1', + path: 'value1', version: secret.version, }, ], @@ -175,25 +198,36 @@ test( const cf2: CloudFunction = { name: TEST_FUNCTION_NAME, description: 'test function2', - labels: { key3: 'value3', key4: 'value4' }, + labels: { + [`label3-${TEST_SEED}`]: `value3_${TEST_SEED}`, + [`label4-${TEST_SEED}`]: `value4_${TEST_SEED}`, + }, buildConfig: { runtime: 'nodejs20', entryPoint: 'helloWorld', - source: sourceUploadUpdateResp, - environmentVariables: { BUILDKEY3: 'VALUE3', BUILDKEY4: 'VALUE4' }, + source: { + storageSource: sourceUploadResp.storageSource, + }, + environmentVariables: { + [`BUILD_ENV_KEY3_${TEST_SEED_UPPER}`]: `VALUE3_${TEST_SEED}`, + [`BUILD_ENV_KEY4_${TEST_SEED_UPPER}`]: `VALUE4_${TEST_SEED}`, + }, }, serviceConfig: { allTrafficOnLatestRevision: true, - availableMemory: '256Mi', - environmentVariables: { KEY3: 'VALUE3', KEY4: 'VALUE4' }, + availableMemory: '1Gi', + environmentVariables: { + [`SERVICE_ENV_KEY3_${TEST_SEED_UPPER}`]: `VALUE3_${TEST_SEED}`, + [`SERVICE_ENV_KEY4_${TEST_SEED_UPPER}`]: `VALUE4_${TEST_SEED}`, + }, ingressSettings: IngressSettings.ALLOW_INTERNAL_AND_GCLB, maxInstanceCount: 3, minInstanceCount: 1, secretEnvironmentVariables: [ { - key: 'SECRET2', + key: `SECRET2_${TEST_SEED_UPPER}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -201,12 +235,12 @@ test( ], secretVolumes: [ { - mountPath: '/etc/secrets/two', + mountPath: `/etc/secrets/two_${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ { - path: '/value2', + path: 'value2', version: secret.version, }, ], @@ -217,27 +251,37 @@ test( }, }; - const patchResp = await client.patch(cf2); + const patchResp = await client.patch(cf2, { + onDebug: (f) => { + process.stdout.write('\n\n\n\n'); + process.stdout.write(f()); + process.stdout.write('\n\n\n\n'); + }, + }); assert.ok(patchResp.name.endsWith(TEST_FUNCTION_NAME)); // The response is the fully-qualified name assert.deepStrictEqual(patchResp.description, 'test function2'); - assert.deepStrictEqual(patchResp.labels, { key3: 'value3', key4: 'value4' }); + assert.deepStrictEqual(patchResp.labels, { + [`label3-${TEST_SEED}`]: `value3_${TEST_SEED}`, + [`label4-${TEST_SEED}`]: `value4_${TEST_SEED}`, + }); assert.deepStrictEqual(patchResp.buildConfig.runtime, 'nodejs20'); assert.deepStrictEqual(patchResp.buildConfig.entryPoint, 'helloWorld'); assert.deepStrictEqual(patchResp.buildConfig.environmentVariables, { - BUILDKEY3: 'VALUE3', - BUILDKEY4: 'VALUE4', + [`BUILD_ENV_KEY3_${TEST_SEED_UPPER}`]: `VALUE3_${TEST_SEED}`, + [`BUILD_ENV_KEY4_${TEST_SEED_UPPER}`]: `VALUE4_${TEST_SEED}`, }); - assert.deepStrictEqual(patchResp.serviceConfig.availableMemory, '256'); + assert.deepStrictEqual(patchResp.serviceConfig.availableMemory, '1Gi'); assert.deepStrictEqual(patchResp.serviceConfig.environmentVariables, { - KEY3: 'VALUE3', - KEY4: 'VALUE4', + LOG_EXECUTION_ID: 'true', // inserted by GCP + [`SERVICE_ENV_KEY3_${TEST_SEED_UPPER}`]: `VALUE3_${TEST_SEED}`, + [`SERVICE_ENV_KEY4_${TEST_SEED_UPPER}`]: `VALUE4_${TEST_SEED}`, }); assert.deepStrictEqual(patchResp.serviceConfig.ingressSettings, 'ALLOW_INTERNAL_AND_GCLB'); assert.deepStrictEqual(patchResp.serviceConfig.maxInstanceCount, 3); assert.deepStrictEqual(patchResp.serviceConfig.minInstanceCount, 1); assert.deepStrictEqual(patchResp.serviceConfig.secretEnvironmentVariables, [ { - key: 'SECRET2', + key: `SECRET2_${TEST_SEED_UPPER}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -245,12 +289,12 @@ test( ]); assert.deepStrictEqual(patchResp.serviceConfig.secretVolumes, [ { - mountPath: '/etc/secrets/two', + mountPath: `/etc/secrets/two_${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ { - path: '/value2', + path: 'value2', version: secret.version, }, ], diff --git a/tests/e2e/e2e.test.ts b/tests/e2e/e2e.test.ts deleted file mode 100644 index 17a2560..0000000 --- a/tests/e2e/e2e.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { test } from 'node:test'; -import assert from 'node:assert'; - -import { skipIfMissingEnv } from '@google-github-actions/actions-utils'; - -import { GoogleAuth } from 'google-auth-library'; - -test( - 'e2e tests', - { - concurrency: true, - skip: skipIfMissingEnv('URL'), - }, - async (suite) => { - await suite.test('makes a request', async () => { - const url = process.env.URL!; - - // Requires ADC to be set - const auth = new GoogleAuth(); - const client = await auth.getIdTokenClient(url); - const response = await client.request({ url: url }); - assert.deepStrictEqual(response.status, 200); - assert.match(response.data as string, /Hello World!/); - }); - }, -);