fix: production ready docker build with ci workflow #1
Workflow file for this run
This file contains hidden or 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
name: Docker CI Pull Request Target | |
on: | |
# pull_request_target: | |
# branches: | |
# - main | |
# types: [opened, synchronize, reopened] | |
jobs: | |
# FIRST JOB ####################################################################### | |
build-test-image: | |
name: Build Image for Testing | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
packages: write | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to ghcr.io registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Extract metadata for the Docker image | |
id: docker_meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ghcr.io/${{ github.repository }} | |
tags: ${{ github.run_id }} | |
- name: Build and Push to GHCR | |
uses: docker/build-push-action@v5 | |
with: | |
file: infra/docker/web/Dockerfile | |
push: true | |
tags: ${{ steps.docker_meta.outputs.tags }} | |
cache-to: type=gha,scope=base,mode=max | |
cache-from: type=gha,scope=base | |
platforms: linux/amd64 | |
# NEXT JOB ####################################################################### | |
unit-test: | |
name: Unit Test in Docker | |
needs: [build-test-image] | |
runs-on: ubuntu-latest | |
permissions: | |
packages: read | |
contents: read | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to ghcr.io registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Build and Unit-Test | |
uses: docker/build-push-action@v5 | |
with: | |
file: infra/docker/web/Dockerfile | |
target: unit-test | |
push: false | |
cache-to: type=gha,scope=test,mode=max | |
cache-from: | | |
type=gha,scope=base | |
type=gha,scope=test | |
platforms: linux/amd64 | |
# NEXT JOB ####################################################################### | |
integration-test: | |
name: Integration Test in Compose | |
needs: [build-test-image] | |
runs-on: ubuntu-latest | |
permissions: | |
packages: read | |
contents: read | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to ghcr.io registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Downcase repo name | |
run: | | |
echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
- name: Test healthcheck in Docker Compose | |
run: | | |
export TESTING_IMAGE=ghcr.io/${REPO}:"$GITHUB_RUN_ID" | |
echo Testing image: "$TESTING_IMAGE" | |
docker compose -f ./infra/docker/web/integration-test/compose.yml up -d calcom | |
echo "Waiting for the server to be healthy..." | |
sleep 60s | |
curl --fail http://localhost:3000 || exit 1 | |
# NEXT JOB ####################################################################### | |
scan-image: | |
name: Scan Image with Trivy | |
needs: [build-test-image] | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: read | |
security-events: write | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to ghcr.io registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Downcase repo name | |
run: | | |
echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
- name: Run Trivy for HIGH,CRITICAL CVEs and report (non-blocking) | |
uses: aquasecurity/[email protected] | |
with: | |
image-ref: ghcr.io/${{env.REPO}}:${{ github.run_id }} | |
format: sarif | |
exit-code: 0 | |
ignore-unfixed: true | |
vuln-type: 'os,library' | |
severity: 'HIGH,CRITICAL' | |
timeout: 10m0s | |
output: 'trivy-results.sarif' | |
env: | |
TRIVY_USERNAME: ${{ github.repository_owner }} | |
TRIVY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} | |
- name: Upload Trivy scan results to GitHub Security tab | |
uses: github/codeql-action/upload-sarif@v3 | |
if: always() | |
with: | |
sarif_file: 'trivy-results.sarif' | |
# NEXT JOB ####################################################################### | |
changelog: | |
name: Automated Changelog using Conventional Commit | |
needs: [build-test-image, unit-test, integration-test, scan-image] | |
runs-on: ubuntu-latest | |
outputs: | |
TAG: ${{ steps.docker_tag.outputs.TAG }} | |
permissions: | |
contents: write | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Check out the repository with all releases | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: 'false' | |
ref: ${{github.event.repository.default_branch}} | |
- name: Conventional Changelog Action | |
id: changelog | |
uses: TriPSs/[email protected] | |
with: | |
github-token: ${{ secrets.RELEASE_MAIN }} | |
version-file: "./apps/web/package.json" | |
git-branch: ${{github.event.repository.default_branch}} | |
preset: "conventionalcommits" | |
input-file: "./apps/web/CHANGELOG.md" | |
output-file: "./apps/web/CHANGELOG.md" | |
tag-prefix: "v" | |
pre-release: "${{github.event_name == 'pull_request_target'}}" | |
pre-release-identifier: "alpha" | |
skip-on-empty: 'false' | |
skip-git-pull: true | |
- name: Create Release | |
uses: actions/create-release@v1 | |
if: ${{ steps.changelog.outputs.skipped == 'false' }} | |
env: | |
GITHUB_TOKEN: ${{ secrets.RELEASE_MAIN }} | |
with: | |
tag_name: ${{ steps.changelog.outputs.tag }} | |
release_name: ${{ steps.changelog.outputs.tag }} | |
body: ${{ steps.changelog.outputs.clean_changelog }} | |
- name: Export tag for final build | |
id: docker_tag | |
run: | | |
echo "TAG=${{ steps.changelog.outputs.tag }}" >> $GITHUB_OUTPUT | |
# NEXT JOB ####################################################################### | |
build-final-image: | |
name: Build Final Image | |
needs: [unit-test, integration-test, scan-image, changelog] | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
packages: write | |
pull-requests: write | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to ghcr.io registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Docker Metadata for Final Image Build | |
id: docker_meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ secrets.DOCKERHUB_USERNAME }}/cal.com | |
tags: | | |
type=raw,value=${{needs.changelog.outputs.TAG}} | |
- name: Comment on pull request | |
uses: marocchino/sticky-pull-request-comment@v2 | |
with: | |
header: final-image | |
message: | | |
image tag: ${{ steps.docker_meta.outputs.tags }} | |
image label: ${{ steps.docker_meta.outputs.labels }} | |
- name: Add labels | |
uses: actions-ecosystem/action-add-labels@v1 | |
if: github.event_name == 'pull_request_target' | |
with: | |
labels: preview | |
- name: Docker Build and Push to Docker Hub | |
uses: docker/build-push-action@v5 | |
with: | |
file: infra/docker/web/Dockerfile | |
push: true | |
tags: | | |
${{ steps.docker_meta.outputs.tags }} | |
labels: ${{ steps.docker_meta.outputs.labels }} | |
cache-from: type=gha,scope=base | |
platforms: linux/amd64 | |
# NEXT JOB ####################################################################### | |
tag-manifest-update-compose: | |
name: Tag Kubernetes Manifest and Update Compose | |
needs: [unit-test, integration-test, scan-image, changelog, build-final-image] | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' | |
steps: | |
- name: Set default values for manifest tag | |
run: | | |
echo "PUSH_MANIFEST_TAG='false'" >> $GITHUB_ENV | |
echo "ENABLE_PREVIEW='false'" >> $GITHUB_ENV | |
echo "REMOTE_REPO=''" >> $GITHUB_ENV | |
echo "REMOTE_WORKFLOW=''" >> $GITHUB_ENV | |
echo "PREVIEW_WORKFLOW=''" >> $GITHUB_ENV | |
- name: Trigger Deployment Workflow | |
if: github.event_name == 'pull_request_target' && github.base_ref == 'refs/heads/main' && env.PUSH_MANIFEST_TAG == 'true' && env.ENABLE_PREVIEW == 'true' | |
uses: benc-uk/workflow-dispatch@v1 | |
with: | |
workflow: ${{env.PREVIEW_WORKFLOW}} | |
repo: ${{ env.REMOTE_REPO }} | |
inputs: '{"image": "${{ secrets.DOCKERHUB_USERNAME }}/calcom:${{ needs.changelog.outputs.TAG }}" }' | |
token: "${{ secrets.RELEASE_MAIN }}" | |