119 lines
3.6 KiB
JavaScript
Executable file
119 lines
3.6 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
import fs from 'node:fs'
|
|
import url from 'node:url'
|
|
import path from 'node:path'
|
|
|
|
import { CloudFront } from '@aws-sdk/client-cloudfront'
|
|
import { S3 } from '@aws-sdk/client-s3'
|
|
import { Upload } from '@aws-sdk/lib-storage'
|
|
import mime from 'mime-types'
|
|
import readDir from 'recursive-readdir'
|
|
|
|
import pkg from '../lerna.json' with { type: 'json' }
|
|
|
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
|
|
|
|
const region = 'eu-west-1'
|
|
const PKG_VERSION = pkg.version
|
|
const PRODUCTION_VERSION = 'v9'
|
|
const DISTRIBUTION_ID = process.env.DISTRIBUTION_ID
|
|
const BUCKET_NAME = 'webdriver.io'
|
|
const BUILD_DIR = path.resolve(__dirname, '..', 'website', 'build')
|
|
const UPLOAD_OPTIONS = { partSize: 10 * 1024 * 1024, queueSize: 1 }
|
|
const IGNORE_FILE_SUFFIX = ['*.rb']
|
|
|
|
const timestamp = Date.now()
|
|
const s3 = new S3({ region })
|
|
const files: string[] = await readDir(BUILD_DIR, IGNORE_FILE_SUFFIX)
|
|
|
|
const version = `v${PKG_VERSION.split('.')[0]}`
|
|
const bucketName = version === PRODUCTION_VERSION ? BUCKET_NAME : `${version}.${BUCKET_NAME}`
|
|
|
|
/**
|
|
* Split array in series
|
|
* @param list array to split
|
|
* @param size size of each chunk
|
|
* @returns array of chunks
|
|
*/
|
|
function splitInSeries<T>(list: T[], size: number): T[][] {
|
|
const result: T[][] = []
|
|
|
|
for (let i = 0; i < list.length; i += size) {
|
|
result.push(list.slice(i, i + size))
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* upload assets
|
|
*/
|
|
console.log(`Uploading ${BUILD_DIR} to S3 bucket ${bucketName}`)
|
|
for (const filesBatch of splitInSeries(files, 10)) {
|
|
await Promise.all(filesBatch.map(async (file) => {
|
|
try {
|
|
const mimeType = mime.lookup(file)
|
|
if (!mimeType) {
|
|
throw new Error(`Couldn't find mime type for ${file}`)
|
|
}
|
|
|
|
const res = await new Upload({
|
|
client: s3,
|
|
params: {
|
|
Bucket: bucketName,
|
|
Key: file.replace(BUILD_DIR + '/', ''),
|
|
Body: fs.createReadStream(file),
|
|
ContentType: mimeType,
|
|
ACL: 'public-read',
|
|
},
|
|
...UPLOAD_OPTIONS
|
|
}).done()
|
|
console.log(`${file} uploaded`)
|
|
return res
|
|
} catch (err) {
|
|
console.error(`Couldn't upload file ${file}: ${(err as Error).stack}`)
|
|
throw err
|
|
}
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* invalidate distribution
|
|
*/
|
|
const distributionId = version === PRODUCTION_VERSION
|
|
? DISTRIBUTION_ID
|
|
: process.env[`DISTRIBUTION_ID_${version.toUpperCase()}`]
|
|
if (distributionId) {
|
|
console.log(`Invalidate objects from distribution ${distributionId}`)
|
|
const cloudfront = new CloudFront({ region })
|
|
const { Invalidation } = await cloudfront.createInvalidation({
|
|
DistributionId: distributionId,
|
|
InvalidationBatch: {
|
|
CallerReference: `${timestamp}`,
|
|
Paths: { Quantity: 1, Items: ['/*'] }
|
|
}
|
|
})
|
|
console.log(`Created new invalidation with ID ${Invalidation?.Id}`)
|
|
}
|
|
|
|
/**
|
|
* delete old assets
|
|
*/
|
|
const objects = await s3.listObjects({
|
|
Bucket: bucketName
|
|
})
|
|
if (!objects.Contents) {
|
|
throw new Error('Couldn\'t find any objects')
|
|
}
|
|
const objectsToDelete = objects.Contents.filter((obj) => obj.LastModified && obj.LastModified.getTime() < timestamp)
|
|
console.log(`Found ${objectsToDelete.length} outdated objects to remove...`)
|
|
|
|
await Promise.all(objectsToDelete.map((obj) => (
|
|
s3.deleteObject({
|
|
Bucket: bucketName,
|
|
Key: obj.Key
|
|
})
|
|
)))
|
|
console.log('Deleted obsolete items successfully')
|
|
console.log('Successfully updated webdriver.io docs')
|