mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-12 19:39:00 -05:00
chore: update release pipeline for new infrastructure (#6541)
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
name: Build & Push Docker to ECR
|
||||
name: Build Cloud Deployment Images
|
||||
|
||||
# This workflow builds Formbricks Docker images for ECR deployment:
|
||||
# - workflow_call: Used by releases with explicit SemVer versions
|
||||
# - workflow_dispatch: Auto-detects version from current branch or uses override
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
image_tag:
|
||||
description: "Image tag to push (e.g., v3.16.1, main)"
|
||||
required: true
|
||||
default: "v3.16.1"
|
||||
version_override:
|
||||
description: "Override version (SemVer only, e.g., 1.2.3). Leave empty to auto-detect from branch."
|
||||
required: false
|
||||
type: string
|
||||
deploy_production:
|
||||
description: "Tag image for production deployment"
|
||||
required: false
|
||||
@@ -17,6 +21,24 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_tag:
|
||||
description: "Image tag to push (required for workflow_call)"
|
||||
required: true
|
||||
type: string
|
||||
IS_PRERELEASE:
|
||||
description: "Whether this is a prerelease (auto-tags for staging/production)"
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
outputs:
|
||||
IMAGE_TAG:
|
||||
description: "Normalized image tag used for the build"
|
||||
value: ${{ jobs.build-and-push.outputs.IMAGE_TAG }}
|
||||
TAGS:
|
||||
description: "Newline-separated list of ECR tags pushed"
|
||||
value: ${{ jobs.build-and-push.outputs.TAGS }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -27,14 +49,15 @@ env:
|
||||
# ECR settings are sourced from repository/environment variables for portability across envs/forks
|
||||
ECR_REGISTRY: ${{ vars.ECR_REGISTRY }}
|
||||
ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }}
|
||||
DOCKERFILE: apps/web/Dockerfile
|
||||
CONTEXT: .
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
name: Build and Push
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
outputs:
|
||||
IMAGE_TAG: ${{ steps.build.outputs.image_tag }}
|
||||
TAGS: ${{ steps.build.outputs.registry_tags }}
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
@@ -44,125 +67,22 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Validate image tag input
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_TAG: ${{ inputs.image_tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${IMAGE_TAG}" ]]; then
|
||||
echo "❌ Image tag is required (non-empty)."
|
||||
exit 1
|
||||
fi
|
||||
if (( ${#IMAGE_TAG} > 128 )); then
|
||||
echo "❌ Image tag must be at most 128 characters."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${IMAGE_TAG}" =~ ^[a-z0-9._-]+$ ]]; then
|
||||
echo "❌ Image tag may only contain lowercase letters, digits, '.', '_' and '-'."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${IMAGE_TAG}" =~ ^[.-] || "${IMAGE_TAG}" =~ [.-]$ ]]; then
|
||||
echo "❌ Image tag must not start or end with '.' or '-'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Validate required variables
|
||||
shell: bash
|
||||
env:
|
||||
ECR_REGISTRY: ${{ env.ECR_REGISTRY }}
|
||||
ECR_REPOSITORY: ${{ env.ECR_REPOSITORY }}
|
||||
ECR_REGION: ${{ env.ECR_REGION }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${ECR_REGISTRY}" || -z "${ECR_REPOSITORY}" || -z "${ECR_REGION}" ]]; then
|
||||
echo "ECR_REGION, ECR_REGISTRY and ECR_REPOSITORY must be set via repository or environment variables (Settings → Variables)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Update package.json version
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_TAG: ${{ inputs.image_tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Remove 'v' prefix if present (e.g., v3.16.1 -> 3.16.1)
|
||||
VERSION="${IMAGE_TAG#v}"
|
||||
|
||||
# Validate SemVer format (major.minor.patch with optional prerelease and build metadata)
|
||||
if [[ ! "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "❌ Error: Invalid version format after extraction. Must be SemVer (e.g., 1.2.3, 1.2.3-alpha, 1.2.3+build.1)"
|
||||
echo "Original input: ${IMAGE_TAG}"
|
||||
echo "Extracted version: ${VERSION}"
|
||||
echo "Expected format: MAJOR.MINOR.PATCH[-PRERELEASE][+BUILDMETADATA]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Valid SemVer format detected: ${VERSION}"
|
||||
echo "Updating package.json version to: ${VERSION}"
|
||||
sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" ./apps/web/package.json
|
||||
cat ./apps/web/package.json | grep version
|
||||
|
||||
- name: Build tag list
|
||||
id: tags
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_TAG: ${{ inputs.image_tag }}
|
||||
DEPLOY_PRODUCTION: ${{ inputs.deploy_production }}
|
||||
DEPLOY_STAGING: ${{ inputs.deploy_staging }}
|
||||
ECR_REGISTRY: ${{ env.ECR_REGISTRY }}
|
||||
ECR_REPOSITORY: ${{ env.ECR_REPOSITORY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Start with the base image tag
|
||||
TAGS="${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_TAG}"
|
||||
|
||||
# Add production tag if requested
|
||||
if [[ "${DEPLOY_PRODUCTION}" == "true" ]]; then
|
||||
TAGS="${TAGS}\n${ECR_REGISTRY}/${ECR_REPOSITORY}:production"
|
||||
fi
|
||||
|
||||
# Add staging tag if requested
|
||||
if [[ "${DEPLOY_STAGING}" == "true" ]]; then
|
||||
TAGS="${TAGS}\n${ECR_REGISTRY}/${ECR_REPOSITORY}:staging"
|
||||
fi
|
||||
|
||||
# Output for debugging
|
||||
echo "Generated tags:"
|
||||
echo -e "${TAGS}"
|
||||
|
||||
# Set output for next step (escape newlines for GitHub Actions)
|
||||
{
|
||||
echo "tags<<EOF"
|
||||
echo -e "${TAGS}"
|
||||
echo "EOF"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Configure AWS credentials (OIDC)
|
||||
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a
|
||||
- name: Build and push cloud deployment image
|
||||
id: build
|
||||
uses: ./.github/actions/build-and-push-docker
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ECR_PUSH_ROLE_ARN }}
|
||||
aws-region: ${{ env.ECR_REGION }}
|
||||
|
||||
- name: Log in to Amazon ECR
|
||||
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@b0b1ea4f69e92ebf5dea3f8713a1b0c37b2126a5 # v1.6.0
|
||||
|
||||
- name: Build and push image (Depot remote builder)
|
||||
uses: depot/build-push-action@636daae76684e38c301daa0c5eca1c095b24e780 # v1.14.0
|
||||
with:
|
||||
project: tw0fqmsx3c
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
context: ${{ env.CONTEXT }}
|
||||
file: ${{ env.DOCKERFILE }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.tags.outputs.tags }}
|
||||
secrets: |
|
||||
database_url=${{ secrets.DUMMY_DATABASE_URL }}
|
||||
encryption_key=${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
registry_type: "ecr"
|
||||
ecr_registry: ${{ env.ECR_REGISTRY }}
|
||||
ecr_repository: ${{ env.ECR_REPOSITORY }}
|
||||
ecr_region: ${{ env.ECR_REGION }}
|
||||
aws_role_arn: ${{ secrets.AWS_ECR_PUSH_ROLE_ARN }}
|
||||
version: ${{ inputs.version_override || inputs.image_tag }}
|
||||
deploy_production: ${{ inputs.deploy_production }}
|
||||
deploy_staging: ${{ inputs.deploy_staging }}
|
||||
is_prerelease: ${{ inputs.IS_PRERELEASE }}
|
||||
env:
|
||||
DEPOT_PROJECT_TOKEN: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
DUMMY_DATABASE_URL: ${{ secrets.DUMMY_DATABASE_URL }}
|
||||
DUMMY_ENCRYPTION_KEY: ${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
DUMMY_REDIS_URL: ${{ secrets.DUMMY_REDIS_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
VERSION:
|
||||
description: "The version of the Docker image to release, full image tag if image tag is v0.0.0 enter v0.0.0."
|
||||
description: "The version of the Docker image to release (clean SemVer, e.g., 1.2.3)"
|
||||
required: true
|
||||
type: string
|
||||
REPOSITORY:
|
||||
|
||||
@@ -8,8 +8,8 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
docker-build:
|
||||
name: Build & release docker image
|
||||
docker-build-community:
|
||||
name: Build & release community docker image
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -19,6 +19,19 @@ jobs:
|
||||
with:
|
||||
IS_PRERELEASE: ${{ github.event.release.prerelease }}
|
||||
|
||||
docker-build-cloud:
|
||||
name: Build & push Formbricks Cloud to ECR
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
uses: ./.github/workflows/build-and-push-ecr.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
image_tag: ${{ needs.docker-build-community.outputs.VERSION }}
|
||||
IS_PRERELEASE: ${{ github.event.release.prerelease }}
|
||||
needs:
|
||||
- docker-build-community
|
||||
|
||||
helm-chart-release:
|
||||
name: Release Helm Chart
|
||||
permissions:
|
||||
@@ -27,31 +40,41 @@ jobs:
|
||||
uses: ./.github/workflows/release-helm-chart.yml
|
||||
secrets: inherit
|
||||
needs:
|
||||
- docker-build
|
||||
- docker-build-community
|
||||
with:
|
||||
VERSION: ${{ needs.docker-build.outputs.VERSION }}
|
||||
VERSION: ${{ needs.docker-build-community.outputs.VERSION }}
|
||||
|
||||
deploy-formbricks-cloud:
|
||||
name: Deploy Helm Chart to Formbricks Cloud
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
secrets: inherit
|
||||
uses: ./.github/workflows/deploy-formbricks-cloud.yml
|
||||
verify-cloud-build:
|
||||
name: Verify Cloud Build Outputs
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5 # Simple verification should be quick
|
||||
needs:
|
||||
- docker-build
|
||||
- helm-chart-release
|
||||
with:
|
||||
VERSION: v${{ needs.docker-build.outputs.VERSION }}
|
||||
ENVIRONMENT: ${{ github.event.release.prerelease && 'staging' || 'production' }}
|
||||
- docker-build-cloud
|
||||
steps:
|
||||
- name: Harden the runner
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Display ECR build outputs
|
||||
env:
|
||||
IMAGE_TAG: ${{ needs.docker-build-cloud.outputs.IMAGE_TAG }}
|
||||
TAGS: ${{ needs.docker-build-cloud.outputs.TAGS }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "✅ ECR Build Completed Successfully"
|
||||
echo "Image Tag: ${IMAGE_TAG}"
|
||||
echo "ECR Tags:"
|
||||
printf '%s\n' "${TAGS}"
|
||||
|
||||
move-stable-tag:
|
||||
name: Move stable tag to release
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write # Required for tag push operations in called workflow
|
||||
uses: ./.github/workflows/move-stable-tag.yml
|
||||
needs:
|
||||
- docker-build # Ensure release is successful first
|
||||
- docker-build-community # Ensure release is successful first
|
||||
with:
|
||||
release_tag: ${{ github.event.release.tag_name }}
|
||||
commit_sha: ${{ github.sha }}
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
name: Docker Release to Github Experimental
|
||||
name: Build Community Testing Images
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow builds experimental/testing versions of Formbricks for self-hosting customers
|
||||
# to test fixes and features before official releases. Images are pushed to GHCR with
|
||||
# timestamped experimental versions for easy identification and testing.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
# Use docker.io for Docker Hub if empty
|
||||
REGISTRY: ghcr.io
|
||||
# github.repository as <account>/<repo>
|
||||
IMAGE_NAME: ${{ github.repository }}-experimental
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
inputs:
|
||||
version_override:
|
||||
description: "Override version (SemVer only, e.g., 1.2.3-beta). Leave empty for auto-generated experimental version."
|
||||
required: false
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-community-testing:
|
||||
name: Build Community Testing Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
# This is used to complete the identity challenge
|
||||
# with sigstore/fulcio when running outside of PRs.
|
||||
id-token: write
|
||||
|
||||
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -42,110 +34,17 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate SemVer version from branch or tag
|
||||
id: generate_version
|
||||
- name: Build and push community testing image
|
||||
uses: ./.github/actions/build-and-push-docker
|
||||
with:
|
||||
registry_type: "ghcr"
|
||||
ghcr_image_name: "${{ github.repository }}-experimental"
|
||||
experimental_mode: "true"
|
||||
version: ${{ inputs.version_override }}
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
REF_TYPE: ${{ github.ref_type }}
|
||||
run: |
|
||||
# Get reference name and type from environment variables
|
||||
echo "Reference type: $REF_TYPE"
|
||||
echo "Reference name: $REF_NAME"
|
||||
|
||||
# Create unique timestamped version for testing sourcemap resolution
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
if [[ "$REF_TYPE" == "tag" ]]; then
|
||||
# If running from a tag, use the tag name + timestamp
|
||||
if [[ "$REF_NAME" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
|
||||
# Tag looks like a SemVer, use it directly (remove 'v' prefix if present)
|
||||
BASE_VERSION=$(echo "$REF_NAME" | sed 's/^v//')
|
||||
VERSION="${BASE_VERSION}-${TIMESTAMP}"
|
||||
echo "Using SemVer tag with timestamp: $VERSION"
|
||||
else
|
||||
# Tag is not SemVer, treat as prerelease
|
||||
SANITIZED_TAG=$(echo "$REF_NAME" | sed 's/[^a-zA-Z0-9.-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
||||
VERSION="0.0.0-${SANITIZED_TAG}-${TIMESTAMP}"
|
||||
echo "Using tag as prerelease with timestamp: $VERSION"
|
||||
fi
|
||||
else
|
||||
# Running from branch, use branch name as prerelease + timestamp
|
||||
SANITIZED_BRANCH=$(echo "$REF_NAME" | sed 's/[^a-zA-Z0-9.-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
||||
VERSION="0.0.0-${SANITIZED_BRANCH}-${TIMESTAMP}"
|
||||
echo "Using branch as prerelease with timestamp: $VERSION"
|
||||
fi
|
||||
|
||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Generated SemVer version: $VERSION"
|
||||
|
||||
- name: Update package.json version
|
||||
run: |
|
||||
sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${{ env.VERSION }}\"/" ./apps/web/package.json
|
||||
cat ./apps/web/package.json | grep version
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@b0b1ea4f69e92ebf5dea3f8713a1b0c37b2126a5 # v1.6.0
|
||||
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
|
||||
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Extract metadata (tags, labels) for Docker
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=raw,value=${{ env.VERSION }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: depot/build-push-action@636daae76684e38c301daa0c5eca1c095b24e780 # v1.14.0
|
||||
with:
|
||||
project: tw0fqmsx3c
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
context: .
|
||||
file: ./apps/web/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
secrets: |
|
||||
database_url=${{ secrets.DUMMY_DATABASE_URL }}
|
||||
encryption_key=${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
|
||||
|
||||
# Sign the resulting Docker image digest except on PRs.
|
||||
# This will only write to the public Rekor transparency log when the Docker
|
||||
# repository is public to avoid leaking data. If you would like to publish
|
||||
# transparency data even for private images, pass --force to cosign below.
|
||||
# https://github.com/sigstore/cosign
|
||||
- name: Sign the published Docker image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||
TAGS: ${{ steps.meta.outputs.tags }}
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
# This step uses the identity token to provision an ephemeral certificate
|
||||
# against the sigstore community Fulcio instance.
|
||||
run: echo "${TAGS}" | xargs -I {} cosign sign --yes "{}@${DIGEST}"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DEPOT_PROJECT_TOKEN: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
DUMMY_DATABASE_URL: ${{ secrets.DUMMY_DATABASE_URL }}
|
||||
DUMMY_ENCRYPTION_KEY: ${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
DUMMY_REDIS_URL: ${{ secrets.DUMMY_REDIS_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Docker Release to Github
|
||||
name: Release Community Docker Images
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
@@ -23,8 +23,6 @@ env:
|
||||
REGISTRY: ghcr.io
|
||||
# github.repository as <account>/<repo>
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -32,6 +30,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -44,103 +43,48 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get Release Tag
|
||||
- name: Extract release version from tag
|
||||
id: extract_release_tag
|
||||
run: |
|
||||
# Extract version from tag (e.g., refs/tags/v1.2.3 -> 1.2.3)
|
||||
set -euo pipefail
|
||||
# Extract version from tag (e.g., refs/tags/1.2.3 or refs/tags/v1.2.3 -> 1.2.3)
|
||||
TAG="$GITHUB_REF"
|
||||
TAG=${TAG#refs/tags/v}
|
||||
TAG=${TAG#refs/tags/}
|
||||
|
||||
# Validate the extracted tag format
|
||||
if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "❌ Error: Invalid release tag format after extraction. Must be semver (e.g., 1.2.3, 1.2.3-alpha)"
|
||||
# Strip leading 'v' or 'V' if present for backward compatibility
|
||||
TAG=${TAG#[vV]}
|
||||
|
||||
# Validate the extracted tag format (clean SemVer expected)
|
||||
if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "ERROR: Invalid release tag format. Must be clean semver (e.g., 1.2.3, 1.2.3-alpha)"
|
||||
echo "Original ref: $GITHUB_REF"
|
||||
echo "Extracted tag: $TAG"
|
||||
echo "Expected: Clean SemVer (v-prefix is automatically stripped for backward compatibility)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Safely add to environment variables
|
||||
echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV
|
||||
|
||||
echo "VERSION=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "Using tag-based version: $TAG"
|
||||
echo "Using clean SemVer version: $TAG"
|
||||
|
||||
- name: Update package.json version
|
||||
run: |
|
||||
sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${{ env.RELEASE_TAG }}\"/" ./apps/web/package.json
|
||||
cat ./apps/web/package.json | grep version
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@b0b1ea4f69e92ebf5dea3f8713a1b0c37b2126a5 # v1.6.0
|
||||
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
|
||||
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
- name: Build and push community release image
|
||||
id: build
|
||||
uses: ./.github/actions/build-and-push-docker
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Extract metadata (tags, labels) for Docker
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
# Default semver tags (version, major.minor, major)
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
# Only tag as 'latest' for stable releases (not prereleases)
|
||||
type=raw,value=latest,enable=${{ !inputs.IS_PRERELEASE }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: depot/build-push-action@636daae76684e38c301daa0c5eca1c095b24e780 # v1.14.0
|
||||
with:
|
||||
project: tw0fqmsx3c
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
context: .
|
||||
file: ./apps/web/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
secrets: |
|
||||
database_url=${{ secrets.DUMMY_DATABASE_URL }}
|
||||
encryption_key=${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
# Sign the resulting Docker image digest except on PRs.
|
||||
# This will only write to the public Rekor transparency log when the Docker
|
||||
# repository is public to avoid leaking data. If you would like to publish
|
||||
# transparency data even for private images, pass --force to cosign below.
|
||||
# https://github.com/sigstore/cosign
|
||||
- name: Sign the published Docker image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
registry_type: "ghcr"
|
||||
ghcr_image_name: ${{ env.IMAGE_NAME }}
|
||||
version: ${{ steps.extract_release_tag.outputs.VERSION }}
|
||||
is_prerelease: ${{ inputs.IS_PRERELEASE }}
|
||||
env:
|
||||
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||
TAGS: ${{ steps.meta.outputs.tags }}
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
# This step uses the identity token to provision an ephemeral certificate
|
||||
# against the sigstore community Fulcio instance.
|
||||
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DEPOT_PROJECT_TOKEN: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
DUMMY_DATABASE_URL: ${{ secrets.DUMMY_DATABASE_URL }}
|
||||
DUMMY_ENCRYPTION_KEY: ${{ secrets.DUMMY_ENCRYPTION_KEY }}
|
||||
DUMMY_REDIS_URL: ${{ secrets.DUMMY_REDIS_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -59,14 +59,35 @@ jobs:
|
||||
uses: dcarbone/install-yq-action@4075b4dca348d74bd83f2bf82d30f25d7c54539b # v1.3.1
|
||||
|
||||
- name: Update Chart.yaml with new version
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
yq -i ".version = \"$VERSION\"" helm-chart/Chart.yaml
|
||||
yq -i ".appVersion = \"v$VERSION\"" helm-chart/Chart.yaml
|
||||
set -euo pipefail
|
||||
|
||||
echo "Updating Chart.yaml with version: ${VERSION}"
|
||||
yq -i ".version = \"${VERSION}\"" helm-chart/Chart.yaml
|
||||
yq -i ".appVersion = \"${VERSION}\"" helm-chart/Chart.yaml
|
||||
|
||||
echo "✅ Successfully updated Chart.yaml"
|
||||
|
||||
- name: Package Helm chart
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "Packaging Helm chart version: ${VERSION}"
|
||||
helm package ./helm-chart
|
||||
|
||||
echo "✅ Successfully packaged formbricks-${VERSION}.tgz"
|
||||
|
||||
- name: Push Helm chart to GitHub Container Registry
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
helm push "formbricks-$VERSION.tgz" oci://ghcr.io/formbricks/helm-charts
|
||||
set -euo pipefail
|
||||
|
||||
echo "Pushing Helm chart to registry: formbricks-${VERSION}.tgz"
|
||||
helm push "formbricks-${VERSION}.tgz" oci://ghcr.io/formbricks/helm-charts
|
||||
|
||||
echo "✅ Successfully pushed Helm chart to registry"
|
||||
|
||||
Reference in New Issue
Block a user