Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
efc994a
chore: update go to 1.25
sofisl Mar 5, 2026
434d4b8
chore: pin nock and return kaniko project executor to previous state
sofisl Mar 6, 2026
3dbff4c
update ingress settings
sofisl Mar 6, 2026
d173f6e
chore: fix syncpack and try to fix issue with glcoud deployment
sofisl Mar 6, 2026
5c88e19
specify syncpack
sofisl Mar 6, 2026
abbd5eb
remove syncpack check
sofisl Mar 6, 2026
fb2e32a
Remove 'only' from cloud functions test suite
sofisl Mar 9, 2026
740b8c6
re-add syncpack
sofisl Mar 9, 2026
3eaaae2
revert all the package.json fixes
sofisl Mar 9, 2026
9f01780
chore: revert all the package.jsons
sofisl Mar 9, 2026
06da790
chore: update nock
sofisl Mar 9, 2026
cced820
revert changes to syncpack
sofisl Mar 9, 2026
bdee41e
run lint
sofisl Mar 9, 2026
8bb2e1f
Increase timeout for system tests
sofisl Mar 9, 2026
566da68
chore: only test
sofisl Mar 10, 2026
e96b7e2
update gcx
sofisl Mar 10, 2026
aa3152c
retry
sofisl Mar 10, 2026
09fd126
retry
sofisl Mar 10, 2026
e064662
retry
sofisl Mar 11, 2026
519186c
chore: get url dynamically
sofisl Mar 11, 2026
b77c157
add bucket
sofisl Mar 11, 2026
3f3fc20
retry
sofisl Mar 11, 2026
0680423
rerun tests
sofisl Mar 11, 2026
016e7d0
retry
sofisl Mar 11, 2026
8664bcc
remove bucket name
sofisl Mar 11, 2026
6446ef8
chore: add fixes for gcp metadata
sofisl Mar 11, 2026
a0a91e4
Increase timeout for system tests
sofisl Mar 11, 2026
c694556
test: replace gcx with gcloud CLI in system tests to avoid 403 Forbidden
sofisl Mar 11, 2026
108a59c
chore: remove unused gcx dependency
sofisl Mar 11, 2026
31959d2
ci: fix gcloud path in Dockerfile
sofisl Mar 11, 2026
1331d05
ci: improve gcloud install and add python symlink in Dockerfile
sofisl Mar 11, 2026
4ca24d1
test: add defensive logging for gcloud path in system tests
sofisl Mar 11, 2026
e0a5ca9
ignore tests while in dev
sofisl Mar 11, 2026
678c129
update cloudbuild
sofisl Mar 12, 2026
a1c8d0e
retry
sofisl Mar 12, 2026
35b20a5
retry yaml
sofisl Mar 12, 2026
d176538
retry
sofisl Mar 12, 2026
1f033f5
retry
sofisl Mar 12, 2026
6f926eb
rerun system tests
sofisl Mar 12, 2026
175e34c
chore: cleanup PR
sofisl Mar 12, 2026
0fb4a2f
chore: revert package.json
sofisl Mar 12, 2026
bbe0df5
retry cloudbuild credentials
sofisl Mar 12, 2026
0b0e017
run tests
sofisl Mar 12, 2026
1a0a2a7
run tests
sofisl Mar 12, 2026
828d2e5
chore: retry
sofisl Mar 12, 2026
7fb6caf
chore: fix unit and sytsem tests
sofisl Mar 12, 2026
be22cf6
run tests
sofisl Mar 12, 2026
fd00d90
run tests
sofisl Mar 12, 2026
1c45c49
chore: fix system tests
sofisl Mar 12, 2026
a3140ab
retry issue with cloudbuild yaml
sofisl Mar 12, 2026
ac905cf
retry reverting gapic showcase issues
sofisl Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions ci/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
ARG NODE_VERSION=16
ARG FLAKYBOT_VERSION=1.1.0

FROM node:${NODE_VERSION}-alpine as build
FROM node:${NODE_VERSION}-slim as build

RUN apk add --no-cache curl tar python3
RUN apt-get update && apt-get install -y curl tar python3

# Install gcloud
RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz

RUN mkdir -p /usr/local/gcloud \
&& tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
&& /usr/local/gcloud/google-cloud-sdk/install.sh
&& /usr/local/gcloud/google-cloud-sdk/install.sh --quiet --usage-reporting=false

RUN ln -s /usr/bin/python3 /usr/bin/python

# Download flakybot release
RUN curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-${FLAKYBOT_VERSION}/flakybot \
Expand All @@ -34,16 +36,14 @@ RUN curl https://github.com/googleapis/repo-automation-bots/releases/download/fl
ENV PNPM_VERSION=7.32.2
RUN curl https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -

FROM node:${NODE_VERSION}-alpine

# Hack for not found error with flakybot
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
FROM node:${NODE_VERSION}-slim

COPY --from=build /usr/local/gcloud /usr/local/gcloud
COPY --from=build /bin/flakybot /bin/flakybot
COPY --from=build /root/.local/share/pnpm /root/.local/share/pnpm

RUN apk add --no-cache git bash python3
RUN apt-get update && apt-get install -y git bash python3 \
&& ln -s /usr/bin/python3 /usr/bin/python

ENV PNPM_HOME=/root/.local/share/pnpm
ENV PATH=$PNPM_HOME:/bin/flakybot:usr/local/gcloud/google-cloud-sdk/bin:$PATH
ENV PATH=$PNPM_HOME:/bin/flakybot:/usr/local/gcloud/google-cloud-sdk/bin:$PATH
17 changes: 5 additions & 12 deletions ci/cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

options:
dynamic_substitutions: true
# Increased from default to 8 vCPUs / 8GB RAM to prevent OOM/silent crashes
machineType: 'E2_HIGHCPU_32'
diskSizeGb: '100'

substitutions:
_BUILD_TYPE: "presubmit"
Expand All @@ -26,17 +29,6 @@ logsBucket: 'gs://${_LOGS_BUCKET}/logs/google-cloud-node-core/${_BUILD_TYPE}/${C
timeout: 32400s

steps:
- name: 'gcr.io/kaniko-project/executor:v1.24.0'
args: [
'--log-format=text',
'--context=dir:///workspace/testing',
'--build-arg=NODE_VERSION=${_NODE_VERSION}',
'--dockerfile=ci/Dockerfile',
'--cache=true',
'--destination=gcr.io/${PROJECT_ID}/google-cloud-node-core-${_NODE_VERSION}',
'--push-retry=3',
'--image-fs-extract-retry=3'
]
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: "bash"
args: ["ci/deletecloudbuild.sh"]
Expand All @@ -53,4 +45,5 @@ steps:
- 'PROJECT_ID=$PROJECT_ID'
- 'REPO_OWNER=${_REPO_OWNER}'
- 'REPO_NAME=${_REPO_NAME}'
- 'COMMIT_SHA=$COMMIT_SHA'
- 'COMMIT_SHA=$COMMIT_SHA'
- 'PATH=/usr/local/gcloud/google-cloud-sdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
14 changes: 2 additions & 12 deletions ci/cloudbuild_with_credentials.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ logsBucket: 'gs://${_LOGS_BUCKET}/logs/google-cloud-node-core/${_BUILD_TYPE}/${C
timeout: 7200s

steps:
- name: 'gcr.io/kaniko-project/executor:v1.9.1'
args: [
'--log-format=text',
'--context=dir:///workspace/testing',
'--build-arg=NODE_VERSION=${_NODE_VERSION}',
'--dockerfile=ci/Dockerfile',
'--cache=true',
'--destination=gcr.io/${PROJECT_ID}/google-cloud-node-core-${_NODE_VERSION}',
'--push-retry=3',
'--image-fs-extract-retry=3'
]
- name: gcr.io/cloud-builders/gcloud
entrypoint: 'bash'
args: [ '-c', "gcloud secrets versions access latest --project=cloud-devrel-kokoro-resources --secret=long-door-651-kokoro-system-test-service-account --format='get(payload.data)' | tr '_-' '/+' | base64 -d > /workspace/google_application_credentials.json" ]
Expand All @@ -50,4 +39,5 @@ steps:
- 'PROJECT_ID=$PROJECT_ID'
- 'REPO_OWNER=${_REPO_OWNER}'
- 'REPO_NAME=${_REPO_NAME}'
- 'COMMIT_SHA=$COMMIT_SHA'
- 'COMMIT_SHA=$COMMIT_SHA'
- 'PATH=/usr/local/gcloud/google-cloud-sdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
9 changes: 6 additions & 3 deletions ci/cloudbuild_with_gapic_showcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ steps:
args: ['clone', 'https://github.com/googleapis/gapic-showcase.git']

- id: 'Build Showcase'
name: 'golang:1.24'
entrypoint: 'go'
args: ['install', './cmd/gapic-showcase']
name: 'golang:1.25'
entrypoint: 'sh'
args: ['-c', 'mkdir -p /workspace/bin && CGO_ENABLED=0 go build -v -o /workspace/bin/gapic-showcase ./cmd/gapic-showcase && ls -l /workspace/bin/gapic-showcase']
dir: 'gapic-showcase'
env:
- 'GOPATH=/workspace'
Expand Down Expand Up @@ -62,6 +62,8 @@ steps:
args:
- '-c'
- |
echo "Verifying gapic-showcase binary..."
ls -l /workspace/bin/gapic-showcase || echo "BINARY NOT FOUND IN /workspace/bin"
echo "Starting gapic-showcase server in background..."
/workspace/bin/gapic-showcase run &
echo "Waiting for server at localhost:7469..."
Expand All @@ -75,6 +77,7 @@ steps:
env:
- 'BUILD_TYPE=${_BUILD_TYPE}'
- 'TEST_TYPE=${_TEST_TYPE}'
- 'GAPIC_SHOWCASE_PATH=/workspace/bin/gapic-showcase'
- 'BUILD_ID=$BUILD_ID'
- 'PROJECT_ID=$PROJECT_ID'
- 'REPO_OWNER=${_REPO_OWNER}'
Expand Down
16 changes: 14 additions & 2 deletions packages/gax/test/showcase-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,20 @@ export class ShowcaseServer {
process.chdir(testDir);
console.log(`Server will be run from ${testDir}.`);

await download(fallbackServerUrl, testDir);
await execa('tar', ['xzf', tarballFilename]);
const prebuiltPath =
process.env['GAPIC_SHOWCASE_PATH'] || '/workspace/bin/gapic-showcase';
if (fs.existsSync(prebuiltPath)) {
console.log(`Using pre-built gapic-showcase binary from ${prebuiltPath}`);
await fsp.copyFile(prebuiltPath, path.join(testDir, 'gapic-showcase'));
await fsp.chmod(path.join(testDir, 'gapic-showcase'), 0o755);
} else {
console.log(
`Pre-built binary not found at ${prebuiltPath}. Downloading...`
);
await download(fallbackServerUrl, testDir);
await execa('tar', ['xzf', tarballFilename]);
}

const childProcess = execa(binaryName, ['run'], {
cwd: testDir,
stdio: 'inherit',
Expand Down
2 changes: 1 addition & 1 deletion packages/gaxios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"multiparty": "^4.2.1",
"mv": "^2.1.1",
"ncp": "^2.0.0",
"nock": "^14.0.5",
"nock": "14.0.5",
"null-loader": "^4.0.1",
"pack-n-play": "^4.0.0",
"puppeteer": "^24.0.0",
Expand Down
1 change: 0 additions & 1 deletion packages/gcp-metadata/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"chai": "^4.3.10",
"cross-env": "^7.0.3",
"gcbuild": "^1.3.39",
"gcx": "^2.0.27",
"gts": "^6.0.2",
"jsdoc": "^4.0.4",
"jsdoc-fresh": "^5.0.0",
Expand Down
17 changes: 1 addition & 16 deletions packages/gcp-metadata/system-test/fixtures/hook/.gcloudignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
node_modules
.git
.gitignore

node_modules
#!include:.gitignore

test/
10 changes: 10 additions & 0 deletions packages/gcp-metadata/system-test/fixtures/hook/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@

const gcpMetadata = require('gcp-metadata');

// Log availability on startup to allow verification via logs
(async () => {
try {
const isAvailable = await gcpMetadata.isAvailable();
console.log(`GCF_METADATA_CHECK: isAvailable=${isAvailable}`);
} catch (e) {
console.error(`GCF_METADATA_CHECK: error=${e.message}`);
}
})();

exports.getMetadata = async (req, res) => {
const isAvailable = await gcpMetadata.isAvailable();
const instance = await gcpMetadata.instance();
Expand Down
124 changes: 94 additions & 30 deletions packages/gcp-metadata/system-test/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@ import assert from 'assert';
import {before, after, describe, it} from 'mocha';
import fs from 'fs';
import * as gcbuild from 'gcbuild';
import {CloudFunctionsServiceClient} from '@google-cloud/functions';
import {v2, CloudFunctionsServiceClient} from '@google-cloud/functions';
import * as path from 'path';
import {promisify} from 'util';
import {execSync} from 'child_process';
import {request} from 'gaxios';

const loadGcx = () => import('gcx');

const copy = promisify(fs.copyFile);
const pkg = require('../../package.json'); // eslint-disable-line

let gcf: CloudFunctionsServiceClient;
let gcfV2: v2.FunctionServiceClient;
let projectId: string;
const shortPrefix = 'gcloud-tests';
const randomUUID = () =>
Expand All @@ -41,7 +40,10 @@ describe('gcp metadata', () => {
// pack up the gcp-metadata module and copy to the target dir
await packModule();
gcf = new CloudFunctionsServiceClient();
gcfV2 = new v2.FunctionServiceClient();
projectId = await gcf.auth.getProjectId();
console.log(`Using Project ID: ${projectId}`);
console.log(`Function Name: ${fullPrefix}`);
});

describe('cloud functions', () => {
Expand All @@ -51,23 +53,60 @@ describe('gcp metadata', () => {

// deploy the function to GCF
await deployApp();
// cloud functions now require authentication by default, see:
// https://cloud.google.com/functions/docs/release-notes
await gcf.setIamPolicy({
resource: `projects/${projectId}/locations/us-central1/functions/${fullPrefix}`,
policy: {
bindings: [
{members: ['allUsers'], role: 'roles/cloudfunctions.invoker'},
],
},
});
});

it('should access the metadata service on GCF', async () => {
const url = `https://us-central1-${projectId}.cloudfunctions.net/${fullPrefix}`;
const res = await request<{isAvailable: boolean}>({url});
console.dir(res.data);
assert.strictEqual(res.data.isAvailable, true);
// Fetch the function metadata
const name = `projects/${projectId}/locations/us-central1/functions/${fullPrefix}`;
const [func] = await gcfV2.getFunction({name});

// 2nd Gen URLs are stored in serviceConfig.uri
const url = func.serviceConfig?.uri;

if (!url) {
throw new Error(
`Could not find URI for function: ${fullPrefix}. Is it a Gen 2 function?`,
);
}

console.log(`Verifying Gen 2 function via logs: ${fullPrefix}`);

// Poll for the log entry
let found = false;
const maxRetries = 20;
const filter = `resource.type="cloud_run_revision" AND resource.labels.service_name="${fullPrefix}" AND textPayload:"GCF_METADATA_CHECK"`;
const cmd = `gcloud logging read '${filter}' --project=${projectId} --format="json" --limit=5`;

console.log(`Polling for logs with command: ${cmd}`);

for (let i = 0; i < maxRetries; i++) {
process.stdout.write('.');
try {
const output = execSync(cmd).toString();
const logs = JSON.parse(output);
if (logs && logs.length > 0) {
console.log('\nFound log entries:');
console.dir(logs, {depth: null});
const latestLog = logs[0].textPayload;
assert.ok(
latestLog.includes('isAvailable=true'),
`Metadata check failed: ${latestLog}`,
);
found = true;
break;
}
} catch (e) {
console.error(`\nError reading logs: ${(e as any).message}`);
}
await new Promise(resolve => setTimeout(resolve, 5000));
}

if (!found) {
throw new Error(
`Could not find GCF_METADATA_CHECK log entry for ${fullPrefix} after ${maxRetries} retries.`,
);
}
console.log('\nSuccessfully verified metadata access via logs.');
});

after(() => pruneFunctions(true));
Expand Down Expand Up @@ -98,12 +137,12 @@ describe('gcp metadata', () => {
*/
async function pruneFunctions(sessionOnly: boolean) {
console.log('Pruning leaked functions...');
const [fns] = await gcf.listFunctions({
const [fns] = await gcfV2.listFunctions({
parent: `projects/${projectId}/locations/-`,
});
await Promise.all(
fns
.filter(fn => {
.filter((fn: any) => {
if (sessionOnly) {
return fn.name!.includes(fullPrefix);
}
Expand All @@ -112,8 +151,8 @@ async function pruneFunctions(sessionOnly: boolean) {
const minutesSinceUpdate = (currentDate - updateDate) / 1000 / 60;
return minutesSinceUpdate > 60 && fn.name!.includes(shortPrefix);
})
.map(async fn => {
await gcf.deleteFunction({name: fn.name}).catch(e => {
.map(async (fn: any) => {
await gcfV2.deleteFunction({name: fn.name}).catch((e: any) => {
console.error(`There was a problem deleting function ${fn.name}.`);
console.error(e);
});
Expand All @@ -126,15 +165,40 @@ async function pruneFunctions(sessionOnly: boolean) {
*/
async function deployApp() {
const targetDir = path.join(__dirname, '../../system-test/fixtures/hook');
const gcx = await loadGcx();
await gcx.deploy({
name: fullPrefix,
entryPoint: 'getMetadata',
triggerHTTP: true,
runtime: 'nodejs20',
region: 'us-central1',
targetDir,
});
const files = fs.readdirSync(targetDir);
console.log(`Files to package: ${files.join(', ')}`);

console.log(`PATH: ${process.env.PATH}`);
try {
const whichGcloud = execSync('which gcloud').toString().trim();
console.log(`Using gcloud at: ${whichGcloud}`);
} catch (e) {
console.error('gcloud CLI not found in PATH');
}

console.log(
`Deploying function ${fullPrefix} from ${targetDir} using gcloud...`,
);
const cmd =
`gcloud functions deploy ${fullPrefix} ` +
'--gen2 ' +
'--region=us-central1 ' +
'--runtime=nodejs20 ' +
`--source=${targetDir} ` +
'--entry-point=getMetadata ' +
'--ingress-settings=internal-only ' +
'--allow-unauthenticated ' +
'--trigger-http ' +
`--project=${projectId} ` +
'--quiet';

try {
execSync(cmd, {stdio: 'inherit'});
console.log(`Successfully deployed ${fullPrefix}`);
} catch (error) {
console.error(`Deployment failed: ${(error as any).message}`);
throw error;
}
}

/**
Expand Down
Loading
Loading