利用 GitHub Actions 部署静态文件到 AWS S3/CloudFront 上

前言

因为 GitHub Action 用来部署东西很爽,所以就用了。再加上我比较喜欢 AWS 和 Architect(他可以自动删掉存储桶里多余的东西欸!),所以写了这篇文章。

还有一个动机是,很多地方我都要显示友链(之前用的是嵌套 iframe),所以想用一个集中的地方去放这些数据。加上有一些数据预处理的要求,所以就选用了 GitHub Actions + AWS 这样的组合。

至于为什么用 JavaScript 呢,大概是因为跟浏览器端贴得比较近吧。

* 由于这个 Markdown Parser 有点问题,本文章使用 (\dollar) 来代替美元符号,即使是在代码块中。

* 本文的实例仓库在 https://github.com/immccn123/data-imken-moe

实践

前置条件:

  • 配置好的 AWS CLI 和 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY。拥有 AdministratorAccess 权限预设(记得是这个)。

显而易见你得安装 Architect。

pnpm add @architect/architect

然后初始化项目。

pnpm arc init # or `pnpm exec arc init`

这个步骤不会删除你的项目的任何一个文件。你可能会发现会多出来一个 src/http/get-index/index.mjs,删掉就行,因为后面不会用到。

这个时候你会发现项目多出来一个 app.arc 文件。

## 开头的是我人工添加的注释)

# app.arc
@app
<your-project-name> ## 你的项目名称

@http
get /

@aws
# profile default
region us-west-2

这里需要对 app.arc 进行一个修改,主要包括:

  • 删除 @http 字段;
  • 添加 @static 字段。

一个示例:

@app
<your-project-name>

@aws
region us-west-2 # 地区

@static
folder ./public # 这里的意思是你需要把构建生成的文件放在 public 目录下
compression br
prune true # 自动删掉 S3 存储桶里不存在于 public 里的东西
# 你的 CloudFront 访问到的是单页应用吗?
#spa true

确保你需要上传的东西被构建到(?)public 目录下之后,运行:

pnpm arc deploy --production

(直接上生产应该没什么问题的)

然后理论上来说不会出什么差错。

% pnpm arc deploy --production
         App ⌁ <your-project-name>
      Region ⌁ us-west-2
     Profile ⌁ Set via environment
     Version ⌁ Architect 11.0.7
         cwd ⌁ /home/[REDACTED]

✓ Deploy Static asset fingerprinting disabled
✓ Hydrate Finished checks, nothing to hydrate
⚬ Deploy Initializing deployment
  | Stack ... <YourProjectName>Production
  | Bucket .. your-project-name-cfn-deployments-[REDACTED]
⚬ Deploy Generating CloudFormation deployment
✓ Deploy Generated CloudFormation deployment
⚬ Deploy Deploying & building infrastructure...
⚬ Deploy Deploying static assets...
✓ Deploy Static asset fingerprinting disabled
✓ Deploy Orphaned file pruning enabled
[  Uploaded  ] https://<yourprojectname>production-staticbucket-[REDACTED].s3.us-west-2.amazonaws.com/[REDACTED]
[  Uploaded  ] https://<yourprojectname>production-staticbucket-[REDACTED].s3.us-west-2.amazonaws.com/[REDACTED]
✓ Deploy Deployed 2 static assets from ./public/
✓ Deploy Deployed & built infrastructure
✓ Success! Deployed app in 67.126 seconds

    http://<yourprojectname>production-staticbucket-[REDACTED].s3-website-us-west-2.amazonaws.com

⚬ Deploy Checking for stale deployment artifacts
⚬ Deploy No stale deployment artifacts found

AWS 控制台里应该可以看到 Architect 自动创建了一个 CloudFormation 部署(注意切换地区)。

接下来就是写 Action 了。你可以来这里看我是怎么写的。

核心有几行:

(下面是受 Markdown Parser 美元符号无法正确解析的代码块)

      - name: Production deploy
        if: github.ref == 'refs/heads/main' # prevent abuse from pull request (?)
        run: pnpm arc deploy --production -v --prune
        env:
          AWS_ACCESS_KEY_ID: (\dollar){{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: (\dollar){{ secrets.AWS_SECRET_ACCESS_KEY }}

然后去 Secrets -> Actions 里面设置下 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 就能跑了。

最后设置下 CloudFront 就差不多了,新建一个分配,把源选到你刚才看到的部署日志的存储桶即可。

感觉最大的坑点就是 Architect 文档不是特别详尽。