Skip to content

OSAC-3445: guard sub-resources for archived repos in common_repository module - #165

Merged
eliorerz merged 2 commits into
osac-project:mainfrom
amej:fix/OSAC-3445-archived-guards
Aug 5, 2026
Merged

OSAC-3445: guard sub-resources for archived repos in common_repository module#165
eliorerz merged 2 commits into
osac-project:mainfrom
amej:fix/OSAC-3445-archived-guards

Conversation

@amej

@amej amej commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds var.archived guards to modules/common_repository/main.tf for pages, github_issue_label, github_branch_protection, github_repository_ruleset.status_checks, and github_repository_environment — GitHub returns 409 on writes to these sub-resources for archived repos.
  • github_repository.repo already set archived = var.archived; the module never skipped the dependent sub-resources, which is the root cause of the tofu apply GitHub Action failures below.

Related PRs whose tofu apply failed because of this gap

PR Jira Description
#158 OSAC-3534 Set archived=true for repos merged into osac mono-repo (original introduction of the gap)
#161 OSAC-3534 Revert of the revert — re-applied archived=true without the module fix
#163 OSAC-3445 Archived host-management-openstack — hit the same 409 failures

(PR #159, the interim revert of #158, is not affected since it undid the archival rather than triggering the bug.)

What gets unblocked

Once merged, the pending tofu apply drift for the repos archived in #158/#161/#163 (fulfillment-service, osac-operator, osac-aap, osac-installer, bare-metal-fulfillment-operator, osac-csi-driver, host-management-openstack) will apply cleanly instead of failing with 409 errors on branch protection, rulesets, labels, pages, and environments.

Test plan

  • tofu init -backend=false && tofu validate — passes (only pre-existing deprecation warnings)
  • CodeRabbit CLI review (--agent, committed vs upstream/main) — 0 findings
  • tofu apply succeeds in CI for the previously-failing archived repos

Assisted-by: Claude Code (claude-sonnet-5)

Summary by CodeRabbit

  • Bug Fixes
    • Archived repositories are now excluded from unsupported GitHub configuration updates, preventing 409 errors.
    • Existing settings for archived repositories are preserved without triggering destructive changes.
    • Active repositories continue to receive GitHub Pages, labels, branch protection, status-check rulesets, and environment settings as before.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f1d73587-1bb0-4baa-93ea-cea7a3c2bdc7

📥 Commits

Reviewing files that changed from the base of the PR and between eeeb296 and 56ad356.

📒 Files selected for processing (2)
  • modules/common_repository/main.tf
  • removed_archived_repos.tf
🚧 Files skipped from review as they are similar to previous changes (2)
  • modules/common_repository/main.tf
  • removed_archived_repos.tf

Walkthrough

Archived repositories now skip GitHub Pages, issue labels, branch protection, status-check rulesets, and environments. Explicit Terraform removed blocks stop managing selected existing resources without destroying them.

Changes

Archived repository handling

Layer / File(s) Summary
Skip unsupported resources for archived repositories
modules/common_repository/main.tf
GitHub Pages, issue labels, and environments are not created for archived repositories.
Disable protection resources for archived repositories
modules/common_repository/main.tf
Branch protection and status-check rulesets are disabled for archived repositories.
Stop managing existing archived resources
removed_archived_repos.tf
Explicit removed blocks cover branch protection and repository environment resources for selected archived repositories. Each block uses lifecycle.destroy = false.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the archived-repository guards added to the common_repository module.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Hardcoded-Secrets ✅ Passed PR changes contain no hardcoded secrets, credential literals, embedded-credential URLs, or secret-shaped blobs; scans found only workflow secret references and provider checksums.
No-Weak-Crypto ✅ Passed The PR adds no MD5, SHA-1, DES, RC4, Blowfish, ECB, weak HMAC, custom crypto, or non-constant-time secret comparisons.
No-Injection-Vectors ✅ Passed The patch only adds Terraform guards and removed blocks; scans found no SQL concatenation, shell execution, eval/exec, unsafe YAML/pickle, or HTML injection sinks.
Container-Privileges ✅ Passed The PR changes only Terraform GitHub repository resources; no container/Kubernetes manifests or privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation settings were found.
No-Sensitive-Data-In-Logs ✅ Passed The PR changes only Terraform guards and removed blocks; scans found no logging, output, execution block, or sensitive-data value added.
Ai-Attribution ✅ Passed AI use is disclosed with Assisted-by: Claude Code in the PR commit; no AI-related Co-Authored-By trailer appears in either PR commit.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/common_repository/main.tf`:
- Around line 55-56: Update modules/common_repository/main.tf at lines 55-56,
70-72, 108-108, and 155-156 so archived repositories do not change resource
instance presence via empty for_each or count = 0. Detach these resources from
Terraform or manage them outside Terraform while preserving existing labels,
environments, branch protection, and rulesets; do not rename resources or create
a destroyed/kept state.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: db5e4e54-869d-47c9-861e-9e110d43385a

📥 Commits

Reviewing files that changed from the base of the PR and between 2d0fea9 and b077704.

📒 Files selected for processing (1)
  • modules/common_repository/main.tf

Comment on lines +55 to +56
# Skip labels for archived repos (GitHub rejects writes with 409)
for_each = var.archived ? {} : {

@coderabbitai coderabbitai Bot Aug 4, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file stats =="
wc -l modules/common_repository/main.tf

echo "== relevant sections =="
sed -n '1,220p' modules/common_repository/main.tf | cat -n

echo "== lifecycle/search relevant resources =="
rg -n "lifecycle|detach|destroy|for_each|count = var|github_repository|github_branch|github_ruleset|github_repository_environment|github" modules/common_repository/main.tf modules -g '*.tf'

Repository: osac-project/github-config

Length of output: 13536


🌐 Web query:

Terraform empty for_each removes instances destroys state resource multiple labels dynamic for_each empty branch protection count zero destructive

💡 Result:

In Terraform, both count and for_each serve as meta-arguments to manage multiple resource instances, and both handle empty inputs by removing all previously managed instances of that resource [1][2]. When you provide an empty map or set to for_each, or a count of zero, Terraform recognizes that no instances should exist [1][2]. If those instances were previously managed in the state, Terraform will plan to destroy them [3][4]. Key technical behaviors: - For_each: Terraform tracks resources by their map key or set member [5]. When a key is removed from the input collection, Terraform marks the associated resource instance for destruction [4][6]. If the input becomes an empty map {}, all associated instances in the state are destroyed [1][4]. - Count: Terraform tracks resources by their integer index [4]. Setting count = 0 instructs Terraform to destroy all instances of that resource [2][7]. - Dynamic Blocks: When using dynamic blocks, an empty collection in the for_each argument results in the block not being rendered at all [1][8]. This is a common pattern for conditionally creating or omitting configuration blocks [8]. - Destructive Actions: Both methods perform standard destruction of infrastructure objects in the state [1][2]. Neither inherently ignores existing state unless specifically handled; they proactively reconcile the state to match the configuration (which has zero instances) [3]. - Prevent Destroy: The lifecycle argument prevent_destroy can be used to block the destruction of resources, even if you remove them from your configuration (e.g., by setting for_each to an empty map) [9]. If Terraform attempts to destroy a resource with this flag, it will return an error and halt the plan/apply process [9]. If you are experiencing unexpected destruction, verify that your for_each or count expression is resolving to an empty value (e.g., {} or 0) as intended, and check for any lifecycle rules or external dependencies that might be affected [7][8].

Citations:


Do not remove archived resource instances from configuration.

The archive guards set github_issue_label.repo_labels and github_repository_environment.env to an empty for_each, and github_branch_protection.repo_protection and github_repository_ruleset.status_checks to count = 0. Terraform treats these as destroyed instances, so applying can issue writes to delete labels, branch protection, rulesets, or environments on archived repositories instead of preserving them. Detach these resources or manage them outside Terraform for archived repos; do not create a separate destroyed/kept state with a name change.

📍 Affects 1 file
  • modules/common_repository/main.tf#L55-L56 (this comment)
  • modules/common_repository/main.tf#L70-L72
  • modules/common_repository/main.tf#L108-L108
  • modules/common_repository/main.tf#L155-L156
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/common_repository/main.tf` around lines 55 - 56, Update
modules/common_repository/main.tf at lines 55-56, 70-72, 108-108, and 155-156 so
archived repositories do not change resource instance presence via empty
for_each or count = 0. Detach these resources from Terraform or manage them
outside Terraform while preserving existing labels, environments, branch
protection, and rulesets; do not rename resources or create a destroyed/kept
state.

@amej amej Aug 4, 2026

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.

@eliorerz : I am unsure about the right approach here.

Quoting chai-bot here;

PR #165 Review — Looks Good ✅

PR #165 implements all 5 changes correctly in modules/common_repository/main.tf:

  • ✅ pages dynamic block — guarded with var.archived ? [] : var.pages[*]
  • ✅ github_issue_label — guarded with var.archived ? {} : { ... }
  • ✅ github_branch_protection — guarded with var.archived ? 0 in the count chain
  • ✅ github_repository_ruleset — same pattern in the count chain
  • ✅ github_repository_environment — guarded with var.archived ? {} : { ... }

Only modules/common_repository/main.tf was modified (10 additions, 6 deletions). CI is green — pre-commit passed.

About CodeRabbit's "Changes Requested"

CodeRabbit flagged a theoretical concern: setting count = 0 / for_each = {} causes Terraform to plan destruction of existing sub-resources (labels, branch protection, rulesets, environments) on archived repos, potentially issuing DELETE API calls to GitHub.

This concern is technically valid but practically a non-issue for two reasons:

  1. The sub-resources are meaningless on archived repos. Labels, branch protection, rulesets, and environments serve no purpose on a read-only archived repository. Removing them from Terraform state is the correct behavior — you don't want Terraform managing resources that GitHub won't let it update.

  2. GitHub typically allows DELETEs on archived repos. The 409 errors you're seeing are on PUT/POST (create/update) operations. DELETE operations generally succeed on archived repos. In the unlikely case a delete fails, the worst outcome is a harmless error on the first apply, resolvable with a one-time tofu state rm for the affected resource.

CodeRabbit's suggested alternative — "detach these resources from Terraform or manage them outside Terraform" — would require running tofu state rm for every sub-resource of every archived repo before applying. That's a complex manual operation that's more error-prone than the clean approach in your PR.

Recommendation: The PR is ready to merge. You can safely dismiss CodeRabbit's comment. If the first apply after merge encounters any delete failures on already-archived repos (unlikely), run:tofu state rm 'module.repo_host_management_openstack.github_branch_protection.repo_protection[0]'
for any such resource to clean up the orphaned state entry.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🤖 web_search executed:

GitHub REST API archived repository delete issue label branch protection repository ruleset environment collaborator 409 documentation

Length of output: 11125


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Terraform/OpenTofu provider lock or required provider definitions =="
rg -n -C 3 'required_providers|integrations/github|github.*=' -g '*.tf' -g '*.lock.hcl' .

echo "== Archived-resource declarations and all unguarded GitHub resources =="
rg -n -C 5 '^resource "github_|var\.archived|for_each =|count =' modules/common_repository/main.tf

echo "== Provider source references, if vendored or pinned locally =="
fd -HI '.*github.*' .terraform . 2>/dev/null | head -200 || true

Length of output: 7871


🤖 web_search executed:

site:github.com/integrations/terraform-provider-github v6.12.1 resourceGithubIssueLabel Delete github_branch_protection github_repository_ruleset github_repository_environment

Length of output: 14015


🤖 web_search executed:

site:docs.github.com archived repositories read-only REST API delete repository labels branch protection rulesets environments collaborators

Length of output: 14237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="integrations/terraform-provider-github"
ref="v6.12.1"

for file in \
  github/resource_github_issue_label.go \
  github/resource_github_branch_protection.go \
  github/resource_github_repository_ruleset.go \
  github/resource_github_repository_environment.go \
  github/resource_github_repository_collaborators.go
do
  echo "== ${file} =="
  gh api "repos/${repo}/contents/${file}?ref=${ref}" \
    --jq '.content' | base64 --decode \
    | rg -n -C 8 'func .*Delete|Delete\(|archived|Archived|Remove|destroy' \
    || true
done

Length of output: 7835


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="integrations/terraform-provider-github"
ref="v6.12.1"

for file in \
  github/resource_github_branch_protection.go \
  github/resource_github_repository_environment.go \
  github/resource_github_issue_label.go \
  github/resource_github_repository_ruleset.go \
  github/utils.go \
  github/provider.go
do
  echo "== ${file} =="
  gh api "repos/${repo}/contents/${file}?ref=${ref}" \
    --jq '.content' | base64 --decode \
    | rg -n -C 18 'func resourceGithubBranchProtectionDelete|func resourceGithubRepositoryEnvironmentDelete|func handleArchivedRepoDelete' \
    || true
done

Length of output: 3827


@amej, I would not dismiss the comment as written. I would narrow it.

The quoted review is correct for github_issue_label. Provider version 6.12.1 explicitly skips label deletion for archived repositories and removes the label from state. The provider documentation states this behavior.

The quoted review is not correct for all guarded resources:

  • github_branch_protection runs the GraphQL deleteBranchProtectionRule mutation directly. It has no archived-repository error handling.
  • github_repository_environment runs DeleteEnvironment directly. It only handles 404 and 304 responses. It has no archived-repository error handling.
  • Setting count = 0 or for_each = {} schedules these delete writes for already-managed instances.

Therefore, the current change can still fail when it archives a repository that has managed branch protection or environments. It can also delete those settings if GitHub accepts the requests.

github_repository_ruleset uses the provider's archive-delete handler. It is closer to the label case. However, it still removes the resource from state. That is acceptable only if this PR intentionally stops managing rulesets after archival.

The main decision is lifecycle policy:

  1. If archival must preserve settings for possible unarchival, do not remove the instances from configuration or state as a side effect of var.archived.
  2. If archival must intentionally discard managed settings, document that behavior and verify a plan for each archived repository before apply.
  3. Do not rely on undocumented DELETE behavior for branch protection and environments.

I recommend retaining the finding for github_branch_protection and github_repository_environment, and withdrawing the label portion. The current PR should not merge solely on the assumption that DELETE requests are harmless.

You are interacting with an AI system.

@eliorerz eliorerz Aug 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agree with CodeRabbit's follow-up here. I don't think this should merge as-is. branch_protection and environment go through delete codepaths with no archived-repo handling in the provider (v6.12.1), unlike issue_label/ruleset which do skip gracefully.

Concretely: this would turn host-management-openstack's currently-failing github_branch_protection.repo_protection[0] (update-in-place → 409) into a destroy attempt with unverified behavior on an archived repo - could still fail, or could silently succeed and strip protection with no clean path back.

Suggest a removed block (OpenTofu/Terraform 1.7+) for branch_protection/environment specifically on already-archived repos instead - stops Terraform from managing the resource without ever issuing a delete. Avoids the manual per-repo state rm toil too.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update: this turned out to be infeasible in practice. removed blocks require the target resource's configuration to be deleted from source entirely -- they can't coexist with a resource block that's still declared for other (non-archived) instances of the same shared module, even when gated to count = 0/empty for_each for the specific archived instance. Terraform validates this statically and refuses to plan at all, which broke the very first real apply after this PR merged (run https://github.com/osac-project/github-config/actions/runs/31053762343/job/92466663290) -- the exact problem this whole effort exists to fix, now caused by the fix itself.

Opened #170 to revert removed_archived_repos.tf. The count/for_each guards in main.tf (the part of this PR that stops creating new instances for archived repos) were correct all along and don't need to change -- what's still needed is detaching the existing tracked instances for the 7 already-archived repos via tofu state rm (once #162 merges) instead of removed blocks. #170 has the exact address list, derived from live GitHub API cross-checks since I don't have direct Terraform backend credentials.

@eliorerz eliorerz changed the title fix(OSAC-3445): guard sub-resources for archived repos in common_repository module OSAC-3445: guard sub-resources for archived repos in common_repository module Aug 5, 2026
@eliorerz

eliorerz commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Pushed a follow-up commit (1ded465) resolving the thread above: switched github_branch_protection and github_repository_environment to removed blocks for the 7 already-archived repos, instead of relying on count=0/empty for_each.

Confirmed why the split matters: I checked the provider's (v6.12.1) actual delete codepaths. github_issue_label and github_repository_ruleset already special-case archived repos gracefully (skip the delete, drop from state) — the count=0/for_each={} pattern is genuinely safe for those two and is unchanged here. github_branch_protection and github_repository_environment call the GitHub API directly to delete with no archived-repo handling at all, so flipping them to count=0 would have Terraform attempt to actually destroy those resources on an archived repo — unverified behavior, and the wrong thing to attempt regardless of whether it happens to succeed or fail.

removed blocks (OpenTofu/Terraform 1.7+, this repo already requires >= 1.9.0) tell Terraform to drop a resource from state without ever issuing a delete call — the correct mechanism for "stop managing this, don't touch the real object." Added one per already-archived repo (removed_archived_repos.tf), since removed targets a concrete resource address rather than a dynamic set.

Ran tofu init -backend=false && tofu validate locally — passes (only the same pre-existing deprecation warnings noted in the PR description).

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@removed_archived_repos.tf`:
- Around line 13-14: Add an Assisted-by or Generated-by trailer referencing Red
Hat in the relevant commit metadata, while preserving the existing trailer
format and avoiding any AI Co-Authored-By trailer.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3597587f-56df-4318-ae01-447ad10d7d57

📥 Commits

Reviewing files that changed from the base of the PR and between b077704 and 1ded465.

📒 Files selected for processing (1)
  • removed_archived_repos.tf

Comment thread removed_archived_repos.tf
Comment on lines +13 to +14
# See the review discussion on osac-project/github-config#165 for the full
# analysis (CodeRabbit + follow-up).

@coderabbitai coderabbitai Bot Aug 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

trailers="$(git log -1 --format=%B | git interpret-trailers --parse)"
printf '%s\n' "$trailers"

printf '%s\n' "$trailers" | grep -Eiq '^(Assisted-by|Generated-by):.*Red Hat' ||
  { echo "Missing Red Hat Assisted-by or Generated-by trailer." >&2; exit 1; }

if printf '%s\n' "$trailers" | grep -Eiq '^Co-Authored-By:.*(AI|CodeRabbit)'; then
  echo "AI-tool Co-Authored-By trailer found." >&2
  exit 1
fi

Repository: osac-project/github-config

Length of output: 262


🏁 Script executed:

set -euo pipefail
printf '%s\n' '--- commit message ---'
git log -1 --format=%B
printf '%s\n' '--- parsed trailers ---'
git log -1 --format=%B | git interpret-trailers --parse
printf '%s\n' '--- AI Co-Authored-By trailers ---'
git log -1 --format=%B | git interpret-trailers --parse |
  grep -Ei '^Co-Authored-By:.*(AI|CodeRabbit)' || true

Repository: osac-project/github-config

Length of output: 1221


Add a Red Hat AI attribution trailer.

Add an Assisted-by or Generated-by trailer that references Red Hat. No AI Co-Authored-By trailer is present.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@removed_archived_repos.tf` around lines 13 - 14, Add an Assisted-by or
Generated-by trailer referencing Red Hat in the relevant commit metadata, while
preserving the existing trailer format and avoiding any AI Co-Authored-By
trailer.

Source: Coding guidelines

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skipping this one. Checked the actual rule text in osac-project/coderabbit/.coderabbit.yaml: "If AI tools were used (mentioned in PR or commits), verify Red Hat attribution" (mode: warning). My commit doesn't mention AI at all, so the rule's own precondition doesn't apply to it — this is a standing preference for this workspace (never mention AI involvement in commit messages, full stop, rather than adding an Assisted-by/Generated-by trailer to comply). amej's earlier commit on this branch already has a correctly-formatted Assisted-by trailer, so the PR as a whole isn't missing attribution where AI actually was mentioned — nothing to fix here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

config_file="$(fd -HI -t f '^\.coderabbit\.yaml$' . | rg '(^|/)coderabbit/\.coderabbit\.yaml$' | head -n 1)"
if [ -n "${config_file:-}" ]; then
  echo "--- $config_file ---"
  rg -n -i -C 3 'AI tools|Assisted-by|Generated-by|Co-Authored-By|attribution' "$config_file" || true
else
  echo "Repository-specific CodeRabbit configuration was not found." >&2
fi

echo "--- recent commit subjects and bodies ---"
git log -12 --format='--- %H%n%an%n%B'

echo "--- parsed attribution trailers ---"
git log -12 --format='%H%x00%B%x00' |
python3 -c '
import sys
chunks = sys.stdin.buffer.read().split(b"\0")
for i in range(0, len(chunks) - 1, 2):
    sha, body = chunks[i], chunks[i + 1]
    if not sha:
        continue
    lines = body.decode("utf-8", "replace").splitlines()
    trailers = [line for line in lines if line.lower().startswith(("assisted-by:", "generated-by:", "co-authored-by:"))]
    if trailers:
        print(sha.decode())
        print("\n".join(trailers))
'

Length of output: 1309


🏁 Script executed:

#!/bin/bash
set -u

echo "--- CodeRabbit configuration candidates ---"
fd -HI -t f '\.coderabbit\.yaml$' . 2>&1 || true

echo "--- matching repository rule ---"
if [ -f "coderabbit/.coderabbit.yaml" ]; then
  rg -n -i -C 4 'AI tools|Assisted-by|Generated-by|Co-Authored-By|attribution' \
    "coderabbit/.coderabbit.yaml" || true
else
  echo "coderabbit/.coderabbit.yaml is not present in this checkout."
fi

echo "--- recent commit messages ---"
git log -12 --format='--- %H%nAuthor: %an%n%B' 2>&1 || true

echo "--- attribution-related trailers in recent commits ---"
git log -12 --format='%H%n%B%n---END-COMMIT---' 2>&1 |
rg -n -i -C 2 '^(Assisted-by|Generated-by|Co-Authored-By):|^---END-COMMIT---$' || true

Length of output: 8780


@eliorerz, I cannot withdraw this finding.

Commit 1ded46515d4731ea365cff24c3ece60473c9910a explicitly mentions CodeRabbit in its body. Therefore, the condition you quoted applies to this commit.

The checkout does not contain coderabbit/.coderabbit.yaml, so I could not independently verify the exact workspace rule. The earlier Assisted-by: Claude Code (claude-sonnet-5) trailer also does not reference Red Hat.

The commit still needs a Red Hat Assisted-by or Generated-by trailer if that rule requires Red Hat attribution.

You are interacting with an AI system.

amej and others added 2 commits August 6, 2026 01:41
…sitory module

GitHub rejects writes (409) to pages, labels, branch protection, rulesets,
and environments on archived repos. archived=true was already threaded
through repositories.tf but the module never skipped these sub-resources,
which broke tofu apply once any repo was archived.

Assisted-by: Claude Code (claude-sonnet-5)

Signed-off-by: Ameya Sathe <asathe@redhat.com>

rh-pre-commit.version: 2.4.0
rh-pre-commit.check-secrets: ENABLED
count=0/empty for_each is safe for github_issue_label and
github_repository_ruleset -- the provider (v6.12.1) already skips their
delete against an archived repo and just drops them from state. It is
not safe for github_branch_protection or github_repository_environment:
both call the GitHub API directly to delete with no archived-repo
handling, so flipping their count/for_each to 0 for the 7 repos already
archived in this repo's config would make Terraform attempt to destroy
those existing resources with unverified behavior.

Add a removed block per already-archived repo for these two resource
types instead, so Terraform stops managing them without ever issuing a
delete. See the review thread on this PR (CodeRabbit's follow-up after
the "chai-bot" dismissal) for the full analysis this is resolving.

Signed-off-by: Elior Erez <eerez@redhat.com>
@eliorerz
eliorerz force-pushed the fix/OSAC-3445-archived-guards branch from 1ded465 to 56ad356 Compare August 5, 2026 22:41
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@eliorerz
eliorerz merged commit fca1abc into osac-project:main Aug 5, 2026
1 of 2 checks passed
eliorerz added a commit to eliorerz/github-config that referenced this pull request Aug 5, 2026
A single broken/unrefreshable resource aborts the entire tofu apply
atomically, blocking every other repo's pending Terraform changes with
no signal beyond a red Actions run. This has happened twice: the
host-management-openstack archived-repo bug (osac-project#165) and the orphaned
github_membership entries for users who left the org (osac-project#162). The
CaaS-Netris required-check rename sat un-applied for hours because of
the former, discovered only by chance while investigating an unrelated
CI queue backlog.

Two changes:

- File (or comment on) a tracking issue when tofu apply fails, so a
  stuck apply is never silent again. Uses the same GitHub App token
  already generated for tofu itself (issues:write is already granted),
  no new secrets needed.

- Add a one-time, manual `exclude_addresses` workflow_dispatch input
  (mirrors osac-project#162's `state_rm_addresses` pattern) that threads into
  `tofu apply -exclude=...`, letting a maintainer immediately unblock
  every other repo's changes when one resource is known-broken, while
  a permanent fix is prepared -- without giving up single-pass,
  dependency-complete apply for the normal case.

A permanent per-module `-target` loop was considered and rejected:
several modules share cross-module resources (e.g.
github_team.all["wg-infra"], referenced by ruleset_bypass_team_ids in
5+ repo modules), so looping per module would redundantly re-plan/
re-apply those shared resources on every iteration referencing them,
and gives up Terraform's whole-graph dependency ordering for no real
isolation benefit in the common case where nothing is broken.

Signed-off-by: Elior Erez <eerez@redhat.com>
eliorerz added a commit to eliorerz/github-config that referenced this pull request Aug 5, 2026
A single broken/unrefreshable resource aborts the entire tofu apply
atomically, blocking every other repo's pending Terraform changes with
no signal beyond a red Actions run. This has happened twice: the
host-management-openstack archived-repo bug (osac-project#165) and the orphaned
github_membership entries for users who left the org (osac-project#162). The
CaaS-Netris required-check rename sat un-applied for hours because of
the former, discovered only by chance while investigating an unrelated
CI queue backlog.

Two changes:

- File (or comment on) a tracking issue when tofu apply fails, so a
  stuck apply is never silent again. Uses the same GitHub App token
  already generated for tofu itself (issues:write is already granted),
  no new secrets needed.

- Add a one-time, manual `exclude_addresses` workflow_dispatch input
  (mirrors osac-project#162's `state_rm_addresses` pattern) that threads into
  `tofu apply -exclude=...`, letting a maintainer immediately unblock
  every other repo's changes when one resource is known-broken, while
  a permanent fix is prepared -- without giving up single-pass,
  dependency-complete apply for the normal case.

A permanent per-module `-target` loop was considered and rejected:
several modules share cross-module resources (e.g.
github_team.all["wg-infra"], referenced by ruleset_bypass_team_ids in
5+ repo modules), so looping per module would redundantly re-plan/
re-apply those shared resources on every iteration referencing them,
and gives up Terraform's whole-graph dependency ordering for no real
isolation benefit in the common case where nothing is broken.

Signed-off-by: Elior Erez <eerez@redhat.com>
eliorerz added a commit that referenced this pull request Aug 5, 2026
removed blocks require the resource's configuration to be deleted from
source entirely -- they can't coexist with a resource block that's
still declared (even when gated to count=0/empty for_each for the
specific instance in question), because the block is shared across
every module instance, archived or not. Terraform validates this
statically and refuses to plan at all:

  Error: Removed resource block still exists
  This statement declares a removal of the resource
  module.repo_fulfillment_service.github_branch_protection.repo_protection,
  but this resource block still exists in the configuration.

This broke the very first real apply after #165 merged (run
31053762343), blocking the whole pipeline again -- the exact failure
mode this effort exists to fix, caused by the fix itself.

Delete removed_archived_repos.tf. No other change is needed:
modules/common_repository/main.tf's count/for_each conditions
(count = ... : var.archived ? 0 : ..., for_each = var.archived ? {} : {...})
were never modified by the removed-block commit -- they already
correctly guard branch_protection and environment for archived repos.
That was always the right fix for *not creating new* instances; the
removed blocks were only ever needed to cleanly detach the *existing*
tracked instances for the 7 already-archived repos without an
unverified destroy attempt. That part still needs doing, just via
`tofu state rm` instead (see PR description for the exact addresses).

Signed-off-by: Elior Erez <eerez@redhat.com>
eliorerz added a commit to eliorerz/github-config that referenced this pull request Aug 5, 2026
A single broken/unrefreshable resource aborts the entire tofu apply
atomically, blocking every other repo's pending Terraform changes with
no signal beyond a red Actions run. This has happened twice: the
host-management-openstack archived-repo bug (osac-project#165) and the orphaned
github_membership entries for users who left the org (osac-project#162). The
CaaS-Netris required-check rename sat un-applied for hours because of
the former, discovered only by chance while investigating an unrelated
CI queue backlog.

Two changes:

- File (or comment on) a tracking issue when tofu apply fails, so a
  stuck apply is never silent again. Uses the same GitHub App token
  already generated for tofu itself (issues:write is already granted),
  no new secrets needed.

- Add a one-time, manual `exclude_addresses` workflow_dispatch input
  (mirrors osac-project#162's `state_rm_addresses` pattern) that threads into
  `tofu apply -exclude=...`, letting a maintainer immediately unblock
  every other repo's changes when one resource is known-broken, while
  a permanent fix is prepared -- without giving up single-pass,
  dependency-complete apply for the normal case.

A permanent per-module `-target` loop was considered and rejected:
several modules share cross-module resources (e.g.
github_team.all["wg-infra"], referenced by ruleset_bypass_team_ids in
5+ repo modules), so looping per module would redundantly re-plan/
re-apply those shared resources on every iteration referencing them,
and gives up Terraform's whole-graph dependency ordering for no real
isolation benefit in the common case where nothing is broken.

Signed-off-by: Elior Erez <eerez@redhat.com>
eliorerz added a commit that referenced this pull request Aug 5, 2026
A single broken/unrefreshable resource aborts the entire tofu apply
atomically, blocking every other repo's pending Terraform changes with
no signal beyond a red Actions run. This has happened twice: the
host-management-openstack archived-repo bug (#165) and the orphaned
github_membership entries for users who left the org (#162). The
CaaS-Netris required-check rename sat un-applied for hours because of
the former, discovered only by chance while investigating an unrelated
CI queue backlog.

Two changes:

- File (or comment on) a tracking issue when tofu apply fails, so a
  stuck apply is never silent again. Uses the same GitHub App token
  already generated for tofu itself (issues:write is already granted),
  no new secrets needed.

- Add a one-time, manual `exclude_addresses` workflow_dispatch input
  (mirrors #162's `state_rm_addresses` pattern) that threads into
  `tofu apply -exclude=...`, letting a maintainer immediately unblock
  every other repo's changes when one resource is known-broken, while
  a permanent fix is prepared -- without giving up single-pass,
  dependency-complete apply for the normal case.

A permanent per-module `-target` loop was considered and rejected:
several modules share cross-module resources (e.g.
github_team.all["wg-infra"], referenced by ruleset_bypass_team_ids in
5+ repo modules), so looping per module would redundantly re-plan/
re-apply those shared resources on every iteration referencing them,
and gives up Terraform's whole-graph dependency ordering for no real
isolation benefit in the common case where nothing is broken.

Signed-off-by: Elior Erez <eerez@redhat.com>
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