diff --git a/README.md b/README.md index 67d5c85..e7a95f5 100644 --- a/README.md +++ b/README.md @@ -62,10 +62,29 @@ options with `accessKeyName` and `secretAccessKeyName`. | `awsAccessKeyName` | Environmental variable name that is used to override `AWS_ACCESS_KEY_ID` | | | | `awsSecretAccessKeyName` | Environmental variable name that is used to override `AWS_SECRET_ACCESS_KEY` | | | | `s3Bucket` | S3 bucket configuration can be defined per git branch or a single bucket | | ✓ | +| `objectACL` | S3 object ACL ("private"|"public-read"|"public-read-write"|"authenticated-read"...) | | | | `directoryPath` | Path to directory which will be uploaded to the bucket | | ✓ | | `removeDirectoryRoot` | Flag that determines will the root directory of the given `directoryPath` be removed | false | | | `removeDiff` | Flag that determines will the file diff which should be uploaded vs files already on s3 will be deleted | true | | + +#### `s3Bucket option` + +The s3Bucket name can contain variable, is is parsed with [Lodash template](https://lodash.com/docs#template). The following variables are available: + +| Parameter | Description | +| -------------- | ------------------------------------------------------------------------------------ | +| `branch.name` | The branch name. | +| `lastRelease` | `Object` with `version`, `gitTag` and `gitHead` of the last release. | +| `nextRelease` | `Object` with `version`, `gitTag`, `gitHead` and `notes` of the release being done. | + +##### `s3Bucket` examples + +The `s3Bucket` `my-bucket/${nextRelease.version}` will generate push your object to this path: + +> my-bucket/v1.0.0/[your-directory-content] + + ### Example ```json @@ -80,6 +99,7 @@ options with `accessKeyName` and `secretAccessKeyName`. "awsAccessKeyName": "ACCESS_KEY_ENV_VARIABLE_NAME", "awsSecretAccessKeyName": "SECRET_ACCESS_KEY_ENV_VARIABLE_NAME", "s3Bucket": "s3-bucket-name", + "objectACL": "public-read", "directoryPath": "directoryName/**/*", "removeDirectoryRoot": true, "removeDiff": false diff --git a/package.json b/package.json index fc823eb..4ea7862 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "aggregate-error": "^3.1.0", "aws-sdk": "^2.1325.0", "globby": "^11.1.0", + "lodash.template": "^4.5.0", "mime-types": "^2.1.35" }, "devDependencies": { @@ -60,6 +61,7 @@ "@semantic-release/github": "^8.0.7", "@semantic-release/npm": "^9.0.2", "@semantic-release/release-notes-generator": "^10.0.3", + "@types/lodash.template": "^4.5.1", "@types/mime-types": "^2.1.1", "@types/semantic-release": "^20.0.1", "commitizen": "^4.3.0", diff --git a/src/aws.ts b/src/aws.ts index 7988d2b..0e96e60 100644 --- a/src/aws.ts +++ b/src/aws.ts @@ -9,6 +9,7 @@ import { import type { ListObjectsV2Request, ManagedUpload, + ObjectCannedACL, PutObjectRequest, } from 'aws-sdk/clients/s3' import type { Context } from 'semantic-release' @@ -94,8 +95,9 @@ export class AWS { ) } - public async uploadFile(bucket: string, key: string, body: ReadStream, objectMimeType: string) { + public async uploadFile(bucket: string, key: string, body: ReadStream, objectMimeType: string, objectACL?: ObjectCannedACL) { const uploadParams: PutObjectRequest = { + ACL: objectACL, Body: body, Bucket: bucket, ContentType: objectMimeType, diff --git a/src/publish.ts b/src/publish.ts index b2fdc2e..079af79 100644 --- a/src/publish.ts +++ b/src/publish.ts @@ -2,6 +2,7 @@ import fs from 'fs' import * as path from 'path' import globby from 'globby' +import template from 'lodash.template' import mime from 'mime-types' import type { Context } from 'semantic-release' @@ -27,10 +28,18 @@ export async function publish(config: PluginConfig, context: Context) { s3Bucket = config.s3Bucket[context.branch.name] } + const s3BucketWithResolvedVariables = template(s3Bucket)( + { + branch: context.branch.name, + lastRelease: context.lastRelease, + nextRelease: context.nextRelease, + } + ) + const [ bucketName, ...bucketPrefixes - ] = s3Bucket?.split(path.sep) ?? [] + ] = s3BucketWithResolvedVariables.split(path.sep) const bucketPrefix = bucketPrefixes.join(path.sep).replace(/\$([_a-z]+\w*)|\$\{(\w*)\}/giu, (match, p1, p2) => { return process.env[p1 || p2] ?? match @@ -80,7 +89,8 @@ export async function publish(config: PluginConfig, context: Context) { bucketName, path.join(bucketPrefix, removedRootFilesPaths[index] ?? filePath), fs.createReadStream(filePath), - mimeType + mimeType, + config.objectACL ) }), ) diff --git a/src/types.ts b/src/types.ts index 5d6bc66..90a6b8a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,4 @@ +import type { ObjectCannedACL } from 'aws-sdk/clients/s3' import type { Config } from 'semantic-release' export interface PluginConfig extends Config { @@ -19,6 +20,12 @@ export interface PluginConfig extends Config { * @default "" */ readonly directoryPath: string + /** + * Object ACL + * + * @default "" + */ + readonly objectACL?: ObjectCannedACL /** * if true, all files which are on remote but not staged for upload will be deleted * diff --git a/yarn.lock b/yarn.lock index 8cc9a82..25f96ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1280,6 +1280,7 @@ __metadata: "@semantic-release/github": ^8.0.7 "@semantic-release/npm": ^9.0.2 "@semantic-release/release-notes-generator": ^10.0.3 + "@types/lodash.template": ^4.5.1 "@types/mime-types": ^2.1.1 "@types/semantic-release": ^20.0.1 aggregate-error: ^3.1.0 @@ -1290,6 +1291,7 @@ __metadata: eslint: ^8.35.0 globby: ^11.1.0 husky: ^8.0.3 + lodash.template: ^4.5.0 mime-types: ^2.1.35 npm-package-json-lint: ^6.4.0 pinst: ^3.0.0 @@ -1581,6 +1583,22 @@ __metadata: languageName: node linkType: hard +"@types/lodash.template@npm:^4.5.1": + version: 4.5.1 + resolution: "@types/lodash.template@npm:4.5.1" + dependencies: + "@types/lodash": "*" + checksum: b2f5726946ca23c366b39608cc6f4ee90cfefc27a2c8b10856f02dc9748b27a565196b8958ad30de90a7ffa4cb449db24cf7e474dc6322cccfce1fabe996cb0f + languageName: node + linkType: hard + +"@types/lodash@npm:*": + version: 4.14.191 + resolution: "@types/lodash@npm:4.14.191" + checksum: ba0d5434e10690869f32d5ea49095250157cae502f10d57de0a723fd72229ce6c6a4979576f0f13e0aa9fbe3ce2457bfb9fa7d4ec3d6daba56730a51906d1491 + languageName: node + linkType: hard + "@types/mime-types@npm:^2.1.1": version: 2.1.1 resolution: "@types/mime-types@npm:2.1.1" @@ -5973,6 +5991,13 @@ __metadata: languageName: node linkType: hard +"lodash._reinterpolate@npm:^3.0.0": + version: 3.0.0 + resolution: "lodash._reinterpolate@npm:3.0.0" + checksum: 06d2d5f33169604fa5e9f27b6067ed9fb85d51a84202a656901e5ffb63b426781a601508466f039c720af111b0c685d12f1a5c14ff8df5d5f27e491e562784b2 + languageName: node + linkType: hard + "lodash.camelcase@npm:^4.3.0": version: 4.3.0 resolution: "lodash.camelcase@npm:4.3.0" @@ -6064,6 +6089,25 @@ __metadata: languageName: node linkType: hard +"lodash.template@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.template@npm:4.5.0" + dependencies: + lodash._reinterpolate: ^3.0.0 + lodash.templatesettings: ^4.0.0 + checksum: ca64e5f07b6646c9d3dbc0fe3aaa995cb227c4918abd1cef7a9024cd9c924f2fa389a0ec4296aa6634667e029bc81d4bbdb8efbfde11df76d66085e6c529b450 + languageName: node + linkType: hard + +"lodash.templatesettings@npm:^4.0.0": + version: 4.2.0 + resolution: "lodash.templatesettings@npm:4.2.0" + dependencies: + lodash._reinterpolate: ^3.0.0 + checksum: 863e025478b092997e11a04e9d9e735875eeff1ffcd6c61742aa8272e3c2cddc89ce795eb9726c4e74cef5991f722897ff37df7738a125895f23fc7d12a7bb59 + languageName: node + linkType: hard + "lodash.uniq@npm:^4.5.0": version: 4.5.0 resolution: "lodash.uniq@npm:4.5.0"