Skip to content

Have terraform own build - #45

Merged
kyokukou merged 5 commits into
developfrom
have-terraform-build
Aug 21, 2026
Merged

Have terraform own build#45
kyokukou merged 5 commits into
developfrom
have-terraform-build

Conversation

@kyokukou

Copy link
Copy Markdown
Contributor

remove old cloudbuild trigger, terraform now builds image and deploys it

@kyokukou
kyokukou deployed to production August 20, 2026 20:09 — with GitHub Actions Active
@kyokukou
kyokukou deployed to development August 20, 2026 20:09 — with GitHub Actions Active
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Terraform plan · production

Plan: 0 to add, 1 to change, 1 to destroy.

Show full plan
google_service_account.job: Refreshing state... [id=projects/arxiv-production/serviceAccounts/mod-notification-handler@arxiv-production.iam.gserviceaccount.com]
google_pubsub_topic.mod_notify: Refreshing state... [id=projects/arxiv-production/topics/mod-notify]
google_cloudbuild_trigger.deploy: Refreshing state... [id=projects/arxiv-production/locations/us-east1/triggers/62cf038d-dfab-483b-92eb-9e5744577517]
google_project_iam_member.job["roles/run.invoker"]: Refreshing state... [id=arxiv-production/roles/run.invoker/serviceAccount:mod-notification-handler@arxiv-production.iam.gserviceaccount.com]
google_project_iam_member.job["roles/cloudsql.client"]: Refreshing state... [id=arxiv-production/roles/cloudsql.client/serviceAccount:mod-notification-handler@arxiv-production.iam.gserviceaccount.com]
google_project_iam_member.job["roles/secretmanager.secretAccessor"]: Refreshing state... [id=arxiv-production/roles/secretmanager.secretAccessor/serviceAccount:mod-notification-handler@arxiv-production.iam.gserviceaccount.com]
google_project_iam_member.job["roles/pubsub.subscriber"]: Refreshing state... [id=arxiv-production/roles/pubsub.subscriber/serviceAccount:mod-notification-handler@arxiv-production.iam.gserviceaccount.com]
google_cloud_run_v2_job.jobs["mod_actions"]: Refreshing state... [id=projects/arxiv-production/locations/us-central1/jobs/mod-notification-handler]
google_pubsub_subscription.mod_actions: Refreshing state... [id=projects/arxiv-production/subscriptions/mod-notification-handler]
google_cloud_scheduler_job.jobs["mod_actions"]: Refreshing state... [id=projects/arxiv-production/locations/us-central1/jobs/mod-notification-handler-scheduler-trigger]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # google_cloud_run_v2_job.jobs["mod_actions"] will be updated in-place
  ~ resource "google_cloud_run_v2_job" "jobs" {
        id                       = "projects/arxiv-production/locations/us-central1/jobs/mod-notification-handler"
        name                     = "mod-notification-handler"
        # (29 unchanged attributes hidden)

      ~ template {
            # (4 unchanged attributes hidden)

          ~ template {
                # (6 unchanged attributes hidden)

              ~ containers {
                  ~ args        = [
                      + "-m",
                      + "app.mod_actions.main",
                    ]
                  ~ command     = [
                      + "python",
                    ]
                    name        = "mod-notification-handler-1"
                    # (3 unchanged attributes hidden)

                    # (11 unchanged blocks hidden)
                }

                # (1 unchanged block hidden)
            }
        }
    }

  # google_cloudbuild_trigger.deploy will be destroyed
  # (because google_cloudbuild_trigger.deploy is not in configuration)
  - resource "google_cloudbuild_trigger" "deploy" {
      - create_time        = "2026-06-10T15:10:52.103357449Z" -> null
      - deletion_policy    = "DELETE" -> null
      - description        = "builds cloud run job that sends emails to mods" -> null
      - disabled           = false -> null
      - filename           = "cicd/cloudbuild.yaml" -> null
      - id                 = "projects/arxiv-production/locations/us-east1/triggers/62cf038d-dfab-483b-92eb-9e5744577517" -> null
      - ignored_files      = [] -> null
      - include_build_logs = "INCLUDE_BUILD_LOGS_WITH_STATUS" -> null
      - included_files     = [] -> null
      - location           = "us-east1" -> null
      - name               = "mod-notification-handler" -> null
      - project            = "arxiv-production" -> null
      - service_account    = "projects/arxiv-production/serviceAccounts/cloudbuild-sa@arxiv-production.iam.gserviceaccount.com" -> null
      - substitutions      = {
          - "_DEPLOY_REGION" = "us-central1"
          - "_JOB_NAME"      = "mod-notification-handler"
        } -> null
      - tags               = [
          - "mod-notify",
        ] -> null
      - trigger_id         = "62cf038d-dfab-483b-92eb-9e5744577517" -> null
        # (1 unchanged attribute hidden)

      - approval_config {
          - approval_required = false -> null
        }

      - github {
          - name                            = "mod-notification-handler" -> null
          - owner                           = "arXiv" -> null
            # (1 unchanged attribute hidden)

          - push {
              - branch       = "^main$" -> null
              - invert_regex = false -> null
                # (1 unchanged attribute hidden)
            }
        }
    }

Plan: 0 to add, 1 to change, 1 to destroy.

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Terraform plan · development

Plan: 0 to add, 1 to change, 1 to destroy.

Show full plan
google_cloudbuild_trigger.deploy: Refreshing state... [id=projects/arxiv-development/triggers/d21e6272-ba3a-4a97-acd1-0fc9ebdaeac4]
google_service_account.job: Refreshing state... [id=projects/arxiv-development/serviceAccounts/mod-notification-handler@arxiv-development.iam.gserviceaccount.com]
google_pubsub_topic.mod_notify: Refreshing state... [id=projects/arxiv-development/topics/mod-notify]
google_pubsub_subscription.mod_actions: Refreshing state... [id=projects/arxiv-development/subscriptions/mod-notification-handler]
google_project_iam_member.job["roles/cloudsql.client"]: Refreshing state... [id=arxiv-development/roles/cloudsql.client/serviceAccount:mod-notification-handler@arxiv-development.iam.gserviceaccount.com]
google_project_iam_member.job["roles/pubsub.subscriber"]: Refreshing state... [id=arxiv-development/roles/pubsub.subscriber/serviceAccount:mod-notification-handler@arxiv-development.iam.gserviceaccount.com]
google_project_iam_member.job["roles/run.invoker"]: Refreshing state... [id=arxiv-development/roles/run.invoker/serviceAccount:mod-notification-handler@arxiv-development.iam.gserviceaccount.com]
google_project_iam_member.job["roles/secretmanager.secretAccessor"]: Refreshing state... [id=arxiv-development/roles/secretmanager.secretAccessor/serviceAccount:mod-notification-handler@arxiv-development.iam.gserviceaccount.com]
google_cloud_run_v2_job.jobs["mod_actions"]: Refreshing state... [id=projects/arxiv-development/locations/us-central1/jobs/mod-notification-handler]
google_cloud_scheduler_job.jobs["mod_actions"]: Refreshing state... [id=projects/arxiv-development/locations/us-central1/jobs/mod-notification-handler-scheduler-trigger]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # google_cloud_run_v2_job.jobs["mod_actions"] will be updated in-place
  ~ resource "google_cloud_run_v2_job" "jobs" {
        id                       = "projects/arxiv-development/locations/us-central1/jobs/mod-notification-handler"
        name                     = "mod-notification-handler"
        # (29 unchanged attributes hidden)

      ~ template {
            # (4 unchanged attributes hidden)

          ~ template {
                # (6 unchanged attributes hidden)

              ~ containers {
                  ~ args        = [
                      + "-m",
                      + "app.mod_actions.main",
                    ]
                  ~ command     = [
                      + "python",
                    ]
                    name        = "mod-notification-handler-1"
                    # (3 unchanged attributes hidden)

                    # (11 unchanged blocks hidden)
                }

                # (1 unchanged block hidden)
            }
        }
    }

  # google_cloudbuild_trigger.deploy will be destroyed
  # (because google_cloudbuild_trigger.deploy is not in configuration)
  - resource "google_cloudbuild_trigger" "deploy" {
      - create_time        = "2026-04-27T17:13:15.106106685Z" -> null
      - deletion_policy    = "DELETE" -> null
      - description        = "Build and deploy a cloud run job for processing notifcations for moderators" -> null
      - disabled           = false -> null
      - filename           = "cicd/cloudbuild.yaml" -> null
      - id                 = "projects/arxiv-development/triggers/d21e6272-ba3a-4a97-acd1-0fc9ebdaeac4" -> null
      - ignored_files      = [] -> null
      - include_build_logs = "INCLUDE_BUILD_LOGS_WITH_STATUS" -> null
      - included_files     = [] -> null
      - location           = "global" -> null
      - name               = "mod-notification-handler" -> null
      - project            = "arxiv-development" -> null
      - service_account    = "projects/arxiv-development/serviceAccounts/cloudbuild-sa@arxiv-development.iam.gserviceaccount.com" -> null
      - substitutions      = {
          - "_DEPLOY_REGION" = "us-central1"
          - "_JOB_NAME"      = "mod-notification-handler"
        } -> null
      - tags               = [
          - "mod-notify",
        ] -> null
      - trigger_id         = "d21e6272-ba3a-4a97-acd1-0fc9ebdaeac4" -> null
        # (1 unchanged attribute hidden)

      - approval_config {
          - approval_required = false -> null
        }

      - github {
          - name                            = "mod-notification-handler" -> null
          - owner                           = "arXiv" -> null
            # (1 unchanged attribute hidden)

          - push {
              - branch       = "^develop$" -> null
              - invert_regex = false -> null
                # (1 unchanged attribute hidden)
            }
        }
    }

Plan: 0 to add, 1 to change, 1 to destroy.

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.

@kyokukou
kyokukou requested a review from a team August 20, 2026 20:11
@kyokukou
kyokukou deployed to production August 20, 2026 20:25 — with GitHub Actions Active
@kyokukou
kyokukou deployed to development August 20, 2026 20:25 — with GitHub Actions Active
Comment thread .github/workflows/deploy.yaml Outdated
concurrency:
group: tf-apply-${{ inputs.environment || github.ref_name }}
group: deploy-${{ inputs.environment || github.ref_name }}
cancel-in-progress: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false is the default, so you could remove this entire concurrency block if you'd like

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is correct that you don't ever want to cancel in progress for a workflow that includes terraform commands

Comment thread .github/workflows/deploy.yaml Outdated
build:
runs-on: ubuntu-latest
timeout-minutes: 20
environment: ${{ inputs.environment || (github.ref_name == 'main' && 'production' || 'development') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest making environment a required input without a default - this prevents accidental deploys to the wrong place

Comment thread .github/workflows/deploy.yaml Outdated
- name: Check out repository code
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit_sha || '' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this functions if you pass an empty string here, but it may be more explicit to pass the current ref (github.sha)

Comment thread .github/workflows/deploy.yaml Outdated
id: build
run: |
set -euo pipefail
SHA="$(git rev-parse HEAD)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will always use the latest checked-out sha. not sure if that was your intention, given that the above allows commit_sha as an input

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goal is a default automated run just uses the latest (triggering) commit to dev/production, but if youre trying to run it manually like you showed me you can select a specific commit

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that is the case this needs to be reworked - the sha used throughout the workflow should be the one set by the condition (use the input, or if none, use github.sha)
you can set it as a global var if that is easiest, example here https://github.com/arXiv/arxiv-qa/blob/12179214f91ded347e764c1267048f7976dfda23/.github/workflows/build-push.yml#L42

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be clear - you should use the same sha for your build/image throughout. if you want the ability to use a different sha for terraform code (which is nice in the case of a rollback that changes the image but not the infra code) you might want to separate the build workflow from the deploy. or you can set two different shas and run the checkout step twice

Comment thread .github/workflows/deploy.yaml Outdated
timeout-minutes: 30

# develop applies development, main applies production. A manual run says which.
environment: ${{ inputs.environment || (github.ref_name == 'main' && 'production' || 'development') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same note as above

set -o pipefail
terraform plan -lock=false -no-color -input=false \
-var-file=envs/${{ matrix.environment }}.tfvars 2>&1 \
-var-file=envs/${{ matrix.environment }}.tfvars \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was a little confused by this workflow. I would suggest planning develop from develop and then production on PR to your main/production branch, if only for the reason that planning from develop may be misleading - other changes may have been made on develop prior to a PR from develop to production (or, less likely, there may be changes on the main/production branch that are not on develop, as in a hotfix)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the additional changes ahead of these is an interesting point! I added the production plan because i wanted a preview incase there's was a mistake before I got too far ahead, but if showing those bonus changes ends up being more trouble than its worth ill go down to one per PR

carly-jones
carly-jones previously approved these changes Aug 21, 2026

@carly-jones carly-jones left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with some comments

@carly-jones

Copy link
Copy Markdown

another suggestion as I'm circling back on these comments -
it may make your life easier to separate the triggers (when to run, and which inputs to supply) from the deploy workflow itself. this way, you can more clearly manage the inputs (which sha to use, which environment to use, etc)
an example here https://github.com/arXiv/arxiv-qa/blob/develop/.github/workflows/pdftotext-triggers.yml

@kyokukou
kyokukou deployed to production August 21, 2026 17:03 — with GitHub Actions Active
@kyokukou
kyokukou deployed to development August 21, 2026 17:03 — with GitHub Actions Active
@kyokukou
kyokukou requested a review from carly-jones August 21, 2026 17:04
terraform_version: "1.13.5"
terraform_wrapper: false

- name: Cache providers

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the .terraform.lock doesn't actually need to be committed in the repo (there may be some stray ones you've seen committed from early days terraforming things)

echo "image=$REPO:$SHA" >> "$GITHUB_OUTPUT"
echo "Built $REPO:$SHA"

apply:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keeping these in the same workflow means you will have to rebuild the image (albeit cached) each time. for now I think this is fine though

@carly-jones carly-jones left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a couple more comments, but I think this looks good

@kyokukou
kyokukou merged commit aaecc1d into develop Aug 21, 2026
4 checks passed
@kyokukou
kyokukou deleted the have-terraform-build branch August 21, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants