Skip to content

Commit e495015

Browse files
authored
Ensure AuthClient is cached (#373)
Closes #364 /cc @GregoireW @danielbankhead could you please test this? @verbanicm hold on merge until further testing.
1 parent 355876e commit e495015

File tree

5 files changed

+53
-15
lines changed

5 files changed

+53
-15
lines changed

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
StorageOptions,
2424
UploadOptions,
2525
} from '@google-cloud/storage';
26+
import { GoogleAuth } from 'google-auth-library';
2627
import { errorMessage, toPlatformPath, toPosixPath } from '@google-github-actions/actions-utils';
2728

2829
import { Metadata } from './headers';
@@ -159,8 +160,27 @@ export interface ClientComputeDestinationOptions {
159160
export class Client {
160161
readonly storage: Storage;
161162

162-
constructor(opts?: ClientOptions) {
163+
static async build(opts?: ClientOptions): Promise<Client> {
164+
const client = new Client(opts);
165+
166+
// We need to force the authClient to cache its internal client. Since all
167+
// our calls are done in parallel, this has to be done as part of
168+
// initialization.
169+
//
170+
// https://github.com/google-github-actions/upload-cloud-storage/issues/364
171+
await client.storage.authClient.getClient();
172+
173+
return client;
174+
}
175+
176+
private constructor(opts?: ClientOptions) {
177+
const authClient = new GoogleAuth({
178+
projectId: opts?.projectID,
179+
universeDomain: opts?.universe,
180+
});
181+
163182
const options: StorageOptions = {
183+
authClient: authClient,
164184
projectId: opts?.projectID,
165185
universeDomain: opts?.universe,
166186
userAgent: userAgent,

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export async function run(): Promise<void> {
163163

164164
// Create the client and upload files.
165165
core.startGroup('Upload files');
166-
const client = new Client({
166+
const client = await Client.build({
167167
projectID: projectID,
168168
universe: universe,
169169
});

tests/client.int.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ test(
6666
});
6767

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

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

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

100100
await suite.test('uploads files with the correct mime type', async () => {
101-
const client = new Client({ projectID: projectID });
101+
const client = await Client.build({ projectID: projectID });
102102
await client.upload({
103103
bucket: testBucket,
104104
files: [
@@ -127,7 +127,7 @@ test(
127127
});
128128

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

141141
await suite.test('uploads a single file without an extension', async () => {
142-
const client = new Client({ projectID: projectID });
142+
const client = await Client.build({ projectID: projectID });
143143
await client.upload({
144144
bucket: testBucket,
145145
files: [{ source: './tests/testdata/testfile', destination: 'testfile' }],
@@ -154,7 +154,7 @@ test(
154154
'uploads a file with unicode characters in the filename',
155155
{ skip: process.platform === 'win32' },
156156
async () => {
157-
const client = new Client({ projectID: projectID });
157+
const client = await Client.build({ projectID: projectID });
158158
await client.upload({
159159
bucket: testBucket,
160160
files: [{ source: './tests/testdata-unicode/🚀', destination: '🚀' }],
@@ -167,7 +167,7 @@ test(
167167
);
168168

169169
await suite.test('uploads a single file with metadata', async () => {
170-
const client = new Client({ projectID: projectID });
170+
const client = await Client.build({ projectID: projectID });
171171
await client.upload({
172172
bucket: testBucket,
173173
files: [{ source: './tests/testdata/test1.txt', destination: 'test1.txt' }],

tests/client.test.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,35 @@ import assert from 'node:assert';
1919

2020
import * as path from 'path';
2121

22+
import { forceRemove, randomFilepath, writeSecureFile } from '@google-github-actions/actions-utils';
23+
2224
import { Client } from '../src/client';
2325
import { Bucket, UploadOptions } from '@google-cloud/storage';
2426

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

2729
describe('Client', { concurrency: true }, async () => {
28-
test('#new', async (suite) => {
30+
test('.build', async (suite) => {
31+
const originalEnv = Object.assign({}, process.env);
32+
const appCreds = {
33+
client_email: 'test-email@example.com',
34+
private_key: 'test-private-key',
35+
};
36+
const appCredsJSON = await writeSecureFile(randomFilepath(), JSON.stringify(appCreds));
37+
38+
suite.beforeEach(async () => {
39+
process.env.GOOGLE_APPLICATION_CREDENTIALS = appCredsJSON;
40+
});
41+
42+
suite.afterEach(async () => {
43+
await forceRemove(appCredsJSON);
44+
process.env = originalEnv;
45+
});
46+
2947
await suite.test('initializes with ADC', async () => {
30-
const client = new Client();
48+
const client = await Client.build();
3149
const result = client?.storage?.authClient?.jsonContent;
32-
assert.deepStrictEqual(result, null);
50+
assert.deepStrictEqual(result, appCreds);
3351
});
3452
});
3553

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

217235
// Do the upload
218-
const client = new Client();
236+
const client = await Client.build();
219237
await client.upload({
220238
bucket: 'my-bucket',
221239
files: [

0 commit comments

Comments
 (0)