Skip to content

Commit 25fd414

Browse files
authored
Merge pull request #167 from anyproto/generate-env
docker-generateconfig/env.py added defaultVersions
2 parents d4f7aed + b1e790b commit 25fd414

1 file changed

Lines changed: 66 additions & 17 deletions

File tree

docker-generateconfig/env.py

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,78 +10,127 @@
1010
'inputFile': '.env.default',
1111
'overrideFile': '.env.override',
1212
'outputFile': '.env',
13+
14+
# Mapping of env variable → API version key
1315
'overrideVarMap': {
1416
'ANY_SYNC_NODE_VERSION': 'pkg::any-sync-node',
1517
'ANY_SYNC_FILENODE_VERSION': 'pkg::any-sync-filenode',
1618
'ANY_SYNC_COORDINATOR_VERSION': 'pkg::any-sync-coordinator',
1719
'ANY_SYNC_CONSENSUSNODE_VERSION': 'pkg::any-sync-consensusnode',
1820
},
21+
22+
# Default versions to use if API is unavailable (values without leading 'v')
23+
'defaultVersions': {
24+
'ANY_SYNC_NODE_VERSION': '0.10.1',
25+
'ANY_SYNC_FILENODE_VERSION': '0.10.0',
26+
'ANY_SYNC_COORDINATOR_VERSION': '0.8.0',
27+
'ANY_SYNC_CONSENSUSNODE_VERSION': '0.5.0',
28+
},
29+
30+
# API endpoints for version maps
1931
'versionsUrlMap': {
2032
'prod': 'https://puppetdoc.anytype.io/api/v1/prod-any-sync-compatible-versions/',
2133
'stage1': 'https://puppetdoc.anytype.io/api/v1/stage1-any-sync-compatible-versions/',
2234
},
35+
36+
# Header to prepend to the generated output file
2337
'outputFileHeader': '''# !!! PLEASE DO NOT EDIT THIS FILE !!!
2438
# To make changes to the '.env', use the '.env.override' file
2539
# https://github.com/anyproto/any-sync-dockercompose/wiki/Configuration
2640
2741
''',
2842
}
2943

30-
# load variables from inputFile
44+
# Load variables from inputFile
3145
envVars = dict()
3246
if os.path.exists(cfg['inputFile']) and os.path.getsize(cfg['inputFile']) > 0:
3347
with open(cfg['inputFile']) as file:
3448
for line in file:
49+
# Skip comments and empty lines
3550
if line.startswith('#') or not line.strip():
3651
continue
52+
53+
# Parse KEY=VALUE pairs
3754
key, value = line.strip().split('=', 1)
3855
if key in envVars:
39-
print(f"WARNING: dublicate key={key} in env file={cfg['inputFile']}")
56+
print(f"WARNING: duplicate key={key} in env file={cfg['inputFile']}")
4057
envVars[key] = value
4158
else:
4259
print(f"ERROR: file={cfg['inputFile']} not found or size=0")
4360
exit(1)
4461

45-
# override variables from overrideFile
62+
# Override variables from overrideFile (if present)
4663
if os.path.exists(cfg['overrideFile']) and os.path.getsize(cfg['overrideFile']) > 0:
4764
with open(cfg['overrideFile']) as file:
4865
for line in file:
66+
# Skip comments and empty lines
4967
if line.startswith('#') or not line.strip():
5068
continue
69+
5170
key, value = line.strip().split('=', 1)
5271
envVars[key] = value
5372

54-
# api request
73+
# Perform API request; return None on failure
5574
def apiRequest(url):
5675
try:
5776
response = requests.get(url, timeout=(3.05, 5))
58-
jsonResponse = response.json()
5977
except Exception as e:
6078
print(f"failed response url={url}, error={str(e)}")
61-
exit(1)
79+
return None
80+
6281
if response.status_code != 200:
6382
print(f"failed response url={url}, status_code={response.status_code}, text={response.text}")
64-
exit(1)
83+
return None
84+
85+
try:
86+
jsonResponse = response.json()
87+
except Exception as e:
88+
print(f"failed parse json url={url}, error={str(e)}")
89+
return None
90+
6591
return jsonResponse
6692

67-
# get latest version
93+
# Fetch latest compatible versions for a given environment ("prod", "stage1")
6894
def getLatestVersions(role):
6995
versions = apiRequest(cfg['versionsUrlMap'][role])
70-
sortedVersions = dict(sorted(versions.items(), key=lambda x: int(x[0])))
71-
lastVersionsTimestamp, lastVersions = next(reversed(sortedVersions.items()))
96+
if not versions:
97+
return None
98+
99+
try:
100+
# API returns timestamps as string keys; sort numerically
101+
sortedVersions = dict(sorted(versions.items(), key=lambda x: int(x[0])))
102+
103+
# Take the last (latest) timestamp entry
104+
lastVersionsTimestamp, lastVersions = next(reversed(sortedVersions.items()))
105+
except Exception as e:
106+
print(f"failed to process versions for role={role}, error={str(e)}")
107+
return None
108+
72109
return lastVersions
73110

74-
# process variables
75-
for key,value in envVars.items():
111+
# Process variables that may require version substitution
112+
for key, value in envVars.items():
76113
if key in cfg['overrideVarMap'].keys():
114+
# value must match an API environment key ("prod", "stage1")
77115
if value in cfg['versionsUrlMap'].keys():
78116
latestVersions = getLatestVersions(value)
79-
lastVersionKey = cfg['overrideVarMap'].get(key)
80-
lastVersionValue = latestVersions.get(lastVersionKey)
81-
if lastVersionKey and lastVersionValue:
82-
envVars[key] = 'v'+str(lastVersionValue)
83117

84-
# save in output file
118+
if latestVersions:
119+
lastVersionKey = cfg['overrideVarMap'].get(key)
120+
lastVersionValue = latestVersions.get(lastVersionKey)
121+
122+
# If API returned a valid version → use it
123+
if lastVersionKey and lastVersionValue:
124+
envVars[key] = 'v' + str(lastVersionValue)
125+
continue # Continue to next env variable
126+
127+
# Fallback: use default version from config if API failed
128+
defaultVersion = cfg.get('defaultVersions', {}).get(key)
129+
if defaultVersion:
130+
print(f"using default version for {key}: {defaultVersion}")
131+
envVars[key] = 'v' + str(defaultVersion)
132+
133+
# Write final env file
85134
with open(cfg['outputFile'], 'w') as file:
86135
file.write(cfg['outputFileHeader'])
87136
for key, value in envVars.items():

0 commit comments

Comments
 (0)