.github/workflows/deploy-vercel-storybook.yml
# Summary:
# Builds a static version of the Storybook website and triggers a new deployment on Vercel's platform, when anything is pushed in any branch.
#
# LEARN MORE AT https://unlyed.github.io/next-right-now/guides/ci-cd/
#
# Dependencies overview:
# - See https://github.com/actions/setup-node https://github.com/actions/setup-node/tree/v2
# - See https://github.com/actions/checkout https://github.com/actions/checkout/tree/v1
# - See https://github.com/actions/upload-artifact https://github.com/actions/upload-artifact/tree/v1
# - See https://github.com/rlespinasse/github-slug-action https://github.com/rlespinasse/github-slug-action/tree/3.x
# - See https://github.com/jwalton/gh-find-current-pr https://github.com/jwalton/gh-find-current-pr/tree/v1
# - See https://github.com/peter-evans/create-or-update-comment https://github.com/peter-evans/create-or-update-comment/tree/v1
# - See https://github.com/UnlyEd/github-action-await-vercel https://github.com/UnlyEd/github-action-await-vercel/tree/v1.1.1
# - See https://github.com/UnlyEd/github-action-store-variable https://github.com/UnlyEd/github-action-store-variable/tree/v2.1.1
# - See https://github.com/cypress-io/github-action https://github.com/cypress-io/github-action/tree/v2
name: Deploy Storybook static site to Vercel
on:
# There are several ways to trigger Github actions - See https://help.github.com/en/actions/reference/events-that-trigger-workflows#example-using-a-single-event for a comprehensive list:
# - "push": Triggers each time a commit is pushed
# - "pull_request": Triggers each time a commit is pushed within a pull request, it makes it much easier to write comments within the PR, but it suffers some strong limitations:
# - There is no way to trigger when a PR is merged into another - See https://github.community/t/pull-request-action-does-not-run-on-merge/16092?u=vadorequest
# - It won't trigger when the PR is conflicting with its base branch - See https://github.community/t/run-actions-on-pull-requests-with-merge-conflicts/17104/2?u=vadorequest
push: # Triggers on each pushed commit
branches:
- '*'
# Runs the deployment workflow only when there are changes made to specific files, in any of the below paths
# Optimizes our CI/CD by not deploying the Storybook static site needlessly (faster deploy, lower cost)
# XXX Filter pattern cheat sheet https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
paths:
- '.github/workflows/deploy-vercel-storybook.yml'
- '.storybook/**'
- 'cypress/**'
- '!cypress/_examples/**'
- '!cypress/fixture/**'
- '!cypress/integration/**'
- '!cypress/config-*.json' # Exclude all config files
- 'cypress/config-storybook.json' # Force include storybook config file
- 'src/stories/**'
- 'src/common/components/**'
- 'src/**/components/**' # Any component in any "components" folder under "src". (e.g: "src/auth/components/comp1", "src/modules/core/auth/components/comp1", etc.)
- '!src/app/components/*Bootstrap*' # Ignore bootstrap components, as they aren't used by Storybook
- '*.js*' # Includes all .js/.json at the root level
- '*.ts' # Includes all .ts at the root level
- '.*ignore' # Includes .gitignore and .vercelignore
- 'yarn.lock'
- '!**/*.md' # Exclude all markdown files
- 'stories/**/*.md' # Force include all markdown files within stories (because they're used for storybook)
env:
STAGE: staging
jobs:
# Configures the deployment environment, install dependencies (like node, npm, etc.) that are requirements for the upcoming jobs
# Ex: Necessary to run `yarn deploy`
setup-environment:
name: Setup deployment environment (Ubuntu latest - Node 14.x)
runs-on: ubuntu-latest
steps:
- name: Installing node.js
uses: actions/setup-node@v2 # Used to install node environment - https://github.com/actions/setup-node
with:
node-version: '14.x' # Use the same node.js version as the one Vercel's uses (currently node14.x)
# Starts a Vercel deployment, using the storybook configuration file
# N.B: It's Vercel that will perform the actual deployment
start-deployment:
name: Starts Vercel deployment (Ubuntu latest)
runs-on: ubuntu-latest
timeout-minutes: 40 # Limit current job timeout https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
needs: setup-environment
steps:
- uses: actions/checkout@v1 # Get last commit pushed - See https://github.com/actions/checkout
- name: Expose GitHub slug/short variables # See https://github.com/rlespinasse/github-slug-action#exposed-github-environment-variables
uses: rlespinasse/github-slug-action@v3.x # See https://github.com/rlespinasse/github-slug-action
# Create a GitHub deployment (within a GitHub environment), useful to keep a public track of all deployments directly in GitHub
- name: Start GitHub deployment
uses: bobheadxi/deployments@v0.4.3 # See https://github.com/bobheadxi/deployments
id: start-github-deployment
with:
step: start
token: ${{ secrets.GITHUB_TOKEN }}
env: storybook # Uses "storybook" as GitHub environment name, because we don't need to manage multiple environments for storybook
no_override: true # Disables auto marking previous environments as "inactive", as they're still active (Vercel deployments don't auto-deactivate) and it would remove the previous deployment links needlessly
- name: Install storybook dependencies
run: yarn install
- name: Deploying on Vercel
uses: UnlyEd/github-action-deploy-on-vercel@94d41ec1ff9b5b1de5256312e385632b6fcd8fa4 # Pin "v1.2.1" - See https://github.com/UnlyEd/github-action-deploy-on-vercel/commit/94d41ec1ff9b5b1de5256312e385632b6fcd8fa4
with:
command: "yarn deploy:sb:gha --token ${{ secrets.VERCEL_TOKEN }}"
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} # Passing github's secret to the worker
# Passing exposed GitHub environment variables - See https://github.com/rlespinasse/github-slug-action#exposed-github-environment-variables
GITHUB_REF_SLUG: ${{ env.GITHUB_REF_SLUG }}
# Update the previously created GitHub deployment, and link it to our Vercel deployment
- name: Link GitHub deployment to Vercel
uses: bobheadxi/deployments@v0.4.3 # See https://github.com/bobheadxi/deployments
id: link-github-deployment-to-vercel
if: always()
with:
step: finish
token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
deployment_id: ${{ steps.start-github-deployment.outputs.deployment_id }}
env_url: ${{ env.VERCEL_DEPLOYMENT_URL }} # Link the Vercel deployment url to the GitHub environment
# We need to find the PR id. Will be used later to comment on that PR.
- name: Finding Pull Request ID
uses: jwalton/gh-find-current-pr@v1 # See https://github.com/jwalton/gh-find-current-pr
id: pr_id_finder
if: always() # It forces the job to be always executed, even if a previous job fail.
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# On deployment failure, add a comment to the PR, if there is an open PR for the current branch
- name: Comment PR (Deployment failure)
uses: peter-evans/create-or-update-comment@v1 # See https://github.com/peter-evans/create-or-update-comment
if: steps.pr_id_finder.outputs.number && failure()
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ steps.pr_id_finder.outputs.number }}
body: |
:x: Deployment **FAILED**
Commit ${{ github.sha }} failed to deploy **Storybook static site** to [${{ env.VERCEL_DEPLOYMENT_URL }}](${{ env.VERCEL_DEPLOYMENT_URL }})
[click to see logs](https://github.com/UnlyEd/next-right-now/pull/${{ steps.pr_id_finder.outputs.number }}/checks)
# On deployment success, add a comment to the PR, if there is an open PR for the current branch
- name: Comment PR (Deployment success)
uses: peter-evans/create-or-update-comment@v1 # See https://github.com/peter-evans/create-or-update-comment
if: steps.pr_id_finder.outputs.number && success()
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ steps.pr_id_finder.outputs.number }}
body: |
:white_check_mark: Deployment **SUCCESS**
Commit ${{ github.sha }} successfully deployed **Storybook static site** :open_book: to [${{ env.VERCEL_DEPLOYMENT_URL }}](${{ env.VERCEL_DEPLOYMENT_URL }})
Deployment aliases (${{ env.VERCEL_ALIASES_CREATED_COUNT }}): ${{ env.VERCEL_ALIASES_CREATED_URLS_MD }}
# At the end of the job, store all variables we will need in the following jobs
# The variables will be stored in and retrieved from a GitHub Artifact (each variable is stored in a different file)
- name: Store variables for next jobs
uses: UnlyEd/github-action-store-variable@v2.1.1 # See https://github.com/UnlyEd/github-action-store-variable
with:
variables: |
VERCEL_DEPLOYMENT_URL=${{ env.VERCEL_DEPLOYMENT_URL }}
VERCEL_DEPLOYMENT_DOMAIN=${{ env.VERCEL_DEPLOYMENT_DOMAIN }}
GITHUB_PULL_REQUEST_ID=${{ steps.pr_id_finder.outputs.number }}
# Waits for the Vercel deployment to reach "READY" state, so that other actions will be applied on a domain that is really online
await-for-vercel-deployment:
name: Await current deployment to be ready (Ubuntu latest)
timeout-minutes: 5 # Limit current job timeout https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
runs-on: ubuntu-latest
needs: start-deployment
steps:
- uses: actions/checkout@v1 # Get last commit pushed - See https://github.com/actions/checkout
# Restore variables stored by previous jobs
- name: Restore variables
uses: UnlyEd/github-action-store-variable@v2.1.1 # See https://github.com/UnlyEd/github-action-store-variable
id: restore-variable
with:
failIfNotFound: true
variables: |
VERCEL_DEPLOYMENT_DOMAIN
# Wait for deployment to be ready, before running E2E (otherwise Cypress might start testing too early, and gets redirected to Vercel's "Login page", and tests fail)
- name: Awaiting Vercel deployment to be ready
uses: UnlyEd/github-action-await-vercel@v1.1.1 # See https://github.com/UnlyEd/github-action-await-vercel
id: await-vercel
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
with:
deployment-url: ${{ env.VERCEL_DEPLOYMENT_DOMAIN }} # Must only contain the domain name (no http prefix, etc.)
timeout: 90 # Wait for 90 seconds before failing
- name: Display deployment status
run: "echo The deployment is ${{ fromJson(steps.await-vercel.outputs.deploymentDetails).readyState }}"
# Runs E2E tests against the Vercel deployment
run-2e2-tests:
name: Run end to end (E2E) tests (Ubuntu latest)
timeout-minutes: 20 # Limit current job timeout https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
runs-on: ubuntu-latest
# Docker image with Cypress pre-installed
# https://github.com/cypress-io/cypress-docker-images/tree/master/included
container: cypress/included:7.4.0
needs: await-for-vercel-deployment
steps:
- uses: actions/checkout@v1 # Get last commit pushed - See https://github.com/actions/checkout
# Restore variables stored by previous jobs
- name: Restore variables
uses: UnlyEd/github-action-store-variable@v2.1.1 # See https://github.com/UnlyEd/github-action-store-variable
id: restore-variable
with:
failIfNotFound: true
variables: |
VERCEL_DEPLOYMENT_URL
GITHUB_PULL_REQUEST_ID
# Runs the E2E tests against the new Vercel deployment
- name: Run E2E tests (Cypress)
uses: cypress-io/github-action@v2 # See https://github.com/cypress-io/github-action
with:
# XXX We disabled "wait-on" option, because it's useless. Cypress will fail anyway, because it gets redirected to some internal Vercel URL if the domain isn't yet available - See https://github.com/cypress-io/github-action/issues/270
# wait-on: '${{ env.VERCEL_DEPLOYMENT_URL }}' # Be sure that the endpoint is ready by pinging it before starting tests, using a default timeout of 60 seconds
config-file: 'cypress/config-storybook.json' # Use Cypress config file for Storybook, and override it below
config: baseUrl=${{ env.VERCEL_DEPLOYMENT_URL }} # Overriding baseUrl provided by config file to test the new deployment
env:
# Enables Cypress debugging logs, very useful if Cypress crashes, like out-of-memory issues.
# DEBUG: "cypress:*" # Enable all logs. See https://docs.cypress.io/guides/references/troubleshooting.html#Print-DEBUG-logs
DEBUG: "cypress:server:util:process_profiler" # Enable logs for "memory and CPU usage". See https://docs.cypress.io/guides/references/troubleshooting.html#Log-memory-and-CPU-usage
# On E2E failure, upload screenshots
- name: Upload screenshots artifacts (E2E failure)
uses: actions/upload-artifact@v1 # On failure we upload artifacts, https://help.github.com/en/actions/automating-your-workflow-with-github-actions/persisting-workflow-data-using-artifacts
if: failure()
with:
name: screenshots
path: cypress/screenshots/
# On E2E failure, upload videos
- name: Upload videos artifacts (E2E failure)
uses: actions/upload-artifact@v1 # On failure we upload artifacts, https://help.github.com/en/actions/automating-your-workflow-with-github-actions/persisting-workflow-data-using-artifacts
if: failure()
with:
name: videos
path: cypress/videos/
# On E2E failure, add a comment to the PR with additional information, if there is an open PR for the current branch
- name: Comment PR (E2E failure)
uses: peter-evans/create-or-update-comment@v1 # See https://github.com/peter-evans/create-or-update-comment
if: env.GITHUB_PULL_REQUEST_ID && failure()
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ env.GITHUB_PULL_REQUEST_ID }}
body: |
:x: E2E tests **FAILED** for commit ${{ github.sha }} previously deployed **Storybook static site** at [${{ env.VERCEL_DEPLOYMENT_URL }}](${{ env.VERCEL_DEPLOYMENT_URL }})
Download artifacts (screenshots + videos) from [`checks`](https://github.com/UnlyEd/next-right-now/pull/${{ env.GITHUB_PULL_REQUEST_ID }}/checks) section
# On E2E success, add a comment to the PR, if there is an open PR for the current branch
- name: Comment PR (E2E success)
uses: peter-evans/create-or-update-comment@v1 # See https://github.com/peter-evans/create-or-update-comment
if: env.GITHUB_PULL_REQUEST_ID && success()
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ env.GITHUB_PULL_REQUEST_ID }}
body: |
:white_check_mark: E2E tests **SUCCESS** for commit ${{ github.sha }} previously deployed **Storybook static site** at [${{ env.VERCEL_DEPLOYMENT_URL }}](${{ env.VERCEL_DEPLOYMENT_URL }})
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}