Fix CI reliability: state lock + internal Forgejo URL #58

Merged
forgejo_admin merged 1 commit from 57-ci-reliability-add-lock-false-to-plan-us into main 2026-03-14 19:57:42 +00:00

Summary

Two targeted fixes to improve CI pipeline reliability for tofu plan on PRs: disable state locking for read-only plans and use the in-cluster Forgejo service URL for posting PR comments.

Changes

  • .woodpecker.yaml (plan step, line 62): Added -lock=false to tofu plan command. PR pipelines run read-only plans that should not acquire a state lock, which can fail or block when another operation holds the lock.
  • .woodpecker.yaml (plan step, line 73): Changed PR comment curl URL from external Tailscale funnel (https://forgejo.tail5b443a.ts.net) to internal Kubernetes service (http://forgejo-http.forgejo.svc.cluster.local:80). Since the CI runner is in-cluster, using the internal service avoids TLS/DNS/funnel issues and is faster.

Test Plan

  • Open a PR against this repo and verify the Woodpecker plan step succeeds without state lock errors
  • Verify the plan output is posted as a PR comment via the internal URL
  • No regressions in the apply step (unchanged)

Review Checklist

  • Passed automated review-fix loop
  • No secrets committed
  • No unnecessary file changes
  • Commit messages are descriptive
  • Closes #57
  • Plan: plan-pal-e-platform
## Summary Two targeted fixes to improve CI pipeline reliability for `tofu plan` on PRs: disable state locking for read-only plans and use the in-cluster Forgejo service URL for posting PR comments. ## Changes - `.woodpecker.yaml` (plan step, line 62): Added `-lock=false` to `tofu plan` command. PR pipelines run read-only plans that should not acquire a state lock, which can fail or block when another operation holds the lock. - `.woodpecker.yaml` (plan step, line 73): Changed PR comment curl URL from external Tailscale funnel (`https://forgejo.tail5b443a.ts.net`) to internal Kubernetes service (`http://forgejo-http.forgejo.svc.cluster.local:80`). Since the CI runner is in-cluster, using the internal service avoids TLS/DNS/funnel issues and is faster. ## Test Plan - [ ] Open a PR against this repo and verify the Woodpecker `plan` step succeeds without state lock errors - [ ] Verify the plan output is posted as a PR comment via the internal URL - [ ] No regressions in the `apply` step (unchanged) ## Review Checklist - [ ] Passed automated review-fix loop - [ ] No secrets committed - [ ] No unnecessary file changes - [ ] Commit messages are descriptive ## Related - Closes #57 - Plan: `plan-pal-e-platform`
fix: CI reliability — add -lock=false to plan + internal Forgejo URL for comments
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
0924227f58
Closes #57

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Review — Pass

Files changed: 1 (.woodpecker.yaml)
Additions/Deletions: +2 / -2

Findings

No issues found. Both changes are minimal, correct, and scoped precisely to the issue:

  1. -lock=false on tofu plan — Correct. PR plan steps are read-only and should not acquire state locks. The flag is placed before -no-color which is valid tofu CLI syntax. The apply step (line 125) is unchanged and retains locking as expected.

  2. Internal Forgejo service URL — Correct. http://forgejo-http.forgejo.svc.cluster.local:80 is the standard in-cluster DNS for the Forgejo HTTP service in the forgejo namespace. This avoids Tailscale funnel round-trips and potential TLS issues from within the cluster.

No secrets, no unrelated changes, no regressions to the validate or apply steps.

## Review — Pass **Files changed:** 1 (`.woodpecker.yaml`) **Additions/Deletions:** +2 / -2 ### Findings No issues found. Both changes are minimal, correct, and scoped precisely to the issue: 1. **`-lock=false` on `tofu plan`** — Correct. PR plan steps are read-only and should not acquire state locks. The flag is placed before `-no-color` which is valid tofu CLI syntax. The `apply` step (line 125) is unchanged and retains locking as expected. 2. **Internal Forgejo service URL** — Correct. `http://forgejo-http.forgejo.svc.cluster.local:80` is the standard in-cluster DNS for the Forgejo HTTP service in the `forgejo` namespace. This avoids Tailscale funnel round-trips and potential TLS issues from within the cluster. No secrets, no unrelated changes, no regressions to the `validate` or `apply` steps.
Author
Owner

Tofu Plan Output

tailscale_acl.this: Refreshing state... [id=acl]
helm_release.nvidia_device_plugin: Refreshing state... [id=nvidia-device-plugin]
kubernetes_namespace_v1.keycloak: Refreshing state... [id=keycloak]
kubernetes_namespace_v1.harbor: Refreshing state... [id=harbor]
kubernetes_namespace_v1.forgejo: Refreshing state... [id=forgejo]
kubernetes_namespace_v1.minio: Refreshing state... [id=minio]
kubernetes_namespace_v1.monitoring: Refreshing state... [id=monitoring]
kubernetes_namespace_v1.cnpg_system: Refreshing state... [id=cnpg-system]
kubernetes_namespace_v1.tailscale: Refreshing state... [id=tailscale]
kubernetes_namespace_v1.postgres: Refreshing state... [id=postgres]
kubernetes_namespace_v1.woodpecker: Refreshing state... [id=woodpecker]
kubernetes_namespace_v1.ollama: Refreshing state... [id=ollama]
data.kubernetes_namespace_v1.tofu_state: Reading...
kubernetes_persistent_volume_claim_v1.keycloak_data: Refreshing state... [id=keycloak/keycloak-data]
data.kubernetes_namespace_v1.pal_e_docs: Reading...
data.kubernetes_namespace_v1.tofu_state: Read complete after 0s [id=tofu-state]
kubernetes_service_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter]
kubernetes_service_v1.keycloak: Refreshing state... [id=keycloak/keycloak]
kubernetes_secret_v1.keycloak_admin: Refreshing state... [id=keycloak/keycloak-admin]
data.kubernetes_namespace_v1.pal_e_docs: Read complete after 0s [id=pal-e-docs]
kubernetes_secret_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter]
helm_release.kube_prometheus_stack: Refreshing state... [id=kube-prometheus-stack]
helm_release.loki_stack: Refreshing state... [id=loki-stack]
helm_release.cnpg: Refreshing state... [id=cnpg]
helm_release.forgejo: Refreshing state... [id=forgejo]
kubernetes_service_account_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup]
kubernetes_role_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup]
kubernetes_secret_v1.paledocs_db_url: Refreshing state... [id=pal-e-docs/paledocs-db-url]
helm_release.tailscale_operator: Refreshing state... [id=tailscale-operator]
kubernetes_role_binding_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup]
kubernetes_deployment_v1.keycloak: Refreshing state... [id=keycloak/keycloak]
helm_release.ollama: Refreshing state... [id=ollama]
kubernetes_config_map_v1.pal_e_docs_dashboard: Refreshing state... [id=monitoring/pal-e-docs-dashboard]
kubernetes_config_map_v1.dora_dashboard: Refreshing state... [id=monitoring/dora-dashboard]
helm_release.harbor: Refreshing state... [id=harbor]
helm_release.minio: Refreshing state... [id=minio]
kubernetes_deployment_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter]
kubernetes_manifest.dora_exporter_service_monitor: Refreshing state...
kubernetes_config_map_v1.grafana_loki_datasource: Refreshing state... [id=monitoring/grafana-loki-datasource]
helm_release.woodpecker: Refreshing state... [id=woodpecker]
kubernetes_ingress_v1.alertmanager_funnel: Refreshing state... [id=monitoring/alertmanager-funnel]
kubernetes_ingress_v1.forgejo_funnel: Refreshing state... [id=forgejo/forgejo-funnel]
kubernetes_ingress_v1.grafana_funnel: Refreshing state... [id=monitoring/grafana-funnel]
kubernetes_ingress_v1.keycloak_funnel: Refreshing state... [id=keycloak/keycloak-funnel]
minio_iam_policy.tf_backup: Refreshing state... [id=tf-backup]
minio_iam_user.cnpg: Refreshing state... [id=cnpg]
minio_s3_bucket.postgres_wal: Refreshing state... [id=postgres-wal]
minio_s3_bucket.tf_state_backups: Refreshing state... [id=tf-state-backups]
minio_s3_bucket.assets: Refreshing state... [id=assets]
minio_iam_policy.cnpg_wal: Refreshing state... [id=cnpg-wal]
minio_iam_user.tf_backup: Refreshing state... [id=tf-backup]
kubernetes_ingress_v1.minio_api_funnel: Refreshing state... [id=minio/minio-api-funnel]
kubernetes_ingress_v1.minio_funnel: Refreshing state... [id=minio/minio-funnel]
minio_iam_user_policy_attachment.tf_backup: Refreshing state... [id=tf-backup-20260314163610110100000001]
minio_iam_user_policy_attachment.cnpg: Refreshing state... [id=cnpg-20260302210642491000000001]
kubernetes_secret_v1.tf_backup_s3_creds: Refreshing state... [id=tofu-state/tf-backup-s3-creds]
kubernetes_secret_v1.cnpg_s3_creds: Refreshing state... [id=postgres/cnpg-s3-creds]
kubernetes_cron_job_v1.tf_state_backup: Refreshing state... [id=tofu-state/tf-state-backup]
kubernetes_ingress_v1.harbor_funnel: Refreshing state... [id=harbor/harbor-funnel]
kubernetes_ingress_v1.woodpecker_funnel: Refreshing state... [id=woodpecker/woodpecker-funnel]

No changes. Your infrastructure matches the configuration.

OpenTofu has compared your real infrastructure against your configuration and
found no differences, so no changes are needed.
## Tofu Plan Output ``` tailscale_acl.this: Refreshing state... [id=acl] helm_release.nvidia_device_plugin: Refreshing state... [id=nvidia-device-plugin] kubernetes_namespace_v1.keycloak: Refreshing state... [id=keycloak] kubernetes_namespace_v1.harbor: Refreshing state... [id=harbor] kubernetes_namespace_v1.forgejo: Refreshing state... [id=forgejo] kubernetes_namespace_v1.minio: Refreshing state... [id=minio] kubernetes_namespace_v1.monitoring: Refreshing state... [id=monitoring] kubernetes_namespace_v1.cnpg_system: Refreshing state... [id=cnpg-system] kubernetes_namespace_v1.tailscale: Refreshing state... [id=tailscale] kubernetes_namespace_v1.postgres: Refreshing state... [id=postgres] kubernetes_namespace_v1.woodpecker: Refreshing state... [id=woodpecker] kubernetes_namespace_v1.ollama: Refreshing state... [id=ollama] data.kubernetes_namespace_v1.tofu_state: Reading... kubernetes_persistent_volume_claim_v1.keycloak_data: Refreshing state... [id=keycloak/keycloak-data] data.kubernetes_namespace_v1.pal_e_docs: Reading... data.kubernetes_namespace_v1.tofu_state: Read complete after 0s [id=tofu-state] kubernetes_service_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter] kubernetes_service_v1.keycloak: Refreshing state... [id=keycloak/keycloak] kubernetes_secret_v1.keycloak_admin: Refreshing state... [id=keycloak/keycloak-admin] data.kubernetes_namespace_v1.pal_e_docs: Read complete after 0s [id=pal-e-docs] kubernetes_secret_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter] helm_release.kube_prometheus_stack: Refreshing state... [id=kube-prometheus-stack] helm_release.loki_stack: Refreshing state... [id=loki-stack] helm_release.cnpg: Refreshing state... [id=cnpg] helm_release.forgejo: Refreshing state... [id=forgejo] kubernetes_service_account_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup] kubernetes_role_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup] kubernetes_secret_v1.paledocs_db_url: Refreshing state... [id=pal-e-docs/paledocs-db-url] helm_release.tailscale_operator: Refreshing state... [id=tailscale-operator] kubernetes_role_binding_v1.tf_backup: Refreshing state... [id=tofu-state/tf-state-backup] kubernetes_deployment_v1.keycloak: Refreshing state... [id=keycloak/keycloak] helm_release.ollama: Refreshing state... [id=ollama] kubernetes_config_map_v1.pal_e_docs_dashboard: Refreshing state... [id=monitoring/pal-e-docs-dashboard] kubernetes_config_map_v1.dora_dashboard: Refreshing state... [id=monitoring/dora-dashboard] helm_release.harbor: Refreshing state... [id=harbor] helm_release.minio: Refreshing state... [id=minio] kubernetes_deployment_v1.dora_exporter: Refreshing state... [id=monitoring/dora-exporter] kubernetes_manifest.dora_exporter_service_monitor: Refreshing state... kubernetes_config_map_v1.grafana_loki_datasource: Refreshing state... [id=monitoring/grafana-loki-datasource] helm_release.woodpecker: Refreshing state... [id=woodpecker] kubernetes_ingress_v1.alertmanager_funnel: Refreshing state... [id=monitoring/alertmanager-funnel] kubernetes_ingress_v1.forgejo_funnel: Refreshing state... [id=forgejo/forgejo-funnel] kubernetes_ingress_v1.grafana_funnel: Refreshing state... [id=monitoring/grafana-funnel] kubernetes_ingress_v1.keycloak_funnel: Refreshing state... [id=keycloak/keycloak-funnel] minio_iam_policy.tf_backup: Refreshing state... [id=tf-backup] minio_iam_user.cnpg: Refreshing state... [id=cnpg] minio_s3_bucket.postgres_wal: Refreshing state... [id=postgres-wal] minio_s3_bucket.tf_state_backups: Refreshing state... [id=tf-state-backups] minio_s3_bucket.assets: Refreshing state... [id=assets] minio_iam_policy.cnpg_wal: Refreshing state... [id=cnpg-wal] minio_iam_user.tf_backup: Refreshing state... [id=tf-backup] kubernetes_ingress_v1.minio_api_funnel: Refreshing state... [id=minio/minio-api-funnel] kubernetes_ingress_v1.minio_funnel: Refreshing state... [id=minio/minio-funnel] minio_iam_user_policy_attachment.tf_backup: Refreshing state... [id=tf-backup-20260314163610110100000001] minio_iam_user_policy_attachment.cnpg: Refreshing state... [id=cnpg-20260302210642491000000001] kubernetes_secret_v1.tf_backup_s3_creds: Refreshing state... [id=tofu-state/tf-backup-s3-creds] kubernetes_secret_v1.cnpg_s3_creds: Refreshing state... [id=postgres/cnpg-s3-creds] kubernetes_cron_job_v1.tf_state_backup: Refreshing state... [id=tofu-state/tf-state-backup] kubernetes_ingress_v1.harbor_funnel: Refreshing state... [id=harbor/harbor-funnel] kubernetes_ingress_v1.woodpecker_funnel: Refreshing state... [id=woodpecker/woodpecker-funnel] No changes. Your infrastructure matches the configuration. OpenTofu has compared your real infrastructure against your configuration and found no differences, so no changes are needed. ```
forgejo_admin deleted branch 57-ci-reliability-add-lock-false-to-plan-us 2026-03-14 19:57:42 +00:00
Sign in to join this conversation.
No description provided.