webdriverio/scripts/updateDocs.ts

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')