Deploy to production #92
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }} |