diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6f67d91..c9e1bcf 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -32,7 +32,8 @@ jobs: - name: 'npm build' run: 'npm ci && npm run build' - - uses: 'google-github-actions/auth@v2' + - id: 'auth' + uses: 'google-github-actions/auth@v2' with: project_id: '${{ vars.PROJECT_ID }}' workload_identity_provider: '${{ vars.WIF_PROVIDER_NAME }}' @@ -46,6 +47,12 @@ jobs: source_dir: './tests/test-node-func/' service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' + - name: 'test' + run: |- + curl -sf "${{ steps.deploy.outputs.url }}" \ + -H "Authorization: Bearer ${{ steps.auth.outputs.auth_token }}" \ + | grep "Hello World" + event_trigger: timeout-minutes: 10 permissions: 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..ca5df68 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -29,13 +29,14 @@ 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'); +const TEST_FUNCTION_NAME = `test-${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 +53,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 +76,35 @@ 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' }, + environmentVariables: { + [`BUILD_ENV_KEY1-${TEST_SEED}`]: `VALUE1-${TEST_SEED}`, + [`BUILD_ENV_KEY2-${TEST_SEED}`]: `VALUE2-${TEST_SEED}`, + }, }, serviceConfig: { allTrafficOnLatestRevision: true, availableCpu: '1', availableMemory: '512m', - environmentVariables: { KEY1: 'VALUE1', KEY2: 'VALUE2' }, + environmentVariables: { + [`SERVICE_ENV_KEY1-${TEST_SEED}`]: `VALUE1-${TEST_SEED}`, + [`SERVICE_ENV_KEY2-${TEST_SEED}`]: `VALUE2-${TEST_SEED}`, + }, ingressSettings: IngressSettings.ALLOW_ALL, maxInstanceCount: 5, minInstanceCount: 2, secretEnvironmentVariables: [ { - key: 'SECRET1', + key: `SECRET1-${TEST_SEED}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -102,7 +112,7 @@ test( ], secretVolumes: [ { - mountPath: '/etc/secrets/one', + mountPath: `/etc/secrets/one-${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ @@ -126,25 +136,28 @@ test( 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.labels, { + [`label1-${TEST_SEED}`]: `value1-${TEST_SEED}`, + [`label2-${TEST_SEED}`]: `value2-${TEST_SEED}`, + }); assert.deepStrictEqual(getResp.buildConfig.runtime, 'nodejs20'); assert.deepStrictEqual(getResp.buildConfig.environmentVariables, { - BUILDKEY1: 'VALUE1', - BUILDKEY2: 'VALUE2', + [`BUILD_ENV_KEY1-${TEST_SEED}`]: `VALUE1-${TEST_SEED}`, + [`BUILD_ENV_KEY2-${TEST_SEED}`]: `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.environmentVariables, { - KEY1: 'VALUE1', - KEY2: 'VALUE2', + [`SERVICE_ENV_KEY1-${TEST_SEED}`]: `VALUE1-${TEST_SEED}`, + [`SERVICE_ENV_KEY2-${TEST_SEED}`]: `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}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -152,7 +165,7 @@ test( ]); assert.deepStrictEqual(getResp.serviceConfig.secretVolumes, [ { - mountPath: '/etc/secrets/one', + mountPath: `/etc/secrets/one-${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ @@ -175,25 +188,34 @@ 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' }, + environmentVariables: { + [`BUILD_ENV_KEY3-${TEST_SEED}`]: `VALUE3-${TEST_SEED}`, + [`BUILD_ENV_KEY4-${TEST_SEED}`]: `VALUE4-${TEST_SEED}`, + }, }, serviceConfig: { allTrafficOnLatestRevision: true, availableMemory: '256Mi', - environmentVariables: { KEY3: 'VALUE3', KEY4: 'VALUE4' }, + environmentVariables: { + [`SERVICE_ENV_KEY3-${TEST_SEED}`]: `VALUE3-${TEST_SEED}`, + [`SERVICE_ENV_KEY4-${TEST_SEED}`]: `VALUE4-${TEST_SEED}`, + }, ingressSettings: IngressSettings.ALLOW_INTERNAL_AND_GCLB, maxInstanceCount: 3, minInstanceCount: 1, secretEnvironmentVariables: [ { - key: 'SECRET2', + key: `SECRET2-${TEST_SEED}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -201,7 +223,7 @@ test( ], secretVolumes: [ { - mountPath: '/etc/secrets/two', + mountPath: `/etc/secrets/two-${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ @@ -220,24 +242,27 @@ test( const patchResp = await client.patch(cf2); 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}`]: `VALUE3-${TEST_SEED}`, + [`BUILD_ENV_KEY4-${TEST_SEED}`]: `VALUE4-${TEST_SEED}`, }); assert.deepStrictEqual(patchResp.serviceConfig.availableMemory, '256'); assert.deepStrictEqual(patchResp.serviceConfig.environmentVariables, { - KEY3: 'VALUE3', - KEY4: 'VALUE4', + [`SERVICE_ENV_KEY3-${TEST_SEED}`]: `VALUE3-${TEST_SEED}`, + [`SERVICE_ENV_KEY4-${TEST_SEED}`]: `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}`, projectId: secret.project, secret: secret.name, version: secret.version, @@ -245,7 +270,7 @@ test( ]); assert.deepStrictEqual(patchResp.serviceConfig.secretVolumes, [ { - mountPath: '/etc/secrets/two', + mountPath: `/etc/secrets/two-${TEST_SEED}`, projectId: secret.project, secret: secret.name, versions: [ 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!/); - }); - }, -);