Build and Push Docker Image #3
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: Build and Push Docker Image | |
on: | |
workflow_dispatch: | |
inputs: | |
bump_type: | |
description: 'Version bump type (patch, minor, major)' | |
required: true | |
default: 'patch' | |
type: choice | |
options: | |
- patch | |
- minor | |
- major | |
branch: | |
description: 'Branch to tag (leave empty for default branch)' | |
required: false | |
default: '' | |
permissions: | |
contents: write # Needed for pushing tags | |
packages: write # Needed for pushing docker images to GHCR | |
jobs: | |
tag_release: | |
runs-on: ubuntu-latest | |
outputs: | |
# Define output to pass the tag to the next job | |
new_tag: ${{ steps.tag_version.outputs.next_version }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
# Fetch all history and tags to find the latest SemVer tag | |
fetch-depth: 0 | |
# Checkout the specific branch if provided, otherwise default | |
ref: ${{ github.event.inputs.branch }} | |
# Token needed to push tags back | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Get latest SemVer tag and calculate next version | |
id: tag_version | |
run: | | |
# Fetch all tags from remote just in case | |
git fetch --tags | |
# Get the latest SemVer tag (handles vX.Y.Z pattern) | |
# Filters tags, sorts them version-aware, takes the last one | |
LATEST_TAG=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort='v:refname' | tail -n 1) | |
if [ -z "$LATEST_TAG" ]; then | |
echo "No previous SemVer tag found. Starting with v0.1.0" | |
# Determine initial version based on bump type (optional, v0.1.0 is often fine) | |
case "${{ github.event.inputs.bump_type }}" in | |
patch|minor) | |
NEXT_VERSION="v0.1.0" | |
;; | |
major) | |
NEXT_VERSION="v1.0.0" | |
;; | |
*) # Should not happen due to 'choice' input, but good practice | |
echo "Invalid bump type: ${{ github.event.inputs.bump_type }}" | |
exit 1 | |
;; | |
esac | |
else | |
echo "Latest tag found: $LATEST_TAG" | |
# Remove 'v' prefix for calculation | |
VERSION=${LATEST_TAG#v} | |
# Split into parts | |
MAJOR=$(echo $VERSION | cut -d. -f1) | |
MINOR=$(echo $VERSION | cut -d. -f2) | |
PATCH=$(echo $VERSION | cut -d. -f3) | |
# Bump version based on input | |
case "${{ github.event.inputs.bump_type }}" in | |
patch) | |
PATCH=$((PATCH + 1)) | |
;; | |
minor) | |
MINOR=$((MINOR + 1)) | |
PATCH=0 | |
;; | |
major) | |
MAJOR=$((MAJOR + 1)) | |
MINOR=0 | |
PATCH=0 | |
;; | |
*) | |
echo "Invalid bump type: ${{ github.event.inputs.bump_type }}" | |
exit 1 | |
;; | |
esac | |
NEXT_VERSION="v${MAJOR}.${MINOR}.${PATCH}" | |
fi | |
echo "Calculated next version: $NEXT_VERSION" | |
# Set output for subsequent steps | |
echo "next_version=$NEXT_VERSION" >> $GITHUB_OUTPUT | |
- name: Create and Push Tag | |
run: | | |
# Configure Git user identity for annotated tag (FIX) | |
git config --global user.name 'github-actions[bot]' | |
git config --global user.email 'github-actions[bot]@users.noreply.github.com' | |
NEXT_TAG="${{ steps.tag_version.outputs.next_version }}" | |
COMMIT_SHA=$(git rev-parse HEAD) | |
echo "Tagging commit $COMMIT_SHA with $NEXT_TAG" | |
# Create an annotated tag (recommended) - this requires user.name/email | |
git tag -a "$NEXT_TAG" -m "Release $NEXT_TAG" | |
# Push the tag to the remote repository | |
echo "Pushing tag $NEXT_TAG to origin" | |
git push origin "$NEXT_TAG" | |
- name: Verify Tag Push | |
run: | | |
echo "Checking if tag ${{ steps.tag_version.outputs.next_version }} exists remotely..." | |
# Give remote a second to update | |
sleep 5 | |
git ls-remote --tags origin | grep "refs/tags/${{ steps.tag_version.outputs.next_version }}" || (echo "Tag push verification failed!" && exit 1) | |
echo "Tag successfully pushed." | |
build_and_push_backend_image: | |
runs-on: ubuntu-latest | |
needs: tag_release # Depends on the tag being created successfully | |
permissions: | |
packages: write # Need permission to write to GHCR | |
contents: read # Need permission to read repo contents (checkout) | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
- name: Login to GitHub Container Registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Extract metadata (tags, labels) for Docker build | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ghcr.io/${{ github.repository_owner }}/surfsense_backend | |
tags: | | |
# Use the tag generated in the previous job | |
type=raw,value=${{ needs.tag_release.outputs.new_tag }} | |
# Optionally add 'latest' tag if building from the default branch | |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) || github.event.inputs.branch == github.event.repository.default_branch }} | |
- name: Build and push surfsense backend | |
uses: docker/build-push-action@v5 | |
with: | |
context: ./surfsense_backend | |
push: true | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
# Optional: Add build cache for faster builds | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
build_and_push_ui_image: | |
runs-on: ubuntu-latest | |
needs: tag_release # Depends on the tag being created successfully | |
permissions: | |
packages: write # Need permission to write to GHCR | |
contents: read # Need permission to read repo contents (checkout) | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
- name: Login to GitHub Container Registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Extract metadata (tags, labels) for Docker build | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ghcr.io/${{ github.repository_owner }}/surfsense_ui | |
tags: | | |
# Use the tag generated in the previous job | |
type=raw,value=${{ needs.tag_release.outputs.new_tag }} | |
# Optionally add 'latest' tag if building from the default branch | |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) || github.event.inputs.branch == github.event.repository.default_branch }} | |
- name: Build and push surfsense UI image | |
uses: docker/build-push-action@v5 | |
with: | |
context: ./surfsense_web | |
push: true | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
# Optional: Add build cache for faster builds | |
cache-from: type=gha | |
cache-to: type=gha,mode=max |