Skip to content

Deploy to production #92

Deploy to production

Deploy to production #92

Workflow file for this run

run-name: Deploy to ${{ github.ref_name }}
on:
push:
branches:
- staging
- production
jobs:
check-cache:
runs-on: ubuntu-latest
outputs:
admin-matched: ${{ steps.first-check.outputs.admin || steps.second-check.outputs.admin }}
web-matched: ${{ steps.first-check.outputs.web || steps.second-check.outputs.web }}
assets-matched: ${{ steps.first-check.outputs.assets || steps.second-check.outputs.assets }}
server-matched: ${{ steps.first-check.outputs.server || steps.second-check.outputs.server }}
admin-hash: ${{ steps.compute-hashes.outputs.admin }}
web-hash: ${{ steps.compute-hashes.outputs.web }}
assets-hash: ${{ steps.compute-hashes.outputs.assets }}
server-hash: ${{ steps.compute-hashes.outputs.server }}
checksum: ${{ steps.compute-hashes.outputs.checksum }}
environment:
name: ${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Compute new hashes
id: compute-hashes
run: |
echo $CWD
echo "admin=$ADMIN" >> $GITHUB_OUTPUT
echo "web=$WEB" >> $GITHUB_OUTPUT
echo "server=$SERVER" >> $GITHUB_OUTPUT
echo "assets=$ASSETS" >> $GITHUB_OUTPUT
echo "checksum=$(echo -n $ADMIN$WEB$SERVER$ASSETS | sha256sum | cut -f 1 -d ' ')" >> $GITHUB_OUTPUT
env:
ADMIN: ${{ hashFiles('packages/admin/**', 'packages/common/**', 'yarn.lock', '.yarnrc.yml') }}
WEB: ${{ hashFiles('packages/web/**', 'packages/common/**', 'yarn.lock', '.yarnrc.yml') }}
SERVER: ${{ hashFiles('packages/server/**', 'packages/common/**', 'partials/**', 'yarn.lock', '.yarnrc.yml', 'ecosystem.config.cjs') }}
ASSETS: ${{ hashFiles('assets/**') }}
CWD: ${{ github.workspace }}
- name: Get Cached Hashes
uses: actions/cache/restore@v4
id: cache
with:
path: .cache
key: hashes-${{ github.ref_name }}-${{ steps.compute-hashes.outputs.checksum }}
restore-keys: |
hashes-${{ github.ref_name }}-${{ steps.compute-hashes.outputs.checksum }}
hashes-${{ github.ref_name }}-
hashes-
- name: Debug
run: |
echo $CACHE
env:
CACHE: ${{ toJSON(steps.cache.outputs) }}
- name: Handle Cache Found
id: first-check
if: steps.cache.outputs.cache-hit == 'true'
run: |
echo "admin=true" >> $GITHUB_OUTPUT
echo "web=true" >> $GITHUB_OUTPUT
echo "assets=true" >> $GITHUB_OUTPUT
echo "server=true" >> $GITHUB_OUTPUT
- name: Get cached hashes
id: get-hashes
if: steps.cache.outputs.cache-hit == 'false' && steps.cache.outputs.cache-matched-key != ''
run: |
echo "admin=$(cat $HASH_FILE | jq -j '.admin')" >> $GITHUB_OUTPUT
echo "web=$(cat $HASH_FILE | jq -j '.web')" >> $GITHUB_OUTPUT
echo "server=$(cat $HASH_FILE | jq -j '.server')" >> $GITHUB_OUTPUT
echo "assets=$(cat $HASH_FILE | jq -j '.assets')" >> $GITHUB_OUTPUT
env:
HASH_FILE: .cache/hashes
- name: Handle yes Cache
id: second-check
if: steps.cache.outputs.cache-hit == 'false' && steps.cache.outputs.cache-matched-key != ''
run: |
echo "admin=$ADMIN" >> $GITHUB_OUTPUT
echo "web=$WEB" >> $GITHUB_OUTPUT
echo "server=$SERVER" >> $GITHUB_OUTPUT
echo "assets=$ASSETS" >> $GITHUB_OUTPUT
echo "$ADMIN, $WEB, $SERVER, $ASSETS"
env:
ADMIN: ${{ steps.compute-hashes.outputs.admin == steps.get-hashes.outputs.admin }}
WEB: ${{ steps.compute-hashes.outputs.web == steps.get-hashes.outputs.web }}
SERVER: ${{ steps.compute-hashes.outputs.server == steps.get-hashes.outputs.server }}
ASSETS: ${{ steps.compute-hashes.outputs.assets == steps.get-hashes.outputs.assets }}
assets:
runs-on: ubuntu-latest
needs: check-cache
if: needs.check-cache.outputs.assets-matched != 'true'
environment:
name: ${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup SSH
uses: ./.github/actions/setup-ssh
with:
ssh-key: ${{ secrets.SSH_ED25519 }}
ssh-host: ${{ secrets.SSH_HOST }}
ssh-user: ${{ secrets.SSH_USER }}
- name: Rsync Assets
if: ${{ vars.ASSETS_DIR != '' }}
run: |
rsync -rpivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx --files-from=$SYNC_FILE_LIST $SRC server:$DEST
env:
SYNC_FILE_LIST: ${{ github.workspace }}/rsync-assets-list
SRC: ${{ github.workspace }}/assets
DEST: ${{ vars.ASSETS_DIR }}
admin:
runs-on: ubuntu-latest
environment:
name: ${{ github.ref_name }}
needs: check-cache
if: needs.check-cache.outputs.admin-matched != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node and Common
uses: ./.github/actions/setup-node-and-common
with:
node-version: 20.x
- name: Admin Install Deps and Build
run: |
yarn workspaces focus admin
yarn workspace admin build
env:
GAPI_KEY_APP: ${{ secrets.GAPI_KEY_APP }}
PUBLIC_HOST: ${{ vars.PUBLIC_HOST }}
- name: Setup SSH
uses: ./.github/actions/setup-ssh
with:
ssh-key: ${{ secrets.SSH_ED25519 }}
ssh-host: ${{ secrets.SSH_HOST }}
ssh-user: ${{ secrets.SSH_USER }}
- name: Rsync Scripts and HTML
if: ${{ vars.HTML_DEST != '' && vars.ADMIN_DEST != '' }}
run: |
rsync --delete --dirs -ivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx -p $SCRIPT_SRC server:$SCRIPT_DEST
rsync -ivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx -p $HTML_SRC server:$HTML_DEST
env:
SCRIPT_SRC: ./packages/admin/build/static/scripts/admin/
SCRIPT_DEST: ${{ vars.ADMIN_DEST }}
HTML_SRC: ./packages/admin/build/admin.html
HTML_DEST: ${{ vars.HTML_DEST }}
web:
runs-on: ubuntu-latest
environment:
name: ${{ github.ref_name }}
needs: check-cache
if: needs.check-cache.outputs.web-matched != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node and Common
uses: ./.github/actions/setup-node-and-common
with:
node-version: 20.x
- name: Web Install Deps and Build
run: |
yarn workspaces focus web
yarn workspace web build
env:
GAPI_KEY_APP: ${{ secrets.GAPI_KEY_APP }}
STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }}
ENABLE_SHOP: ${{ vars.ENABLE_SHOP }}
- name: Setup SSH
uses: ./.github/actions/setup-ssh
with:
ssh-key: ${{ secrets.SSH_ED25519 }}
ssh-host: ${{ secrets.SSH_HOST }}
ssh-user: ${{ secrets.SSH_USER }}
- name: Rsync Scripts and HTML
if: ${{ vars.HTML_DEST != '' && vars.WEB_DEST != '' }}
run: |
rsync --delete --dirs -ivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx -p $SCRIPT_SRC server:$SCRIPT_DEST
rsync -ivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx -p $HTML_SRC server:$HTML_DEST
env:
SCRIPT_SRC: ./packages/web/build/static/scripts/web/
SCRIPT_DEST: ${{ vars.WEB_DEST }}
HTML_SRC: ./packages/web/build/index.html
HTML_DEST: ${{ vars.HTML_DEST }}
server:
runs-on: ubuntu-latest
environment:
name: ${{ github.ref_name }}
needs: check-cache
if: needs.check-cache.outputs.server-matched != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node and Common
uses: ./.github/actions/setup-node-and-common
with:
node-version: 20.x
- name: Server Install Deps and Build
run: |
yarn workspaces focus server
yarn workspace server build
- name: Setup SSH
uses: ./.github/actions/setup-ssh
with:
ssh-key: ${{ secrets.SSH_ED25519 }}
ssh-host: ${{ secrets.SSH_HOST }}
ssh-user: ${{ secrets.SSH_USER }}
- name: Rsync Build Artifacts
if: ${{ vars.BACKEND_DIR != '' }}
run: |
rsync --delete -rpivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx --files-from=$SYNC_FILE_LIST --exclude=.env $SRC server:$DEST
rsync -ivz --chown=deploy:www-data --chmod=Dg=rwx,Fg=rwx -p $HTML_SRC server:$HTML_DEST
env:
SYNC_FILE_LIST: ${{ format('{0}/rsync-server-list', github.workspace) }}
SRC: ${{ github.workspace }}
DEST: ${{ vars.BACKEND_DIR }}
HTML_SRC: ./partials/purchaseEmail.html
HTML_DEST: ${{ vars.HTML_DEST }}
- name: Install Deps on Server
run: |
ssh server $COMMAND
env:
COMMAND: ${{ format('cd {0} && . ~/.nvm/nvm.sh && nvm use 20 && yarn workspaces focus server --production', vars.BACKEND_DIR) }}
- name: Migrate Up
run: |
ssh server $COMMAND
env:
COMMAND: ${{ format('cd {0} && dbmate -d ./packages/server/migrations up', vars.BACKEND_DIR) }}
restart-app:
runs-on: ubuntu-latest
needs: [web, server, admin]
if: ${{ always() && contains(format('{0},{1},{2},{3}', needs.assets.result, needs.web.result, needs.server.result, needs.assets.result), 'success') }}
environment:
name: ${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup SSH
uses: ./.github/actions/setup-ssh
with:
ssh-key: ${{ secrets.SSH_ED25519 }}
ssh-host: ${{ secrets.SSH_HOST }}
ssh-user: ${{ secrets.SSH_USER }}
- name: PM2 Start App
run: |
ssh server $COMMAND
env:
COMMAND: ${{ format('cd {0} && . ~/.nvm/nvm.sh && nvm use 20 && pm2 start ecosystem.config.cjs', vars.BACKEND_DIR) }}
save-cache:
runs-on: ubuntu-latest
needs: [check-cache, assets, web, server, admin]
if: ${{ always() && contains(format('{0},{1},{2},{3}', needs.assets.result, needs.web.result, needs.server.result, needs.assets.result), 'success') }}
environment:
name: ${{ github.ref_name }}
steps:
- name: Write Cache
run: |
echo $CWD
mkdir -p .cache
cat > .cache/hashes << EOF
{
"admin": "$ADMIN",
"web": "$WEB",
"server": "$SERVER",
"assets": "$ASSETS"
}
EOF
env:
ADMIN: ${{ needs.check-cache.outputs.admin-hash }}
WEB: ${{ needs.check-cache.outputs.web-hash }}
SERVER: ${{ needs.check-cache.outputs.server-hash }}
ASSETS: ${{ needs.check-cache.outputs.assets-hash }}
CWD: ${{ github.workspace }}
- name: Save Cache
uses: actions/cache/save@v4
with:
path: .cache
key: hashes-${{ github.ref_name }}-${{ needs.check-cache.outputs.checksum }}