Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

22 changes: 21 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
StorageOptions,
UploadOptions,
} from '@google-cloud/storage';
import { GoogleAuth } from 'google-auth-library';
import { errorMessage, toPlatformPath, toPosixPath } from '@google-github-actions/actions-utils';

import { Metadata } from './headers';
Expand Down Expand Up @@ -159,8 +160,27 @@ export interface ClientComputeDestinationOptions {
export class Client {
readonly storage: Storage;

constructor(opts?: ClientOptions) {
static async build(opts?: ClientOptions): Promise<Client> {
const client = new Client(opts);

// We need to force the authClient to cache its internal client. Since all
// our calls are done in parallel, this has to be done as part of
// initialization.
//
// https://github.com/google-github-actions/upload-cloud-storage/issues/364
await client.storage.authClient.getClient();

return client;
}

private constructor(opts?: ClientOptions) {
const authClient = new GoogleAuth({
projectId: opts?.projectID,
universeDomain: opts?.universe,
});

const options: StorageOptions = {
authClient: authClient,
projectId: opts?.projectID,
universeDomain: opts?.universe,
userAgent: userAgent,
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export async function run(): Promise<void> {

// Create the client and upload files.
core.startGroup('Upload files');
const client = new Client({
const client = await Client.build({
projectID: projectID,
universe: universe,
});
Expand Down
16 changes: 8 additions & 8 deletions tests/client.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ test(
});

await suite.test('throws an error on a non-existent bucket', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await assert.rejects(async () => {
await client.upload({
bucket: 'definitely-not-a-real-bucket',
Expand All @@ -76,7 +76,7 @@ test(
});

await suite.test('throws an error on a non-existent file', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await assert.rejects(async () => {
await client.upload({
bucket: testBucket,
Expand All @@ -86,7 +86,7 @@ test(
});

await suite.test('uploads a single file', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [{ source: './tests/testdata/test1.txt', destination: 'test1.txt' }],
Expand All @@ -98,7 +98,7 @@ test(
});

await suite.test('uploads files with the correct mime type', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [
Expand Down Expand Up @@ -127,7 +127,7 @@ test(
});

await suite.test('uploads a single file with prefix', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [{ source: './tests/testdata/test1.txt', destination: 'my/prefix/test1.txt' }],
Expand All @@ -139,7 +139,7 @@ test(
});

await suite.test('uploads a single file without an extension', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [{ source: './tests/testdata/testfile', destination: 'testfile' }],
Expand All @@ -154,7 +154,7 @@ test(
'uploads a file with unicode characters in the filename',
{ skip: process.platform === 'win32' },
async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [{ source: './tests/testdata-unicode/🚀', destination: '🚀' }],
Expand All @@ -167,7 +167,7 @@ test(
);

await suite.test('uploads a single file with metadata', async () => {
const client = new Client({ projectID: projectID });
const client = await Client.build({ projectID: projectID });
await client.upload({
bucket: testBucket,
files: [{ source: './tests/testdata/test1.txt', destination: 'test1.txt' }],
Expand Down
26 changes: 22 additions & 4 deletions tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,35 @@ import assert from 'node:assert';

import * as path from 'path';

import { forceRemove, randomFilepath, writeSecureFile } from '@google-github-actions/actions-utils';

import { Client } from '../src/client';
import { Bucket, UploadOptions } from '@google-cloud/storage';

import { mockUpload } from './helpers.test';

describe('Client', { concurrency: true }, async () => {
test('#new', async (suite) => {
test('.build', async (suite) => {
const originalEnv = Object.assign({}, process.env);
const appCreds = {
client_email: 'test-email@example.com',
private_key: 'test-private-key',
};
const appCredsJSON = await writeSecureFile(randomFilepath(), JSON.stringify(appCreds));

suite.beforeEach(async () => {
process.env.GOOGLE_APPLICATION_CREDENTIALS = appCredsJSON;
});

suite.afterEach(async () => {
await forceRemove(appCredsJSON);
process.env = originalEnv;
});

await suite.test('initializes with ADC', async () => {
const client = new Client();
const client = await Client.build();
const result = client?.storage?.authClient?.jsonContent;
assert.deepStrictEqual(result, null);
assert.deepStrictEqual(result, appCreds);
});
});

Expand Down Expand Up @@ -215,7 +233,7 @@ describe('Client', { concurrency: true }, async () => {
const uploadMock = t.mock.method(Bucket.prototype, 'upload', mockUpload);

// Do the upload
const client = new Client();
const client = await Client.build();
await client.upload({
bucket: 'my-bucket',
files: [
Expand Down