Skip to content

fix: preserve .env overrides during git directory sync#3095

Merged
kmendell merged 1 commit into
mainfrom
fix/env-hardening
Jul 4, 2026
Merged

fix: preserve .env overrides during git directory sync#3095
kmendell merged 1 commit into
mainfrom
fix/env-hardening

Conversation

@kmendell

@kmendell kmendell commented Jul 1, 2026

Copy link
Copy Markdown
Member

Checklist

  • This PR is not opened from my fork’s main branch
  • All new user-facing strings are translated via Paraglide (m.*())

What This PR Implements

Fixes: #2476

Changes Made

Testing Done

AI Tool Used (if applicable)

Additional Context

Disclaimer Greptiles Reviews use AI, make sure to check over its work.

To better help train Greptile on our codebase, if the comment is useful and valid Like the comment, if its not helpful or invalid Dislike

To have Greptile Re-Review the changes, mention greptileai.

Greptile Summary

This PR fixes a bug (issue #2476) where .env overrides edited in Arcane were silently wiped on every git directory sync because .env was being raw-written from the git payload instead of being routed through the three-file override merge (gitEnvContent.env.git, project.env, .env).

  • Core fix (gitops_sync_service.go): partitionReservedRootEnvFilesInternal splits the git payload so .env is captured as gitEnvContent (not written directly), then applyGitSyncEnvToDirInternal runs the same three-file merge that single-file sync uses. A companion filterReservedRootEnvFilesInternal drops .env from the old tracked-files list so CleanupRemovedFiles does not treat it as "removed by git" and delete the live-copied stage .env before the merge step reads it (addressing the migration case).
  • Permission-locked env files (env.go, project_service.go): readOptionalProjectFileInternal now returns an unreadable flag for os.ErrPermission; WriteManagedEnvFile skips writes to locked files rather than aborting the sync.
  • Lenient compose validation (project_service.go, load.go): validateComposeContentForUpdate gains a lenient bool parameter; git sync paths now tolerate undefined ${VAR} references that would previously fail with typed-decode errors during validation.

Confidence Score: 5/5

Safe to merge — the change is well-scoped to the directory sync path, backward-compatible via the legacy .env filter, and covered by three new regression tests.

The two concerns flagged in the previous review are both addressed: legacy sync.SyncedFiles entries containing .env are filtered before CleanupRemovedFiles sees them, and reserved-file drops from the git payload now emit slog.Warn entries. No new correctness issues were found after tracing the staging flow, the envContentChangedInternal signal, and the permission-locked skip path end-to-end.

No files require special attention.

Comments Outside Diff (2)

  1. backend/internal/services/gitops_sync_service.go, line 87-107 (link)

    P2 Silent drop of reserved files from git payload — no warning logged

    partitionReservedRootEnvFilesInternal drops .env.git, project.env, and .env.global from the git payload without emitting any log entry. Every other "skip" in this PR (permission-locked reads in readOptionalProjectFileInternal, seedStageEnvFromCandidateDirInternal, WriteManagedEnvFile) logs a slog.Warn. A git repo that accidentally commits .env.git or project.env — or intentionally commits .env.global (which was previously raw-written) — will have those files silently dropped with no trace in the logs, making the behavior change invisible to operators.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: backend/internal/services/gitops_sync_service.go
    Line: 87-107
    
    Comment:
    **Silent drop of reserved files from git payload — no warning logged**
    
    `partitionReservedRootEnvFilesInternal` drops `.env.git`, `project.env`, and `.env.global` from the git payload without emitting any log entry. Every other "skip" in this PR (permission-locked reads in `readOptionalProjectFileInternal`, `seedStageEnvFromCandidateDirInternal`, `WriteManagedEnvFile`) logs a `slog.Warn`. A git repo that accidentally commits `.env.git` or `project.env` — or intentionally commits `.env.global` (which was previously raw-written) — will have those files silently dropped with no trace in the logs, making the behavior change invisible to operators.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

    Fix in Codex Fix in Claude Code

  2. backend/internal/services/gitops_sync_service.go, line 1711 (link)

    P1 Preserve migrated env
    When an existing directory sync was created before this change, sync.SyncedFiles contains .env; this call now compares it to syncedFiles after .env has been filtered out, so CleanupRemovedFiles deletes the copied live .env from the stage before applyGitSyncEnvToDirInternal can read it. With no prior .env.git/project.env, the merge falls back to the git .env and loses the Arcane-edited value during the first sync after upgrade.

    Rule Used: What: When implementing a feature, modify and reus... (source)

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: backend/internal/services/gitops_sync_service.go
    Line: 1711
    
    Comment:
    **Preserve migrated env**
    When an existing directory sync was created before this change, `sync.SyncedFiles` contains `.env`; this call now compares it to `syncedFiles` after `.env` has been filtered out, so `CleanupRemovedFiles` deletes the copied live `.env` from the stage before `applyGitSyncEnvToDirInternal` can read it. With no prior `.env.git`/`project.env`, the merge falls back to the git `.env` and loses the Arcane-edited value during the first sync after upgrade.
    
    **Rule Used:** What: When implementing a feature, modify and reus... ([source](https://app.greptile.com/ofkm/-/custom-context?memory=0983d2ab-8ef9-4463-85d5-a790cefce423))
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Codex Fix in Claude Code

Reviews (3): Last reviewed commit: "fix: preserve .env overrides during git ..." | Re-trigger Greptile

@kmendell kmendell marked this pull request as ready for review July 1, 2026 00:29

kmendell commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@kmendell kmendell requested a review from a team July 1, 2026 00:29
@getarcaneappbot

getarcaneappbot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Container images for this PR have been built successfully!

  • Manager: ghcr.io/getarcaneapp/manager:pr-3095
  • Agent: ghcr.io/getarcaneapp/agent:pr-3095

Built from commit 23eb493

@kmendell kmendell force-pushed the fix/env-hardening branch 8 times, most recently from 66131b1 to 2484b55 Compare July 3, 2026 00:35
@kmendell kmendell force-pushed the fix/env-hardening branch from 2484b55 to 23eb493 Compare July 3, 2026 16:06
@kmendell kmendell merged commit b975259 into main Jul 4, 2026
34 of 35 checks passed
@kmendell kmendell deleted the fix/env-hardening branch July 4, 2026 00:20
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.

🐞 Bug: Git sync reverts changes made to .env

2 participants