So, I am working with simple NestJS application, docker, and terraform. My CI/CD scripts consists of 3 jobs, Docker, Terraform, and Deploy (with GCP). So I need to store the external IP of my created vm instance (by terraform) during the Terraform job. When I use the stored external IP, it is worked when I print it using echo
. But, it seems doesn’t work when I use it in SSH with appleboy/ssh-action
. Here is the detail.
Screenshot of my GitHub Actions Jobs
And here is my CI/CD scripts.
name: 'Automatic Deployment with Terraform and Docker to GCP'
on:
push:
branches: [ "master" ]
pull_request:
permissions:
contents: read
jobs:
docker:
name: 'Docker'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Docker Hub Authentication
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build Docker Image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest .
- name: Tag Docker Image
run: docker tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest
- name: Push Docker Image to Docker Hub
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest
terraform:
name: 'Terraform'
runs-on: ubuntu-latest
outputs:
external_ip: ${{ steps.store.outputs.vm_external_ip }}
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v4
# Authenticate via gcloud CLI
- name: Setup gcloud CLI
uses: google-github-actions/[email protected]
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GOOGLE_CREDENTIALS }}
export_default_credentials: true
# Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Create Terraform Variables
id: vars
run: |
cat > terraform.tfvars <<EOF
project="${{ secrets.GCP_PROJECT_ID }}"
region="${{ vars.GCP_REGION }}"
zone="${{ vars.GCP_ZONE }}"
ssh_pub_key="${{ secrets.SSH_PUBLIC_KEY }}"
ssh_username="${{ secrets.GCP_USER }}"
vm_instance_name="${{ vars.VM_INSTANCE_NAME }}"
EOF
# Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
- name: Terraform Init
run: terraform init
# Checks that all Terraform configuration files adhere to a canonical format
- name: Terraform Format
run: terraform fmt
# Generates an execution plan for Terraform
- name: Terraform Plan
run: terraform plan -out=plan
# On push to "master", build or change infrastructure according to Terraform configuration files
# Note: It is recommended to set up a required "strict" status check in your repository for "Terraform Cloud". See the documentation on "strict" required status checks for more information: https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks
- name: Terraform Apply
run: terraform apply "plan"
- name: Store Terraform Output
run: |
EXTERNAL_IP=$(terraform-bin output -raw vm_external_ip)
echo "VM_EXTERNAL_IP=$EXTERNAL_IP" >> $GITHUB_ENV
echo "not env: $EXTERNAL_IP"
echo "env: ${{ env.VM_EXTERNAL_IP }}"
- name: Echo Terraform Output
id: store
env:
EXTERNAL_IP: ${{ env.VM_EXTERNAL_IP }}
run: |
echo "env directly: ${{ env.VM_EXTERNAL_IP }}"
echo "env variable: $EXTERNAL_IP"
echo "vm_external_ip=$EXTERNAL_IP" >> "$GITHUB_OUTPUT"
# - name: Terraform Destroy
# run: terraform destroy -auto-approve
deploy:
runs-on: ubuntu-latest
needs: [docker, terraform]
steps:
- name: Echo VM External IP
env:
VM_EXTERNAL_IP: ${{ needs.terraform.outputs.external_ip }}
run: echo "$VM_EXTERNAL_IP"
- name: Set up Cloud CLI
uses: google-github-actions/[email protected]
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GOOGLE_CREDENTIALS }}
export_default_credentials: true
- name: Access gcloud CLI
run: |
gcloud auth configure-docker
- name: Checkout repository
uses: actions/checkout@v3
- name: SSH into GCP and Run Docker Container
env:
VM_EXTERNAL_IP: ${{ needs.terraform.outputs.external_ip }}
uses: appleboy/ssh-action@master
with:
host: $VM_EXTERNAL_IP
username: ${{ secrets.GCP_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest
docker run -d -p 3000:3000 ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.DOCKER_IMAGE_NAME }}:latest
Thank you very much.
Iqbal Pahlevi A is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.