🌤️
GithubにPushしたファイルをCacheControl付きでS3に自動アップロードする
この記事は何
- GithubにPush(または任意のトリガー)されたファイルを自動的にS3にアップロードするGithub actionは既存のものがある。リンク
- 大変素晴らしい…!
- ただ、こちらのシステムのようにS3に上げたファイルを配信したい場合、適切なCacheControlを付与しておきたい。(付けないとPage Speed Insightさんとかにも怒られるし…)
- もとのactionからfolkして、CacheControlを付けられるものをちゃちゃっと作りました。
結論
こちらに置いてあります。
メモ
もとのアクションに対する追加は下記です。
index.js
index.js
const core = require('@actions/core');
const S3 = require('aws-sdk/clients/s3');
const fs = require('fs');
const path = require('path');
const shortid = require('shortid');
const klawSync = require('klaw-sync');
const { lookup } = require('mime-types');
const AWS_KEY_ID = core.getInput('aws_key_id', {
required: true
});
const SECRET_ACCESS_KEY = core.getInput('aws_secret_access_key', {
required: true
});
const BUCKET = core.getInput('aws_bucket', {
required: true
});
const SOURCE_DIR = core.getInput('source_dir', {
required: true
});
const DESTINATION_DIR = core.getInput('destination_dir', {
required: false
});
+ const CACHE_MAX_AGE = core.getInput('cache_max_age', {
+ required: false
+ })
const s3 = new S3({
accessKeyId: AWS_KEY_ID,
secretAccessKey: SECRET_ACCESS_KEY
});
const destinationDir = DESTINATION_DIR === '/' ? shortid() : DESTINATION_DIR;
+ const maxAge = 'max-age='+CACHE_MAX_AGE
const paths = klawSync(SOURCE_DIR, {
nodir: true
});
function upload(params) {
return new Promise(resolve => {
s3.upload(params, (err, data) => {
if (err) core.error(err);
core.info(`uploaded - ${data.Key}`);
core.info(`located - ${data.Location}`);
resolve(data.Location);
});
});
}
function run() {
const sourceDir = path.join(process.cwd(), SOURCE_DIR);
return Promise.all(
paths.map(p => {
const fileStream = fs.createReadStream(p.path);
const bucketPath = path.join(destinationDir, path.relative(sourceDir, p.path));
const params = {
Bucket: BUCKET,
ACL: 'public-read',
Body: fileStream,
Key: bucketPath,
ContentType: lookup(p.path) || 'text/plain',
+ CacheControl: maxAge
};
return upload(params);
})
);
}
run()
.then(locations => {
core.info(`object key - ${destinationDir}`);
core.info(`object locations - ${locations}`);
core.setOutput('object_key', destinationDir);
core.setOutput('object_locations', locations);
})
.catch(err => {
core.error(err);
core.setFailed(err.message);
});
action.yml
action.yml
name: Upload S3
description: 'Upload directory to S3'
author: 'Dong Keon Kim'
branding:
icon: 'upload-cloud'
color: 'orange'
inputs:
aws_key_id:
description: 'aws key id'
required: true
aws_secret_access_key:
description: 'aws secret access key'
required: true
aws_bucket:
description: 'aws bucket name'
required: true
source_dir:
required: true
description: 'directory to upload'
destination_dir:
required: false
default: /
description: 'destination directory for upload'
+ cache_max_age:
+ required: false
+ default: 0
+ description: 'add cache control to uploaded files'
outputs:
object_key:
description: 'object key'
object_locations:
description: 'object locations'
runs:
using: 'node12'
main: 'dist/index.js'
使い方例
- 事前にGithubリポジトリにsecretを設定する。(IAMのもろもろ、bucket名など)
- リポジトリ直下に
.github/workflows
ディレクトリを作成して、適当な名前で.yml
ファイルを作成する。例えばメインブランチにpushした時にアップロードする場合の記載内容は下記の通り(一番シンプルなケースです)。
hogehoge.yml
name: Upload to S3
on:
push:
branches:
- main
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: tenkoh/upload-s3-action@master
with:
aws_key_id: ${{ secrets.IAM_ACCESS_KEY }}
aws_secret_access_key: ${{ secrets.IAM_SECRET}}
aws_bucket: ${{ secrets.AWS_BUCKET }}
source_dir: 'fugafuga'
destination_dir: 'hogefuga'
+ cache_max_age: 86400
こうして記事にして見ると、使っているアクションの中に@master
が残ってますね…。actions/checkout
は現在のデフォルトブランチはmain
になっているようですが、ファイルの差分は無さそうなので据え置きでも実質問題ないかと…。upload-s3-action
の方はmain
という名前のブランチを作ってないので時流に乗り遅れてます^^;
Discussion