Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create env files from templates in a change-preserving way #5099

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ logs/

# Environment
.env
.env.bkp-*
.ov_profile.json

# Python environments
Expand Down
68 changes: 62 additions & 6 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,73 @@ lint-codeowners checks="stable":
# Init #
########

# Smart copy .env files from templates
_env src dest:
#!/usr/bin/env python3
import datetime
import filecmp
from pathlib import Path
import shutil

src = Path("{{ src }}")
dest = Path("{{ dest }}")
print(f"Creating {dest} from {src}.")

if dest.exists() and not filecmp.cmp(src, dest):
# If there is an existing env file, back it up.
ts = datetime.datetime.now().strftime("%Y-%m-%d")
bkp = dest.with_suffix(f"{dest.suffix}.bkp-{ts}")
print(f"Backing up existing {dest} to {bkp}.")
shutil.copy(dest, bkp)
else:
# If there is no existing env file, only copy the template.
shutil.copy(src, dest)
exit(0)

# Read existing env file and store contents.
existing_env = {
key: value
for line in dest.read_text().splitlines()
if line and not line.startswith("#")
for key, _, value in [line.partition("=")]
if key and value
}

with dest.open("w") as dest_file:
for line in src.read_text().splitlines():
# Write comments and empty lines unchanged.
if not line or line.startswith("#"):
dest_file.write(f"{line}\n")
continue

key, _, value = line.partition("=")

# If existing value is changed, keep the existing value.
existing_value = existing_env.pop(key, None)
if existing_value and existing_value != value:
print(f"{key}={existing_value} (existing)")
value = existing_value

dest_file.write(f"{key}={value}\n")

# Keep extra variables that are not in the env template.
if len(existing_env):
dest_file.write("\n# Preserved variables\n")
for key, value in existing_env.items():
print(f"{key}={value} (preserved)")
dest_file.write(f"{key}={value}\n")

# Create .env files from templates
@env:
# Root
([ ! -f .env ] && cp env.template .env) || true
just _env env.template .env
# Docker
([ ! -f docker/minio/.env ] && cp docker/minio/env.template docker/minio/.env) || true
just _env docker/minio/env.template docker/minio/.env
# First-party services
([ ! -f catalog/.env ] && cp catalog/env.template catalog/.env) || true
([ ! -f ingestion_server/.env ] && cp ingestion_server/env.template ingestion_server/.env) || true
([ ! -f indexer_worker/.env ] && cp indexer_worker/env.template indexer_worker/.env) || true
([ ! -f api/.env ] && cp api/env.template api/.env) || true
just _env catalog/env.template catalog/.env
just _env ingestion_server/env.template ingestion_server/.env
just _env indexer_worker/env.template indexer_worker/.env
just _env api/env.template api/.env

##########
# Docker #
Expand Down