From aa65d0afa857f17631bdbfa6837c08d0b210cd91 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Fri, 23 Aug 2024 15:58:31 -0600 Subject: [PATCH] Allow passing gcloudignore path and fix root computation (#376) - Fixes https://github.com/google-github-actions/upload-cloud-storage/issues/336 - Fixes https://github.com/google-github-actions/upload-cloud-storage/issues/357 --------- Co-authored-by: Eddie Lin --- action.yml | 10 ++++++++++ src/main.ts | 11 ++++++----- tests/client.test.ts | 2 ++ tests/main.test.ts | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 99a4e7de..a7ef8870 100644 --- a/action.yml +++ b/action.yml @@ -160,6 +160,16 @@ inputs: required: false default: '100' + gcloudignore_path: + description: |- + Path to a gcloudignore file within the repository. + + ```yaml + gcloudignore_path: '.gcloudignore.dev' + ``` + required: false + default: '.gcloudignore' + process_gcloudignore: description: |- Process a `.gcloudignore` file present in the top-level of the repository. diff --git a/src/main.ts b/src/main.ts index b60f720b..d28cc8a1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -71,6 +71,7 @@ export async function run(): Promise { const predefinedAcl = predefinedAclInput === '' ? undefined : (predefinedAclInput as PredefinedAcl); const headersInput = core.getInput('headers'); + const gcloudIgnorePath = core.getInput('gcloudignore_path') || '.gcloudignore'; const processGcloudIgnore = parseBoolean(core.getInput('process_gcloudignore')); const metadata = headersInput === '' ? {} : parseHeadersInput(headersInput); @@ -89,18 +90,18 @@ export async function run(): Promise { // - Format all files to be posix relative to input.path // - Filter out items that match if (processGcloudIgnore) { - core.debug(`Processing gcloudignore`); + core.debug(`Processing gcloudignore at ${gcloudIgnorePath}`); const ignores = ignore(); // Look for a .gcloudignore in the repository root. const githubWorkspace = process.env.GITHUB_WORKSPACE; if (githubWorkspace) { - const gcloudIgnorePath = path.join(githubWorkspace, '.gcloudignore'); - const ignoreList = await parseGcloudIgnore(gcloudIgnorePath); + const gcloudIgnorePathAbs = path.join(githubWorkspace, gcloudIgnorePath); + const ignoreList = await parseGcloudIgnore(gcloudIgnorePathAbs); if (ignoreList && ignoreList.length) { - core.debug(`Using .gcloudignore at: ${gcloudIgnorePath}`); + core.debug(`Using .gcloudignore at: ${gcloudIgnorePathAbs}`); core.debug(`Parsed ignore list: ${JSON.stringify(ignoreList)}`); ignores.add(ignoreList); @@ -113,7 +114,7 @@ export async function run(): Promise { } for (let i = 0; i < files.length; i++) { - const name = files[i]; + const name = path.join(root, files[i]); try { if (ignores.ignores(name)) { core.debug(`Ignoring ${name} because of ignore file`); diff --git a/tests/client.test.ts b/tests/client.test.ts index ccb87ac9..7f8a18a1 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -23,6 +23,7 @@ import { forceRemove, randomFilepath, writeSecureFile } from '@google-github-act import { Client } from '../src/client'; import { Bucket, UploadOptions } from '@google-cloud/storage'; +import { GoogleAuth } from 'google-auth-library'; import { mockUpload } from './helpers.test'; @@ -231,6 +232,7 @@ describe('Client', { concurrency: true }, async () => { test('#upload', async (suite) => { await suite.test('calls uploadFile', async (t) => { const uploadMock = t.mock.method(Bucket.prototype, 'upload', mockUpload); + t.mock.method(GoogleAuth.prototype, 'getClient', () => {}); // Do the upload const client = await Client.build(); diff --git a/tests/main.test.ts b/tests/main.test.ts index b2e534aa..0eb7ef95 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -24,6 +24,7 @@ import { promises as fs } from 'fs'; import * as core from '@actions/core'; import { clearEnv, forceRemove, setInputs } from '@google-github-actions/actions-utils'; import { Bucket, UploadOptions } from '@google-cloud/storage'; +import { GoogleAuth } from 'google-auth-library'; import { mockUpload } from './helpers.test'; @@ -47,6 +48,9 @@ test('#run', { concurrency: true }, async (suite) => { suite.mock.method(core, 'endGroup', () => {}); suite.mock.method(core, 'addPath', () => {}); suite.mock.method(core, 'exportVariable', () => {}); + + // We do not care about authentication in the unit tests + suite.mock.method(GoogleAuth.prototype, 'getClient', () => {}); }); suite.beforeEach(async () => { @@ -194,7 +198,41 @@ test('#run', { concurrency: true }, async (suite) => { }); // Add gcloudignore - await fs.writeFile(path.join(githubWorkspace, '.gcloudignore'), '*.txt'); + await fs.writeFile(path.join(githubWorkspace, '.gcloudignore'), 'testdata/**/*.txt'); + + await run(); + + // Check call sites + const uploadedFiles = uploadMock.mock.calls.map((call) => call?.arguments?.at(0)); + assert.deepStrictEqual(uploadedFiles, [ + path.join(githubWorkspace, 'testdata', 'test.css'), + path.join(githubWorkspace, 'testdata', 'test.js'), + path.join(githubWorkspace, 'testdata', 'test.json'), + path.join(githubWorkspace, 'testdata', 'testfile'), + ]); + + // Check arguments + const call = uploadMock.mock.calls.at(0)?.arguments?.at(1) as UploadOptions; + assert.deepStrictEqual(call?.destination, 'sub/path/testdata/test.css'); + }); + + await suite.test('processes a custom gcloudignore path', async (t) => { + const uploadMock = t.mock.method(Bucket.prototype, 'upload', mockUpload); + const gcloudIgnorePath = path.join(githubWorkspace, '.gcloudignore-other'); + + setInputs({ + path: './testdata', + destination: 'my-bucket/sub/path', + gzip: 'true', + resumable: 'true', + parent: 'true', + concurrency: '10', + process_gcloudignore: 'true', + gcloudignore_path: '.gcloudignore-other', + }); + + // Add gcloudignore + await fs.writeFile(gcloudIgnorePath, 'testdata/**/*.txt'); await run();