Skip to content

Commit 0146c5a

Browse files
Use local agent-version.cache even without CI_PIPELINE_ID.
Omnibus drops CI_PIPELINE_ID, so Windows resource versioning skipped the cache and ran git describe on a shallow clone. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent db4c825 commit 0146c5a

2 files changed

Lines changed: 74 additions & 34 deletions

File tree

tasks/libs/releasing/version.py

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,36 @@ def _get_release_version_from_release_json(release_json, version_re, release_jso
261261
return release_component_version
262262

263263

264+
def _load_agent_version_cache(ctx, pipeline_id=None, project_name=None):
265+
"""Return parsed agent-version.cache contents, or None if unavailable.
266+
267+
A local cache file is used whenever it exists. S3 is only contacted when the
268+
file is missing and CI coordinates are present. This matters for Omnibus:
269+
its sanitized environment omits CI_PIPELINE_ID, so Windows package builds
270+
cannot re-fetch the cache, but they do copy the file into the source tree.
271+
"""
272+
if project_name is None:
273+
project_name = os.getenv("CI_PROJECT_NAME")
274+
try:
275+
cache_exists = os.path.exists(AGENT_VERSION_CACHE_NAME)
276+
if not cache_exists and pipeline_id and str(pipeline_id).isdigit() and project_name == REPO_NAME:
277+
result = ctx.run(
278+
f"aws s3 cp s3://dd-ci-artefacts-build-stable/datadog-agent/{pipeline_id}/{AGENT_VERSION_CACHE_NAME} .",
279+
hide="stdout",
280+
)
281+
if "unable to locate credentials" in result.stderr.casefold():
282+
raise Exit("Permanent error: unable to locate credentials, retry the job", 42)
283+
cache_exists = True
284+
if not cache_exists:
285+
return None
286+
with open(AGENT_VERSION_CACHE_NAME) as file:
287+
return json.load(file)
288+
except (OSError, json.JSONDecodeError) as e:
289+
# If a cache file is found but corrupted we ignore it.
290+
print(f"Error while recovering the version from {AGENT_VERSION_CACHE_NAME}: {e}", file=sys.stderr)
291+
return None
292+
293+
264294
def get_version(
265295
ctx,
266296
url_safe=False,
@@ -280,28 +310,15 @@ def get_version(
280310

281311
project_name = os.getenv("CI_PROJECT_NAME")
282312
try:
283-
agent_version_cache_file_exist = os.path.exists(AGENT_VERSION_CACHE_NAME)
284-
if not agent_version_cache_file_exist:
285-
if pipeline_id and pipeline_id.isdigit() and project_name == REPO_NAME:
286-
result = ctx.run(
287-
f"aws s3 cp s3://dd-ci-artefacts-build-stable/datadog-agent/{pipeline_id}/{AGENT_VERSION_CACHE_NAME} .",
288-
hide="stdout",
289-
)
290-
if "unable to locate credentials" in result.stderr.casefold():
291-
raise Exit("Permanent error: unable to locate credentials, retry the job", 42)
292-
agent_version_cache_file_exist = True
293-
294-
if agent_version_cache_file_exist:
295-
with open(AGENT_VERSION_CACHE_NAME) as file:
296-
cache_data = json.load(file)
297-
313+
cache_data = _load_agent_version_cache(ctx, pipeline_id=pipeline_id, project_name=project_name)
314+
if cache_data:
298315
version, pre, commits_since_version, git_sha, pipeline_id = cache_data[major_version]
299316
# Dev's versions behave the same as nightly
300317
is_nightly = cache_data["nightly"] or cache_data["dev"]
301318

302319
if pre and include_pre:
303320
version = f"{version}-{pre}"
304-
except (OSError, json.JSONDecodeError, IndexError) as e:
321+
except (IndexError, KeyError, TypeError, ValueError) as e:
305322
# If a cache file is found but corrupted we ignore it.
306323
print(f"Error while recovering the version from {AGENT_VERSION_CACHE_NAME}: {e}", file=sys.stderr)
307324
version = ""
@@ -344,24 +361,14 @@ def get_version_numeric_only(ctx, major_version='7'):
344361
version = ""
345362
pipeline_id = os.getenv("CI_PIPELINE_ID")
346363
project_name = os.getenv("CI_PROJECT_NAME")
347-
if pipeline_id and pipeline_id.isdigit() and project_name == REPO_NAME:
348-
try:
349-
if not os.path.exists(AGENT_VERSION_CACHE_NAME):
350-
result = ctx.run(
351-
f"aws s3 cp s3://dd-ci-artefacts-build-stable/datadog-agent/{pipeline_id}/{AGENT_VERSION_CACHE_NAME} .",
352-
hide="stdout",
353-
)
354-
if "unable to locate credentials" in result.stderr.casefold():
355-
raise Exit("Permanent error: unable to locate credentials, retry the job", 42)
356-
357-
with open(AGENT_VERSION_CACHE_NAME) as file:
358-
cache_data = json.load(file)
359-
364+
try:
365+
cache_data = _load_agent_version_cache(ctx, pipeline_id=pipeline_id, project_name=project_name)
366+
if cache_data:
360367
version, *_ = cache_data[major_version]
361-
except (OSError, json.JSONDecodeError, IndexError) as e:
362-
# If a cache file is found but corrupted we ignore it.
363-
print(f"Error while recovering the version from {AGENT_VERSION_CACHE_NAME}: {e}")
364-
version = ""
368+
except (IndexError, KeyError, TypeError, ValueError) as e:
369+
# If a cache file is found but corrupted we ignore it.
370+
print(f"Error while recovering the version from {AGENT_VERSION_CACHE_NAME}: {e}", file=sys.stderr)
371+
version = ""
365372
if not version:
366373
version, *_ = query_version(ctx, major_version)
367374
return version

tasks/unit_tests/version_tests.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
import json
12
import os
23
import random
34
import unittest
4-
from unittest.mock import MagicMock, patch
5+
from unittest.mock import MagicMock, mock_open, patch
56

67
from invoke import MockContext, Result, UnexpectedExit
78

89
from tasks.libs.releasing.version import (
910
current_version_for_release_branch,
1011
get_matching_pattern,
12+
get_version_numeric_only,
1113
next_rc_version,
1214
query_version,
1315
)
@@ -500,3 +502,34 @@ def test_no_tag_match(self):
500502
ctx.run.return_value.stdout = "7.63.0-installer"
501503
version = next_rc_version(ctx, '7.63.x')
502504
self.assertEqual(version, Version(7, 64, 0, rc=1))
505+
506+
507+
_CACHE_CONTENTS = {
508+
"6": ["6.84.0", "devel", 10, "abc1234", "131065751"],
509+
"7": ["7.84.0", "devel", 203, "db4c825", "131065751"],
510+
"nightly": False,
511+
"dev": True,
512+
}
513+
514+
515+
class TestGetVersionNumericOnly(unittest.TestCase):
516+
@patch.dict(os.environ, {"CI": "true"}, clear=True)
517+
@patch("tasks.libs.releasing.version.os.path.exists", return_value=True)
518+
@patch("builtins.open", new_callable=mock_open, read_data=json.dumps(_CACHE_CONTENTS))
519+
def test_uses_local_cache_without_pipeline_id(self, _mock_file, _mock_exists):
520+
# Omnibus sanitizes CI_PIPELINE_ID out of the environment, but copies
521+
# agent-version.cache into the source tree. The numeric version used
522+
# for Windows resources must still come from that file.
523+
ctx = MagicMock()
524+
self.assertEqual(get_version_numeric_only(ctx), "7.84.0")
525+
ctx.run.assert_not_called()
526+
527+
@patch.dict(os.environ, {"CI": "true", "CI_PIPELINE_ID": "131065751", "CI_PROJECT_NAME": "datadog-agent"}, clear=True)
528+
@patch("tasks.libs.releasing.version.os.path.exists", return_value=False)
529+
def test_fetches_cache_from_s3_when_missing(self, _mock_exists):
530+
ctx = MagicMock()
531+
ctx.run.return_value = Result(stderr="")
532+
with patch("builtins.open", mock_open(read_data=json.dumps(_CACHE_CONTENTS))):
533+
self.assertEqual(get_version_numeric_only(ctx), "7.84.0")
534+
ctx.run.assert_called_once()
535+
self.assertIn("aws s3 cp", ctx.run.call_args.args[0])

0 commit comments

Comments
 (0)