Skip to content

Commit 6e7a1aa

Browse files
committed
* Reuse CI detection from the telemetry part in vcpkgcmdarguments.
* Set SECTION_NAME for GitLabCI to the alphaumericdots of the filename. * Deduplicate some CI detection tests. * Fix a *foo.get() pattern in create_user_troubleshooting_message.
1 parent a8c0356 commit 6e7a1aa

File tree

10 files changed

+146
-105
lines changed

10 files changed

+146
-105
lines changed

include/vcpkg/base/contractual-constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ namespace vcpkg
347347
inline constexpr StringLiteral FileInclude = "include";
348348
inline constexpr StringLiteral FileIncomplete = "incomplete";
349349
inline constexpr StringLiteral FileInfo = "info";
350+
inline constexpr StringLiteral FileIssueBodyMD = "issue_body.md";
350351
inline constexpr StringLiteral FileLicense = "LICENSE";
351352
inline constexpr StringLiteral FileLicenseDotTxt = "LICENSE.txt";
352353
inline constexpr StringLiteral FilePortfileDotCMake = "portfile.cmake";

include/vcpkg/base/message-data.inc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,11 @@ DECLARE_MESSAGE(ConstraintViolation, (), "", "Found a constraint violation:")
945945
DECLARE_MESSAGE(ContinueCodeUnitInStart, (), "", "found continue code unit in start position")
946946
DECLARE_MESSAGE(ControlCharacterInString, (), "", "Control character in string")
947947
DECLARE_MESSAGE(ControlSupportsMustBeAPlatformExpression, (), "", "\"Supports\" must be a platform expression")
948+
DECLARE_MESSAGE(CopyIssueBodyFromFile, (msg::path), "", "Copy issue body from {path}")
949+
DECLARE_MESSAGE(CopyIssueBodyFromCollapsibleSection,
950+
(msg::path),
951+
"",
952+
"Copy issue body from collapsed section \"{path}\" in the ci log output")
948953
DECLARE_MESSAGE(CopyrightIsDir,
949954
(),
950955
"",

include/vcpkg/commands.build.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,18 @@ namespace vcpkg
9494
StringLiteral to_string_locale_invariant(const BuildResult build_result);
9595
LocalizedString to_string(const BuildResult build_result);
9696
LocalizedString create_user_troubleshooting_message(const InstallPlanAction& action,
97+
CIKind detected_ci,
9798
const VcpkgPaths& paths,
9899
const std::vector<std::string>& error_logs,
99-
const Optional<Path>& issue_body);
100+
const Optional<Path>& maybe_issue_body);
100101
inline void print_user_troubleshooting_message(const InstallPlanAction& action,
102+
CIKind detected_ci,
101103
const VcpkgPaths& paths,
102104
const std::vector<std::string>& error_logs,
103-
Optional<Path>&& issue_body)
105+
Optional<Path>&& maybe_issue_body)
104106
{
105-
msg::println(Color::error, create_user_troubleshooting_message(action, paths, error_logs, issue_body));
107+
msg::println(Color::error,
108+
create_user_troubleshooting_message(action, detected_ci, paths, error_logs, maybe_issue_body));
106109
}
107110

108111
/// <summary>

include/vcpkg/fwd/vcpkgcmdarguments.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,20 @@ namespace vcpkg
2020
struct VcpkgCmdArguments;
2121
struct FeatureFlagSettings;
2222
struct PortApplicableSetting;
23+
24+
enum class CIKind
25+
{
26+
None,
27+
GithubActions,
28+
GitLabCI,
29+
AzurePipelines,
30+
AppVeyor,
31+
AwsCodeBuild,
32+
CircleCI,
33+
HerokuCI,
34+
JenkinsCI,
35+
TeamCityCI,
36+
TravisCI,
37+
Generic
38+
};
2339
}

include/vcpkg/vcpkgcmdarguments.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ namespace vcpkg
298298
f.dependency_graph = dependency_graph_enabled();
299299
return f;
300300
}
301-
const Optional<StringLiteral>& detected_ci_environment() const { return m_detected_ci_environment; }
301+
const Optional<StringLiteral>& detected_ci_environment_name() const { return m_detected_ci_environment_name; }
302+
CIKind detected_ci() const { return m_detected_ci_environment_type; }
302303

303304
const std::string& get_command() const noexcept { return command; }
304305

@@ -333,7 +334,8 @@ namespace vcpkg
333334

334335
std::string command;
335336

336-
Optional<StringLiteral> m_detected_ci_environment;
337+
Optional<StringLiteral> m_detected_ci_environment_name;
338+
CIKind m_detected_ci_environment_type;
337339

338340
friend LocalizedString usage_for_command(const CommandMetadata& command_metadata);
339341
CmdParser parser;

locales/messages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@
546546
"ContinueCodeUnitInStart": "found continue code unit in start position",
547547
"ControlCharacterInString": "Control character in string",
548548
"ControlSupportsMustBeAPlatformExpression": "\"Supports\" must be a platform expression",
549+
"CopyIssueBodyFromCollapsibleSection": "Copy issue body from collapsed section \"{path}\" in the ci log output",
550+
"_CopyIssueBodyFromCollapsibleSection.comment": "An example of {path} is /foo/bar.",
551+
"CopyIssueBodyFromFile": "Copy issue body from {path}",
552+
"_CopyIssueBodyFromFile.comment": "An example of {path} is /foo/bar.",
549553
"CopyrightIsDir": "this port sets ${{CURRENT_PACKAGES_DIR}}/share/${{PORT}}/copyright to a directory, but it should be a file. Consider combining separate copyright files into one using vcpkg_install_copyright. To suppress this message, add set(VCPKG_POLICY_SKIP_COPYRIGHT_CHECK enabled)",
550554
"CorruptedDatabase": "vcpkg's installation database corrupted. This is either a bug in vcpkg or something else has modified the contents of the 'installed' directory in an unexpected way. You may be able to fix this by deleting the 'installed' directory and reinstalling what you want to use. If this problem happens consistently, please file a bug at https://github.com/microsoft/vcpkg .",
551555
"CorruptedInstallTree": "Your vcpkg 'installed' tree is corrupted.",

src/vcpkg/commands.build.cpp

Lines changed: 76 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ namespace vcpkg
207207
msg::print(Color::warning, warnings);
208208
}
209209
msg::println_error(create_error_message(result, spec));
210-
msg::print(create_user_troubleshooting_message(*action, paths, {}, nullopt));
210+
msg::print(create_user_troubleshooting_message(*action, args.detected_ci(), paths, {}, nullopt));
211211
return 1;
212212
}
213213
case BuildResult::Excluded:
@@ -1702,115 +1702,113 @@ namespace vcpkg
17021702
Strings::percent_encode(body));
17031703
}
17041704

1705-
enum class CIType
1705+
static bool is_collapsible_ci_kind(CIKind kind)
17061706
{
1707-
GithubActions,
1708-
GitLabCi,
1709-
Azure,
1710-
};
1711-
1712-
static Optional<CIType> detect_ci_type()
1713-
{
1714-
if (get_environment_variable(EnvironmentVariableGitHubActions).has_value())
1715-
{
1716-
return CIType::GithubActions;
1717-
}
1718-
if (get_environment_variable(EnvironmentVariableGitLabCI).has_value())
1719-
{
1720-
return CIType::GitLabCi;
1721-
}
1722-
if (get_environment_variable(EnvironmentVariableTfBuild).has_value())
1707+
switch (kind)
17231708
{
1724-
return CIType::Azure;
1709+
case CIKind::GithubActions:
1710+
case CIKind::GitLabCI:
1711+
case CIKind::AzurePipelines: return true;
1712+
default: return false;
17251713
}
1726-
return {};
17271714
}
17281715

17291716
static void append_file_collapsible(LocalizedString& output,
1730-
CIType type,
1717+
CIKind kind,
17311718
const ReadOnlyFilesystem& fs,
17321719
const Path& file)
17331720
{
1734-
auto title = file.filename();
1735-
// starting tag
1736-
if (type == CIType::GithubActions)
1721+
if (!is_collapsible_ci_kind(kind))
17371722
{
1738-
// https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#grouping-log-lines
1739-
output.append_raw("::group::").append_raw(title).append_raw('\n');
1723+
Checks::unreachable(VCPKG_LINE_INFO);
17401724
}
1741-
else if (type == CIType::GitLabCi)
1742-
{
1743-
// https://docs.gitlab.com/ee/ci/jobs/job_logs.html#custom-collapsible-sections
1744-
using namespace std::chrono;
1745-
const auto timestamp = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
1746-
output.append_raw(fmt::format("\\e[0Ksection_start:{}:SECTION_NAME[collapsed=true]\r\\e[0K", timestamp))
1747-
.append_raw(title)
1748-
.append_raw('\n');
1749-
}
1750-
else if (type == CIType::Azure)
1751-
{
1752-
output.append_raw("##vso[task.uploadfile]").append_raw(fs.absolute(file, VCPKG_LINE_INFO)).append_raw('\n');
1753-
// https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#formatting-commands
1754-
output.append_raw("##[group]").append_raw(title).append_raw('\n');
1755-
}
1756-
1757-
// output real file
1758-
output.append_raw(fs.read_contents(file, VCPKG_LINE_INFO));
17591725

1760-
// end tag
1761-
if (type == CIType::GithubActions)
1762-
{
1763-
output.append_raw("::endgroup::\n");
1764-
}
1765-
else if (type == CIType::GitLabCi)
1766-
{
1767-
using namespace std::chrono;
1768-
const auto timestamp = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
1769-
output.append_raw(fmt::format("\\e[0Ksection_end:{}:SECTION_NAME\r\\e[0K\n", timestamp));
1770-
}
1771-
else if (type == CIType::Azure)
1772-
{
1773-
output.append_raw("##[endgroup]\n");
1726+
auto title = file.filename();
1727+
auto contents = fs.read_contents(file, VCPKG_LINE_INFO);
1728+
switch (kind)
1729+
{
1730+
case CIKind::GithubActions:
1731+
// https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#grouping-log-lines
1732+
output.append_raw("::group::")
1733+
.append_raw(title)
1734+
.append_raw('\n')
1735+
.append_raw(contents)
1736+
.append_raw("::endgroup::\n");
1737+
break;
1738+
case CIKind::GitLabCI:
1739+
{
1740+
// https://docs.gitlab.com/ee/ci/jobs/job_logs.html#custom-collapsible-sections
1741+
using namespace std::chrono;
1742+
std::string section_name;
1743+
std::copy_if(title.begin(), title.end(), std::back_inserter(section_name), [](char c) {
1744+
return c == '.' || ParserBase::is_alphanum(c);
1745+
});
1746+
const auto timestamp = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
1747+
output
1748+
.append_raw(
1749+
fmt::format("\\e[0Ksection_start:{}:{}[collapsed=true]\r\\e[0K", timestamp, section_name))
1750+
.append_raw(title)
1751+
.append_raw('\n')
1752+
.append_raw(contents)
1753+
.append_raw(fmt::format("\\e[0Ksection_end:{}:{}\r\\e[0K\n", timestamp, section_name));
1754+
}
1755+
break;
1756+
case CIKind::AzurePipelines:
1757+
// https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#formatting-commands
1758+
output.append_raw("##vso[task.uploadfile]")
1759+
.append_raw(file)
1760+
.append_raw('\n')
1761+
.append_raw("##[group]")
1762+
.append_raw(title)
1763+
.append_raw('\n')
1764+
.append_raw(contents)
1765+
.append_raw("##[endgroup]\n");
1766+
break;
17741767
}
17751768
}
17761769

17771770
LocalizedString create_user_troubleshooting_message(const InstallPlanAction& action,
1771+
CIKind detected_ci,
17781772
const VcpkgPaths& paths,
17791773
const std::vector<std::string>& error_logs,
1780-
const Optional<Path>& issue_body)
1774+
const Optional<Path>& maybe_issue_body)
17811775
{
17821776
const auto& spec_name = action.spec.name();
17831777
const auto& triplet_name = action.spec.triplet().to_string();
17841778
LocalizedString result = msg::format(msgBuildTroubleshootingMessage1).append_raw('\n');
17851779
result.append_indent().append_raw(make_gh_issue_search_url(spec_name)).append_raw('\n');
17861780
result.append(msgBuildTroubleshootingMessage2).append_raw('\n');
17871781

1788-
if (issue_body.has_value())
1782+
if (auto issue_body = maybe_issue_body.get())
17891783
{
1790-
auto ci = detect_ci_type();
1791-
const auto path = issue_body.get()->generic_u8string();
1784+
auto& fs = paths.get_filesystem();
1785+
const auto path = issue_body->generic_u8string();
1786+
const bool collapsible = is_collapsible_ci_kind(detected_ci);
17921787
const auto body =
1793-
ci.map([&](auto) {
1794-
return fmt::format("Copy issue body from collapsed section \"{}\" in the ci log output",
1795-
issue_body.get()->filename());
1796-
}).value_or(Strings::concat("Copy issue body from ", path));
1788+
collapsible ? msg::format(msgCopyIssueBodyFromCollapsibleSection, msg::path = issue_body->filename())
1789+
: msg::format(msgCopyIssueBodyFromFile, msg::path = path);
1790+
17971791
result.append_indent().append_raw(make_gh_issue_open_url(spec_name, triplet_name, body)).append_raw('\n');
1798-
if (!ci && !paths.get_filesystem().find_from_PATH("gh").empty())
1792+
if (collapsible)
17991793
{
1800-
Command gh("gh");
1801-
gh.string_arg("issue").string_arg("create").string_arg("-R").string_arg("microsoft/vcpkg");
1802-
gh.string_arg("--title").string_arg(fmt::format("[{}] Build failure on {}", spec_name, triplet_name));
1803-
gh.string_arg("--body-file").string_arg(path);
1804-
1805-
result.append(msgBuildTroubleshootingMessageGH).append_raw('\n');
1806-
result.append_indent().append_raw(gh.command_line());
1794+
append_file_collapsible(result, detected_ci, fs, *issue_body);
1795+
for (Path error_log_path : error_logs)
1796+
{
1797+
append_file_collapsible(result, detected_ci, fs, error_log_path);
1798+
}
18071799
}
1808-
if (ci)
1800+
else
18091801
{
1810-
append_file_collapsible(result, *ci.get(), paths.get_filesystem(), *issue_body.get());
1811-
for (Path error_log_path : error_logs)
1802+
auto gh_path = fs.find_from_PATH("gh");
1803+
if (!gh_path.empty())
18121804
{
1813-
append_file_collapsible(result, *ci.get(), paths.get_filesystem(), error_log_path);
1805+
Command gh(gh_path[0]);
1806+
gh.string_arg("issue").string_arg("create").string_arg("-R").string_arg("microsoft/vcpkg");
1807+
gh.string_arg("--title").string_arg(
1808+
fmt::format("[{}] Build failure on {}", spec_name, triplet_name));
1809+
gh.string_arg("--body-file").string_arg(path);
1810+
result.append(msgBuildTroubleshootingMessageGH).append_raw('\n');
1811+
result.append_indent().append_raw(gh.command_line());
18141812
}
18151813
}
18161814
}

src/vcpkg/commands.install.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,12 @@ namespace vcpkg
604604
{
605605
this_install.print_elapsed_time();
606606
print_user_troubleshooting_message(
607-
action, paths, result.error_logs, result.stdoutlog.then([&](auto&) -> Optional<Path> {
608-
auto issue_body_path = paths.installed().root() / "vcpkg" / "issue_body.md";
607+
action,
608+
args.detected_ci(),
609+
paths,
610+
result.error_logs,
611+
result.stdoutlog.then([&](auto&) -> Optional<Path> {
612+
auto issue_body_path = paths.installed().root() / FileVcpkg / FileIssueBodyMD;
609613
paths.get_filesystem().write_contents(
610614
issue_body_path,
611615
create_github_issue(args, result, paths, action, include_manifest_in_github_issue),

src/vcpkg/commands.z-print-config.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ namespace vcpkg
4848
obj.insert(JsonIdHostTriplet, host_triplet.canonical_name());
4949
obj.insert(JsonIdVcpkgRoot, paths.root.native());
5050
obj.insert(JsonIdTools, paths.tools.native());
51-
if (auto ci_env = args.detected_ci_environment().get())
51+
if (auto ci_env = args.detected_ci_environment_name().get())
5252
{
5353
obj.insert(JsonIdDetectedCIEnvironment, *ci_env);
5454
}

0 commit comments

Comments
 (0)