torrust-tracker-deployer 0.1.0

Torrust Tracker Deployer - Deployment Infrastructure with Ansible and OpenTofu
Documentation
# Container workflow for Torrust Tracker Deployer
#
# This workflow builds, tests, and publishes the deployer Docker image.
# Following patterns from torrust/torrust-tracker container.yaml workflow.
#
# Triggers:
#   - Push to main/develop/releases/** branches
#   - Pull requests to main/develop
#   - Manual dispatch
#
# Publishing:
#   - Images are pushed to Docker Hub on push to main/develop/release branches (not PRs)
#   - Release branches (releases/vX.Y.Z or releases/vX.Y.Z-pre.N) publish versioned Docker tags
#   - Release Docker tags use bare semver without the v prefix
#   - Requires Docker Hub credentials in the dockerhub-torrust GitHub Environment

name: Container

on:
  push:
    branches:
      - "develop"
      - "main"
      - "releases/**/*"

  pull_request:
    branches:
      - "develop"
      - "main"
    paths:
      - "src/**"
      - "Cargo.toml"
      - "Cargo.lock"
      - "docker/deployer/**"
      - ".github/workflows/container.yaml"

  workflow_dispatch:

env:
  CARGO_TERM_COLOR: always
  DOCKER_HUB_USERNAME: torrust

jobs:
  test:
    name: Build & Test
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build Image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./docker/deployer/Dockerfile
          target: release
          push: false
          load: true
          tags: torrust-tracker-deployer:local
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Inspect Image
        run: docker image inspect torrust-tracker-deployer:local

      - name: Verify Tools
        run: |
          echo "=== Verifying installed tools ==="
          docker run --rm torrust-tracker-deployer:local --version || true

          echo "=== Checking OpenTofu ==="
          docker run --rm --entrypoint tofu torrust-tracker-deployer:local version

          echo "=== Checking Ansible ==="
          docker run --rm --entrypoint ansible torrust-tracker-deployer:local --version

          echo "=== Checking SSH ==="
          docker run --rm --entrypoint ssh torrust-tracker-deployer:local -V

          echo "=== Checking Git ==="
          docker run --rm --entrypoint git torrust-tracker-deployer:local --version

      - name: Test Help Output
        run: |
          docker run --rm torrust-tracker-deployer:local --help

  context:
    name: Context
    needs: test
    runs-on: ubuntu-latest

    outputs:
      continue: ${{ steps.check.outputs.continue }}
      type: ${{ steps.check.outputs.type }}
      version: ${{ steps.check.outputs.version }}

    steps:
      - name: Check Context
        id: check
        run: |
          if [[ "${{ github.repository }}" == "torrust/torrust-tracker-deployer" ]]; then
            if [[ "${{ github.event_name }}" == "push" ]]; then
              if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
                echo "type=main" >> $GITHUB_OUTPUT
                echo "continue=true" >> $GITHUB_OUTPUT
              elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
                echo "type=develop" >> $GITHUB_OUTPUT
                echo "continue=true" >> $GITHUB_OUTPUT
              elif [[ $(echo "${{ github.ref }}" | grep -P '^refs/heads/releases/v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[a-zA-Z0-9][a-zA-Z0-9.-]*)?$') ]]; then
                version=$(echo "${{ github.ref }}" | sed -n -E 's/^refs\/heads\/releases\///p')
                echo "version=$version" >> $GITHUB_OUTPUT
                echo "type=release" >> $GITHUB_OUTPUT
                echo "continue=true" >> $GITHUB_OUTPUT
              fi
            fi
          fi

          # Default: don't continue
          if [[ -z "$(cat $GITHUB_OUTPUT 2>/dev/null)" ]]; then
            echo "continue=false" >> $GITHUB_OUTPUT
          fi

  publish:
    name: Publish Image
    environment: dockerhub-torrust
    needs: context
    if: needs.context.outputs.continue == 'true'
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Configure Docker Tag Strategy
        id: tag_config
        run: |
          if [[ "${{ needs.context.outputs.type }}" == "develop" ]]; then
            {
              echo "tags<<EOF"
              echo "type=ref,event=branch"
              echo "type=sha,prefix=dev-"
              echo "EOF"
            } >> "$GITHUB_OUTPUT"
          elif [[ "${{ needs.context.outputs.type }}" == "main" ]]; then
            {
              echo "tags<<EOF"
              echo "type=raw,value=latest"
              echo "type=ref,event=branch"
              echo "type=sha"
              echo "EOF"
            } >> "$GITHUB_OUTPUT"
          elif [[ "${{ needs.context.outputs.type }}" == "release" ]]; then
            {
              echo "tags<<EOF"
              echo "type=semver,value=${{ needs.context.outputs.version }},pattern={{version}}"
              echo "EOF"
            } >> "$GITHUB_OUTPUT"
          else
            echo "Unsupported publish type: ${{ needs.context.outputs.type }}" >&2
            exit 1
          fi

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer
          tags: ${{ steps.tag_config.outputs.tags }}

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ env.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build and Push
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./docker/deployer/Dockerfile
          target: release
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Inspect Published Image
        if: needs.context.outputs.type == 'release'
        run: |
          version=$(echo "${{ needs.context.outputs.version }}" | sed 's/^v//')
          docker pull ${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer:"$version"
          docker image inspect ${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer:"$version"