Provision and Deploy #15
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: Provision and Deploy | |
| on: | |
| workflow_run: | |
| workflows: ["Test, Build and Push Images"] | |
| types: [completed] | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| image_tag: | |
| description: "Image tag to deploy (latest or a commit SHA)" | |
| default: latest | |
| # Never let two deploys touch the VM / Terraform state at the same time. | |
| concurrency: | |
| group: deploy-vm | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| packages: read | |
| jobs: | |
| deploy: | |
| name: Provision and deploy | |
| runs-on: ubuntu-latest | |
| environment: Azure | |
| # Manual runs always proceed; automatic runs only for a green build of main. | |
| if: >- | |
| ${{ github.event_name == 'workflow_dispatch' || | |
| (github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.head_branch == 'main') }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Resolve deployment values | |
| id: vars | |
| run: | | |
| # ghcr.io requires a fully lowercase repository path. | |
| echo "registry=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" | |
| if [ "${{ github.event_name }}" = "workflow_run" ]; then | |
| echo "image_tag=${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "image_tag=${{ inputs.image_tag }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| # Provision Terraform | |
| - name: Azure login | |
| uses: azure/login@v2 | |
| with: | |
| creds: ${{ secrets.AZURE_CREDENTIALS }} | |
| - name: Set up Terraform | |
| uses: hashicorp/setup-terraform@v3 | |
| with: | |
| terraform_wrapper: false | |
| - name: Terraform apply | |
| working-directory: infra/terraform | |
| run: | | |
| terraform init -input=false | |
| terraform apply -input=false -auto-approve | |
| - name: Capture app URL | |
| id: tf | |
| working-directory: infra/terraform | |
| run: echo "public_ip=$(terraform output -raw public_ip)" >> "$GITHUB_OUTPUT" | |
| # Configure + deploy Ansible | |
| # terraform apply already wrote infra/ansible/inventory.ini + ssh_key.pem. | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Install Ansible | |
| run: pipx install ansible-core | |
| - name: Write deploy vars | |
| working-directory: infra/ansible | |
| env: | |
| LOGOS_KEY: ${{ secrets.LOGOS_KEY }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| umask 077 | |
| cat > deploy-vars.yml <<EOF | |
| registry: "${{ steps.vars.outputs.registry }}" | |
| image_tag: "${{ steps.vars.outputs.image_tag }}" | |
| ghcr_username: "${{ github.actor }}" | |
| ghcr_token: "${GHCR_TOKEN}" | |
| logos_key: "${LOGOS_KEY}" | |
| openai_api_key: "${OPENAI_API_KEY}" | |
| EOF | |
| - name: Run Ansible playbook | |
| working-directory: infra/ansible | |
| env: | |
| ANSIBLE_HOST_KEY_CHECKING: "False" | |
| run: ansible-playbook site.yml -e @deploy-vars.yml | |
| - name: Clean up secrets | |
| if: always() | |
| working-directory: infra/ansible | |
| run: rm -f deploy-vars.yml ssh_key.pem | |
| - name: Summary | |
| if: success() | |
| run: echo "Deployed to http://${{ steps.tf.outputs.public_ip }}:8081" >> "$GITHUB_STEP_SUMMARY" |