From 3be527cac8a30af1e40b8c7a8808f2928a13be7b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 8 Nov 2022 13:27:20 +0000
Subject: [PATCH] Deploy `develop` branch to Cloudflare Pages (#23454)
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
---
.github/cfp_headers | 10 ++++
.github/workflows/build_develop.yml | 73 ++++++++++++++++++++++++++---
res/apple-app-site-association | 18 +++++++
scripts/copy-res.js | 1 +
src/vector/index.html | 12 ++---
webpack.config.js | 6 +++
6 files changed, 108 insertions(+), 12 deletions(-)
create mode 100644 .github/cfp_headers
create mode 100644 res/apple-app-site-association
diff --git a/.github/cfp_headers b/.github/cfp_headers
new file mode 100644
index 000000000..2252ae372
--- /dev/null
+++ b/.github/cfp_headers
@@ -0,0 +1,10 @@
+/*
+ X-XSS-Protection: 1; mode=block
+ X-Content-Type-Options: nosniff
+ Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
+
+/version
+ Content-Type: text/plain
+
+/apple-app-site-association
+ Content-Type: application/json
diff --git a/.github/workflows/build_develop.yml b/.github/workflows/build_develop.yml
index 56d27c52b..1b3e228ab 100644
--- a/.github/workflows/build_develop.yml
+++ b/.github/workflows/build_develop.yml
@@ -1,21 +1,25 @@
# Separate to the main build workflow for access to develop
# environment secrets, largely similar to build.yaml.
-name: Build and Package develop
+name: Build and Deploy develop
on:
push:
branches: [ develop ]
repository_dispatch:
types: [ element-web-notify ]
concurrency:
- group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
+ group: ${{ github.repository_owner }}-${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
jobs:
build:
- name: "Build & Upload source maps to Sentry"
+ name: "Build & Deploy develop.element.io"
# Only respect triggers from our develop branch, ignore that of forks
if: github.repository == 'vector-im/element-web'
runs-on: ubuntu-latest
environment: develop
+ env:
+ R2_BUCKET: 'element-web-develop'
+ R2_URL: ${{ secrets.CF_R2_S3_API }}
+ R2_PUBLIC_URL: 'https://element-web-develop.element.io'
steps:
- uses: actions/checkout@v2
@@ -34,11 +38,16 @@ jobs:
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_ORG: element
SENTRY_PROJECT: riot-web
+ # We only deploy the latest bundles to Cloudflare Pages and use _redirects to fallback to R2 for
+ # older ones. This redirect means that 'self' is insufficient in the CSP,
+ # and we have to add the R2 URL.
+ # Once Cloudflare redirects support proxying mode we will be able to ditch this.
+ # See Proxying in support table at https://developers.cloudflare.com/pages/platform/redirects
+ CSP_EXTRA_SOURCE: ${{ env.R2_PUBLIC_URL }}
- run: mv dist/element-*.tar.gz dist/develop.tar.gz
- # We keep the latest develop.tar.gz as the artifact uploaded later expires after 24 and requires auth to download
- # Element Desktop's fetch script uses this tarball to fetch latest develop to build Nightlies.
+ # TODO: remove this once the element-desktop fetch script is updated to grab develop.element.io/develop.tar.gz
- name: Deploy develop.tar.gz to Github Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
@@ -50,12 +59,64 @@ jobs:
name: webapp
path: dist/develop.tar.gz
retention-days: 1
+
+ - name: Extract webapp
+ run: |
+ mkdir _deploy
+ tar xf dist/develop.tar.gz -C _deploy --strip-components=1
+
+ - name: Copy config
+ run: cp element.io/develop/config.json _deploy/config.json
+
+ - name: Populate 404.html
+ run: echo "404 Not Found" > _deploy/404.html
+
+ - name: Populate _headers
+ run: cp .github/cfp_headers _deploy/_headers
+
+ # Redirect requests for the develop tarball and the historical bundles to R2
+ - name: Populate _redirects
+ run: |
+ {
+ echo "/develop.tar.gz $R2_PUBLIC_URL/develop.tar.gz 301"
+ for bundle in $(aws s3 ls s3://$R2_BUCKET/bundles/ --endpoint-url $R2_URL --region=auto | awk '{print $2}'); do
+ echo "/bundles/${bundle}* $R2_PUBLIC_URL/bundles/${bundle}:splat 301"
+ done
+ } | tee _deploy/_redirects
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
- name: Wait for other steps to succeed
uses: lewagon/wait-on-check-action@v1.1.2
with:
ref: ${{ github.ref }}
- running-workflow-name: 'Build & Upload source maps to Sentry'
+ running-workflow-name: 'Build & Deploy develop.element.io'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
check-regexp: ^((?!SonarQube|issues|board).)*$
+
+ # We keep the latest develop.tar.gz on R2 instead of relying on the github artifact uploaded earlier
+ # as the expires after 24h and requires auth to download.
+ # Element Desktop's fetch script uses this tarball to fetch latest develop to build Nightlies.
+ - name: Deploy to R2
+ run: |
+ aws s3 cp dist/develop.tar.gz s3://$R2_BUCKET/develop.tar.gz --endpoint-url $R2_URL --region=auto
+ aws s3 cp _deploy/bundles s3://$R2_BUCKET/bundles --recursive --endpoint-url $R2_URL --region=auto
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
+
+ - name: Deploy to Cloudflare Pages
+ id: cfp
+ uses: cloudflare/pages-action@1
+ with:
+ apiToken: ${{ secrets.CF_PAGES_TOKEN }}
+ accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
+ projectName: element-web-develop
+ directory: _deploy
+ gitHubToken: ${{ secrets.GITHUB_TOKEN }}
+
+ - run: |
+ echo "Deployed to ${{ steps.cfp.outputs.url }}" >> $GITHUB_STEP_SUMMARY
+
diff --git a/res/apple-app-site-association b/res/apple-app-site-association
new file mode 100644
index 000000000..8cf662850
--- /dev/null
+++ b/res/apple-app-site-association
@@ -0,0 +1,18 @@
+{
+ "applinks": {
+ "apps": [],
+ "details": [
+ {
+ "appID": "7J4U792NQT.im.vector.app",
+ "paths": [
+ "*"
+ ]
+ }
+ ]
+ },
+ "webcredentials": {
+ "apps": [
+ "7J4U792NQT.im.vector.app"
+ ]
+ }
+}
diff --git a/scripts/copy-res.js b/scripts/copy-res.js
index 4f53f8f3e..07826b3e8 100755
--- a/scripts/copy-res.js
+++ b/scripts/copy-res.js
@@ -63,6 +63,7 @@ const INCLUDE_LANGS = [
// common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and
// "dest/b/...".
const COPY_LIST = [
+ ["res/apple-app-site-association", "webapp"],
["res/manifest.json", "webapp"],
["res/sw.js", "webapp"],
["res/welcome.html", "webapp"],
diff --git a/src/vector/index.html b/src/vector/index.html
index 24694fc46..e416ef281 100644
--- a/src/vector/index.html
+++ b/src/vector/index.html
@@ -25,17 +25,17 @@
<% for (var i=0; i < htmlWebpackPlugin.files.css.length; i++) {
var file = htmlWebpackPlugin.files.css[i];
diff --git a/webpack.config.js b/webpack.config.js
index a559836b6..7db8d3b62 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -10,6 +10,11 @@ const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackInjectPreload = require('@principalstudio/html-webpack-inject-preload');
const SentryCliPlugin = require("@sentry/webpack-plugin");
+// Environment variables
+// RIOT_OG_IMAGE_URL: specifies the URL to the image which should be used for the opengraph logo.
+// CSP_EXTRA_SOURCE: specifies a URL which should be appended to each CSP directive which uses 'self',
+// this can be helpful if your deployment has redirects for old bundles, such as develop.element.io.
+
dotenv.config();
let ogImageUrl = process.env.RIOT_OG_IMAGE_URL;
if (!ogImageUrl) ogImageUrl = 'https://app.element.io/themes/element/img/logos/opengraph.png';
@@ -587,6 +592,7 @@ module.exports = (env, argv) => {
minify: false,
templateParameters: {
og_image_url: ogImageUrl,
+ csp_extra_source: process.env.CSP_EXTRA_SOURCE ?? "",
},
}),