From 3b9d80910bdce89fc6b808dd0ce7f533e9139a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 13:03:18 +0200 Subject: [PATCH 1/6] Add possibility to verify commit hash from metadata --- Common/Core/MetadataHelper.cxx | 29 +++++++ Common/Core/MetadataHelper.h | 15 ++++ Common/Core/macros/testMetadataHelper.C | 108 ++++++++++++++++++++++++ 3 files changed, 152 insertions(+) diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index b025c5df7a1..64b95fc0111 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -21,6 +21,8 @@ #include #include +#include + #include #include @@ -140,3 +142,30 @@ std::string MetadataHelper::makeMetadataLabel() const } return label; } + +std::string MetadataHelper::getO2Version() const +{ + if (!mIsInitialized) { + LOG(fatal) << "Metadata not initialized"; + } + return get("O2Version"); +} + +bool MetadataHelper::isCommitInSoftwareTag(const std::string& commitHash, const std::string & ccdbUrl) const +{ + const std::string softwareTag = getO2Version(); + std::string command = "curl -i -L "; + command += ccdbUrl; + command += "O2Version/CommitHash/"; + command += commitHash; + command += "/-1/"; + command += "O2Version=" + softwareTag; + command += " 2>&1 | grep --text O2Version:"; + // LOG(info) << "Command to check if commit " << commitHash << " is in software tag " << softwareTag << ": " << command; + TString res = gSystem->GetFromPipe(command.c_str()); + if (res.Contains(Form("O2Version: %s", softwareTag.c_str()))) { + LOG(debug) << "Commit " << commitHash << " is contained in software tag " << softwareTag; + return true; + } + return false; +} diff --git a/Common/Core/MetadataHelper.h b/Common/Core/MetadataHelper.h index 3854820bd84..7b871084f9a 100644 --- a/Common/Core/MetadataHelper.h +++ b/Common/Core/MetadataHelper.h @@ -51,11 +51,21 @@ struct MetadataHelper { /// @return true if the data has been initialized, false otherwise bool isInitialized() const; + /// @brief Function to get the O2 version from the metadata in the monalisa format + /// @return the O2 version from the metadata + std::string getO2Version() const; + /// @brief Function to get the metadata value for a given key /// @param key the key of the metadata /// @return the value of the metadata. Throws an exception if the key is not found std::string get(const std::string& key) const; + /// @brief Function to set a metadata key to a given value + /// @param key the key of the metadata + /// @param value the value to set + /// Note: this function does not check if the key is valid + void set(const std::string& key, const std::string& value) { mMetadata[key] = value; } + /// @brief Function to check if a key is defined in the metadata /// @param key the key to check /// @return true if the key is defined, false otherwise. Throws an exception if the key is not found @@ -64,6 +74,11 @@ struct MetadataHelper { /// @brief Function to create a label with the metadata information, useful e.g. for histogram naming std::string makeMetadataLabel() const; + /// Function to check if a commit is included in the software tag + /// @param commitHash the commit hash to check + /// @return true if the commit is included in the software tag, false otherwise + bool isCommitInSoftwareTag(const std::string& commitHash, const std::string& ccdbUrl = "http://ccdb-test.cern.ch:8080/") const; + private: std::map mMetadata; /// < The metadata map bool mIsInitialized = false; /// < Flag to check if the metadata has been initialized diff --git a/Common/Core/macros/testMetadataHelper.C b/Common/Core/macros/testMetadataHelper.C index 30c109f7840..d6ab7480e47 100644 --- a/Common/Core/macros/testMetadataHelper.C +++ b/Common/Core/macros/testMetadataHelper.C @@ -15,6 +15,7 @@ #include "Common/Core/MetadataHelper.h" +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -57,8 +59,97 @@ auto readMetadata(std::unique_ptr& currentFile) -> std::vectorHostName() ? gSystem->HostName() : ""; + if (host.find("lxplus") == std::string::npos) { + LOG(warn) << "Not on lxplus (" << host << "); skipping creation of /tmp/o2version.txt"; + return; + } + // If file exists, do nothing + std::ifstream infile("/tmp/o2version.txt"); + if (infile.is_open()) { + return; + } + gSystem->Exec("alienv q | grep VO_ALICE@O2:: > /tmp/o2version.txt"); +} + +std::map buildMapForCommitHash(const std::string& hash) +{ + // Change directory to /tmp + std::map results; + std::ifstream infileO2Versions("/tmp/o2version.txt"); + std::string lineOfO2Version; + const std::string fileContainingCommit = "/tmp/branches_" + hash + ".txt"; + std::ifstream infileO2VersionsWithHash(fileContainingCommit); + if (!infileO2VersionsWithHash.is_open()) { + gSystem->cd("/tmp/"); + gSystem->Exec("git clone git@github.com:AliceO2Group/AliceO2.git"); + gSystem->cd("AliceO2"); + std::string cmd = Form("git branch -r --contains %s > %s 2>&1", hash.c_str(), fileContainingCommit.c_str()); + LOG(info) << "Executing command " << cmd; + gSystem->Exec(cmd.c_str()); + } + std::string lineOfO2VersionsWithHash; + while (std::getline(infileO2Versions, lineOfO2Version)) { + std::string tag = lineOfO2Version.substr(lineOfO2Version.find("O2::") + 4); + // Strip a trailing "-1" (some alienv entries append this) + if (tag.size() >= 2 && tag.compare(tag.size() - 2, 2, "-1") == 0) { + tag.resize(tag.size() - 2); + } + LOG(debug) << "Checking tag '" << lineOfO2Version << "' tag (" << tag << ")"; + bool found = false; + infileO2VersionsWithHash.open(fileContainingCommit); + while (std::getline(infileO2VersionsWithHash, lineOfO2VersionsWithHash)) { + // LOG(info) << "Comparing " << lineOfO2Version << " with " << lineOfO2VersionsWithHash; + if (lineOfO2VersionsWithHash.find(tag) != std::string::npos) { + LOG(info) << "Tag " << tag << " contains hash " << hash; + found = true; + break; + } + } + infileO2VersionsWithHash.close(); + results[tag] = found; + } + return results; +} + +void populateCCDBWithCommitAvailability(std::map hasHashMap, + const std::string commitHash) +{ + // First, init the CCDB manager to test if the ccdb is already populated + o2::ccdb::CcdbApi api; + api.init("http://ccdb-test.cern.ch:8080/"); + if (!api.isHostReachable()) { + LOG(fatal) << "CCDB host http://ccdb-test.cern.ch:8080/ is not reacheable, cannot go forward"; + } + for (const auto& entry : hasHashMap) { + if (!entry.second) { // Version of the code does not have the hash + continue; + } + LOG(info) << "Populating CCDB with information that commit hash " << commitHash << " is contained in software tag " << entry.first; + std::map metadata; + metadata["O2Version"] = entry.first; + const std::string ccdbPath = "O2Version/CommitHash/" + commitHash; + auto headers = api.retrieveHeaders(ccdbPath, metadata, -1); + if (headers.size() != 0) { + LOG(info) << "Entry in CCDB already present for commit hash " << commitHash << ", skipping creation"; + continue; + } + LOG(info) << "No entry in CCDB for commit hash " << commitHash << ", creating it"; + std::string s = "available"; + api.storeAsTFileAny(&s, ccdbPath, metadata); + } +} + void testMetadataHelper(std::string aod = "/tmp/AO2D.root") { + createO2VersionFile(); + const std::string commitHash = "63bc2e3893851ef0f849bb4c98c65eae1ba21e47"; + const std::map hasHashMap = buildMapForCommitHash(commitHash); + populateCCDBWithCommitAvailability(hasHashMap, commitHash); TFile* file = TFile::Open(aod.c_str()); if (!file || file->IsZombie()) { @@ -79,6 +170,23 @@ void testMetadataHelper(std::string aod = "/tmp/AO2D.root") aodCfg.options().get("aod-metadata-DataType"); o2::common::core::MetadataHelper metadataInfo; metadataInfo.initMetadata(aodCfg); + metadataInfo.set("O2Version", "epn-20250715"); // Override the O2 version to a known one metadataInfo.print(); LOG(info) << "Metadata label: " << metadataInfo.makeMetadataLabel(); + + // Check if the hash is in the software tag + const std::string v = metadataInfo.getO2Version(); + if (hasHashMap.find(v) == hasHashMap.end()) { + LOG(fatal) << "Software tag " << v << " not found in available O2 versions"; + } + if (hasHashMap.at(v)) { + LOG(info) << "Hash " << commitHash << " is contained in software tag " << v; + } else { + LOG(warn) << "Hash " << commitHash << " is NOT contained in software tag " << v; + } + if (metadataInfo.isCommitInSoftwareTag(commitHash)) { + LOG(info) << "MetadataHelper confirms that hash " << commitHash << " is contained in software tag " << v; + } else { + LOG(warn) << "MetadataHelper confirms that hash " << commitHash << " is NOT contained in software tag " << v; + } } From 236929d71bb0a61bac19002e7520c56fa90986fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 13:07:00 +0200 Subject: [PATCH 2/6] Update testMetadataHelper.C --- Common/Core/macros/testMetadataHelper.C | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Common/Core/macros/testMetadataHelper.C b/Common/Core/macros/testMetadataHelper.C index d6ab7480e47..05b9bde1617 100644 --- a/Common/Core/macros/testMetadataHelper.C +++ b/Common/Core/macros/testMetadataHelper.C @@ -94,10 +94,13 @@ std::map buildMapForCommitHash(const std::string& hash) } std::string lineOfO2VersionsWithHash; while (std::getline(infileO2Versions, lineOfO2Version)) { - std::string tag = lineOfO2Version.substr(lineOfO2Version.find("O2::") + 4); + // Extract the tag + int stripSize = 4; + std::string tag = lineOfO2Version.substr(lineOfO2Version.find("O2::") + stripSize); // Strip a trailing "-1" (some alienv entries append this) - if (tag.size() >= 2 && tag.compare(tag.size() - 2, 2, "-1") == 0) { - tag.resize(tag.size() - 2); + stripSize = 2; + if (tag.size() >= stripSize && tag.compare(tag.size() - stripSize, stripSize, "-1") == 0) { + tag.resize(tag.size() - stripSize); } LOG(debug) << "Checking tag '" << lineOfO2Version << "' tag (" << tag << ")"; bool found = false; From 4c754650d260389ddc86aad20062e4954a1827c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 13:08:04 +0200 Subject: [PATCH 3/6] Refactor CCDB URL handling in populateCCDBWithCommitAvailability --- Common/Core/macros/testMetadataHelper.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Common/Core/macros/testMetadataHelper.C b/Common/Core/macros/testMetadataHelper.C index 05b9bde1617..3032eab2708 100644 --- a/Common/Core/macros/testMetadataHelper.C +++ b/Common/Core/macros/testMetadataHelper.C @@ -120,13 +120,13 @@ std::map buildMapForCommitHash(const std::string& hash) } void populateCCDBWithCommitAvailability(std::map hasHashMap, - const std::string commitHash) + const std::string commitHash const std::string ccdbUrl = "http://ccdb-test.cern.ch:8080/") { // First, init the CCDB manager to test if the ccdb is already populated o2::ccdb::CcdbApi api; - api.init("http://ccdb-test.cern.ch:8080/"); + api.init(ccdbUrl); if (!api.isHostReachable()) { - LOG(fatal) << "CCDB host http://ccdb-test.cern.ch:8080/ is not reacheable, cannot go forward"; + LOG(fatal) << "CCDB host " << ccdbUrl << " is not reacheable, cannot go forward"; } for (const auto& entry : hasHashMap) { if (!entry.second) { // Version of the code does not have the hash From a20ce61d65d7d9f39e64e413219ea66862af03f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 13:09:54 +0200 Subject: [PATCH 4/6] Fix parameter type in isCommitInSoftwareTag method --- Common/Core/MetadataHelper.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index 64b95fc0111..817efc4edad 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -151,7 +151,7 @@ std::string MetadataHelper::getO2Version() const return get("O2Version"); } -bool MetadataHelper::isCommitInSoftwareTag(const std::string& commitHash, const std::string & ccdbUrl) const +bool MetadataHelper::isCommitInSoftwareTag(const std::string& commitHash, const std::string& ccdbUrl) const { const std::string softwareTag = getO2Version(); std::string command = "curl -i -L "; From 0840bb750586e4862f33eb93461ca3b19267477b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 14:43:10 +0200 Subject: [PATCH 5/6] Update testMetadataHelper.C --- Common/Core/macros/testMetadataHelper.C | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/Core/macros/testMetadataHelper.C b/Common/Core/macros/testMetadataHelper.C index 3032eab2708..27371aaf0e3 100644 --- a/Common/Core/macros/testMetadataHelper.C +++ b/Common/Core/macros/testMetadataHelper.C @@ -27,6 +27,7 @@ #include #include +#include #include #include #include From a7f46cc1bec6ffb1b565fe7646729d0103775456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sat, 11 Oct 2025 14:43:28 +0200 Subject: [PATCH 6/6] Change log level from fatal to warning for initialization --- Common/Core/MetadataHelper.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index 817efc4edad..70af2dbec2b 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -146,7 +146,8 @@ std::string MetadataHelper::makeMetadataLabel() const std::string MetadataHelper::getO2Version() const { if (!mIsInitialized) { - LOG(fatal) << "Metadata not initialized"; + LOG(warning) << "Metadata not initialized"; + return "undefined"; } return get("O2Version"); }