# This is a reusable Gitea Actions workflow. # It's designed to be called by other repositories to standardize the deployment process. # It performs two main jobs: # 1. Build: Builds a Docker image from the calling repository's Dockerfile and pushes it to a registry. # 2. Deploy: Runs the ansible-gitea playbook to deploy the newly built image to a target server. name: Reusable CI/CD # This workflow is triggered by a call from another workflow. on: workflow_call: # ------------------ INPUTS ------------------ # These are parameters that the calling workflow must provide. inputs: # The name of the application/service being deployed. # Used to find project-specific variables in ansible. app_name: description: 'The application name' required: true type: string # The deployment environment (e.g., staging, production). deploy_env: description: 'The deployment environment' required: true type: string # ------------------ SECRETS ------------------ # These are secrets that the calling workflow must pass. # They should be configured in the Gitea organization or repository settings. secrets: # Address of the target host(s) for Ansible. SERVER_HOST: description: 'Target hosts for Ansible (e.g., "user@host")' required: true SERVER_PORT: description: 'Target port for Ansible (e.g., "22")' required: false default: '22' SERVER_USER: description: 'Target user for Ansible (e.g., "cicd")' required: false default: 'cicd' # SSH private key to connect to the Ansible target host. SERVER_SSH_PRIVATE_KEY: description: 'SSH Private Key for Ansible' required: false # Password for the target host. SERVER_PASSWORD: description: 'Password for Ansible' required: false # Password for the Ansible vault. VAULT_PASSWORD: description: 'Ansible Vault Password' required: true # Docker registry username. DOCKER_USERNAME: description: 'Docker Registry Username' required: true # Docker registry password or token. DOCKER_PASSWORD: description: 'Docker Registry Password' required: true # The URL of the Docker registry. DOCKER_REGISTRY: description: 'Docker Registry URL' required: true jobs: # ============================================================================ # JOB 1: BUILD AND PUSH DOCKER IMAGE # ============================================================================ build: runs-on: ubuntu-latest outputs: image_tag: ${{ steps.meta.outputs.version }} image_name: ${{ secrets.DOCKER_REGISTRY }}/${{ github.repository_owner }}/${{ inputs.app_name }} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Docker Registry uses: docker/login-action@v3 with: registry: ${{ secrets.DOCKER_REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Docker metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ secrets.DOCKER_REGISTRY }}/${{ github.repository_owner }}/${{ inputs.app_name }} tags: | type=sha,prefix=,format=long type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} # ============================================================================ # JOB 2: DEPLOY WITH ANSIBLE # ============================================================================ deploy: runs-on: ubuntu-latest needs: build # This job runs only after the 'build' job succeeds. steps: - name: Checkout Application Code uses: actions/checkout@v4 - name: Checkout Ansible Repo uses: actions/checkout@v4 with: # This should be the path to your ansible-gitea repository repository: ${{ github.repository_owner }}/ansible-gitea path: .ansible - name: Set up Ansible and Dependencies run: | sudo apt-get update sudo apt-get install -y sshpass python3-pip pip3 install ansible ansible-galaxy collection install community.docker - name: Setup SSH if: ${{ secrets.SERVER_SSH_PRIVATE_KEY != '' }} run: | mkdir -p ~/.ssh echo "${{ secrets.SERVER_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa # Disable strict host key checking for simplicity in CI echo "StrictHostKeyChecking no" >> ~/.ssh/config - name: Setup Ansible Vault run: | echo "${{ secrets.VAULT_PASSWORD }}" > .ansible/.vault_pass - name: Run Ansible Playbook working-directory: .ansible env: SERVER_HOST: ${{ secrets.SERVER_HOST }} SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }} SERVER_SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_PRIVATE_KEY }} run: | auth_method_var="" if [[ -n "$SERVER_SSH_PRIVATE_KEY" ]]; then auth_method_var="auth_method=ssh_key ssh_key_path=/root/.ssh/id_rsa" if [[ -n "$SERVER_PASSWORD" ]]; then auth_method_var="$auth_method_var server_become_password=$SERVER_PASSWORD" fi elif [[ -n "$SERVER_PASSWORD" ]]; then auth_method_var="auth_method=password server_password=$SERVER_PASSWORD" auth_method_var="$auth_method_var server_become_password=$SERVER_PASSWORD" fi ansible-playbook playbook.yml \ -i "$SERVER_HOST," \ --extra-vars "app_name=${{ inputs.app_name }} \ deploy_env=${{ inputs.deploy_env }} \ server_user=${{ inputs.server_user }} \ server_port=${{ inputs.server_port }} \ server_host=$SERVER_HOST \ git_repo=${{ github.server_url }}/${{ github.repository }} \ docker_image_tag=${{ needs.build.outputs.image_tag }} \ docker_image_name=${{ needs.build.outputs.image_name }} \ docker_image_full=${{ needs.build.outputs.image_name }}:${{ needs.build.outputs.image_tag }} \ docker_registry=${{ secrets.DOCKER_REGISTRY }} \ $auth_method_var" \ --vault-password-file .vault_pass