Terraform plan fails in GitHub Actions PR with 'no changes' but local works

Error:

No changes. Your infrastructure matches the configuration.

Background
I am trying to set up a CI/CD pipeline for CXone resources using the Genesys Cloud Terraform provider. I followed the docs: “Run terraform plan on every pull request and apply on merge.” I am using GitHub Actions. The goal is to validate infrastructure changes before merging to main.

Issue
My terraform plan job runs on every Pull Request. However, it always reports “No changes” even when I have clearly added a new User resource in the PR branch. Locally, terraform plan correctly shows the addition. The docs state “The plan step should detect differences between the state and the configuration.” Why is the remote state not reflecting the branch changes in the pipeline?

Troubleshooting
I checked the GitHub Actions logs. The authentication step passes. The terraform init succeeds. I am using the same backend config for local and remote.

Snippet:

name: TF Plan
on:
 pull_request:
 branches: [ main ]
jobs:
 plan:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v3
 - uses: hashicorp/setup-terraform@v2
 - run: terraform init
 - run: terraform plan

Is there a specific flag or backend configuration required for PR checks to see the branch code? The docs do not mention branch-specific state handling for plans.

The easiest fix here is this is to ensure the backend state file is not being shared or locked across the PR environment and the local environment, causing a drift in state tracking.

No changes. Your infrastructure matches the configuration.

Check if your backend configuration in the TF file points to a remote state that is being overwritten by a previous run, or if the provider version constraints are allowing different schema interpretations between your local CLI and the GitHub Actions runner.

You need to verify that your GitHub Actions workflow is correctly pointing to the remote state backend defined in your backend block. If the runner is falling back to local state storage due to a missing or misconfigured backend, it will naturally report “No changes” because it is comparing against an empty or stale local .tfstate file rather than the live remote state.

Ensure your main.tf explicitly defines the backend, typically S3 or Artifactory for enterprise setups.

terraform {
 backend "s3" {
 bucket = "my-org-terraform-state"
 key = "dev/genesys/terraform.tfstate"
 region = "eu-west-1"
 encrypt = true
 dynamodb_table = "terraform-locks"
 }
}

In your GitHub Actions YAML, you must ensure the provider credentials are injected correctly before the init step. The genesyscloud provider requires valid OAuth credentials. If these are missing, the init might succeed silently but fail to connect to the remote backend properly during the plan phase.

- name: Init Terraform
 run: |
 terraform init -backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID }}" \
 -backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY }}" \
 -backend-config="token=${{ secrets.GC_ACCESS_TOKEN }}"

Also, check for state locking issues. If another process holds a lock on the DynamoDB table, the plan might fail to read the current state. Use terraform force-unlock if you suspect a stale lock, though this is rare in isolated PR environments. Verify the TF_LOG output in the action logs to see if it is attempting to fetch the remote state. If it skips the fetch step entirely, your backend configuration in the workflow is likely ignored.