143 lines
4.1 KiB
JavaScript
143 lines
4.1 KiB
JavaScript
import path from 'node:path';
|
|
import fs from 'node:fs';
|
|
|
|
import { SitespeedioPlugin } from '@sitespeed.io/plugin';
|
|
|
|
// Documentation of @google-cloud/storage: https://cloud.google.com/nodejs/docs/reference/storage/2.3.x/Bucket#upload
|
|
import { Storage } from '@google-cloud/storage';
|
|
import { getLogger } from '@sitespeed.io/log';
|
|
import { throwIfMissing } from '../../support/util.js';
|
|
import { recursiveReaddir } from '../../support/fileUtil.js';
|
|
|
|
const log = getLogger('sitespeedio.plugin.gcs');
|
|
|
|
async function uploadLatestFiles(dir, gcsOptions, prefix) {
|
|
const config = {
|
|
projectId: gcsOptions.projectId,
|
|
keyFilename: gcsOptions.key
|
|
};
|
|
|
|
const storage = new Storage(config);
|
|
const bucket = storage.bucket(gcsOptions.bucketname);
|
|
|
|
const files = await recursiveReaddir(dir, true);
|
|
const promises = [];
|
|
|
|
for (let file of files) {
|
|
promises.push(uploadFile(file, bucket, gcsOptions, prefix, dir, true));
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
async function upload(dir, gcsOptions, prefix) {
|
|
const files = await recursiveReaddir(dir);
|
|
const promises = [];
|
|
|
|
const storage = new Storage({
|
|
projectId: gcsOptions.projectId
|
|
});
|
|
|
|
if (gcsOptions.key) {
|
|
storage.keyFilename = gcsOptions.key;
|
|
}
|
|
|
|
const bucket = storage.bucket(gcsOptions.bucketname);
|
|
|
|
for (let file of files) {
|
|
const stats = fs.statSync(file);
|
|
|
|
if (stats.isFile()) {
|
|
promises.push(uploadFile(file, bucket, gcsOptions, prefix, dir));
|
|
} else {
|
|
log.debug(`Will not upload ${file} since it is not a file`);
|
|
}
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
async function uploadFile(
|
|
file,
|
|
bucket,
|
|
gcsOptions,
|
|
prefix,
|
|
baseDir,
|
|
noCacheTime
|
|
) {
|
|
const subPath = path.relative(baseDir, file);
|
|
const fileName = path.join(gcsOptions.path || prefix, subPath);
|
|
|
|
const parameters = {
|
|
public: !!gcsOptions.public,
|
|
destination: fileName,
|
|
resumable: false,
|
|
validation: 'crc32c',
|
|
gzip: !!gcsOptions.gzip,
|
|
metadata: {
|
|
// eslint-disable-next-line unicorn/numeric-separators-style
|
|
cacheControl: 'public, max-age=' + (noCacheTime ? 0 : 31536000)
|
|
}
|
|
};
|
|
|
|
return bucket.upload(file, parameters);
|
|
}
|
|
|
|
export default class GcsPlugin extends SitespeedioPlugin {
|
|
constructor(options, context, queue) {
|
|
super({ name: 'gcs', options, context, queue });
|
|
}
|
|
|
|
open(context, options) {
|
|
this.gcsOptions = options.gcs;
|
|
this.options = options;
|
|
this.make = context.messageMaker('gcs').make;
|
|
throwIfMissing(this.gcsOptions, ['bucketname'], 'gcs');
|
|
this.storageManager = context.storageManager;
|
|
}
|
|
async processMessage(message, queue) {
|
|
if (message.type === 'sitespeedio.setup') {
|
|
// Let other plugins know that the GCS plugin is alive
|
|
queue.postMessage(this.make('gcs.setup'));
|
|
} else if (message.type === 'html.finished') {
|
|
const make = this.make;
|
|
const gcsOptions = this.gcsOptions;
|
|
const baseDir = this.storageManager.getBaseDir();
|
|
|
|
log.info(
|
|
`Uploading ${baseDir} to Google Cloud Storage bucket ${gcsOptions.bucketname}, this can take a while ...`
|
|
);
|
|
|
|
try {
|
|
await upload(
|
|
baseDir,
|
|
gcsOptions,
|
|
this.storageManager.getStoragePrefix()
|
|
);
|
|
if (this.options.copyLatestFilesToBase) {
|
|
const rootPath = path.resolve(baseDir, '..');
|
|
const directoriesAsArray = rootPath.split(path.sep);
|
|
const rootName = directoriesAsArray.at(-1);
|
|
await uploadLatestFiles(rootPath, gcsOptions, rootName);
|
|
}
|
|
log.info('Finished upload to Google Cloud Storage');
|
|
if (gcsOptions.public) {
|
|
log.info(
|
|
'Uploaded results on Google Cloud storage are publicly readable'
|
|
);
|
|
}
|
|
if (gcsOptions.removeLocalResult) {
|
|
fs.rmSync(baseDir, { recursive: true });
|
|
log.debug(`Removed local files and directory ${baseDir}`);
|
|
} else {
|
|
log.debug(
|
|
`Local result files and directories are stored in ${baseDir}`
|
|
);
|
|
}
|
|
} catch (error) {
|
|
queue.postMessage(make('error', error));
|
|
log.error('Could not upload to Google Cloud Storage', error);
|
|
}
|
|
queue.postMessage(make('gcs.finished'));
|
|
}
|
|
}
|
|
}
|