aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bdep/buildfile2
-rw-r--r--bdep/ci.cli18
-rw-r--r--bdep/ci.cxx81
-rwxr-xr-xdoc/cli.sh1
-rw-r--r--tests/ci.testscript74
5 files changed, 170 insertions, 6 deletions
diff --git a/bdep/buildfile b/bdep/buildfile
index cb701e8..2bbf1c3 100644
--- a/bdep/buildfile
+++ b/bdep/buildfile
@@ -150,7 +150,7 @@ if $cli.configured
--keep-separator --generate-specifier --generate-modifier \
--generate-description --generate-parse --generate-merge \
--page-usage 'bdep::print_$name$_' --ansi-color --include-base-last \
---suppress-undocumented --option-length 23
+--suppress-undocumented --option-length 24
cli.cxx{common-options}: cli.options += --short-usage --long-usage # Both.
cli.cxx{bdep-options}: cli.options += --short-usage
diff --git a/bdep/ci.cli b/bdep/ci.cli
index 8befd82..a45828c 100644
--- a/bdep/ci.cli
+++ b/bdep/ci.cli
@@ -79,6 +79,12 @@ namespace bdep
hierarchically so that the \cb{build-{include,exclude\}} overrides don't
affect the \cb{builds} values.
+ If supported by the CI service, a package can be tested interactively
+ in a specific build configuration using the \c{\b{--interactive}|\b{-i}}
+ option. In this mode the CI service provides the login information for
+ the execution environment and pauses the testing at the specified
+ breakpoint.
+
While the exact interpretation of the CI request depends on the specific
service, normally, the CI server will respond with a reference that can
be used to query the results. See \l{brep#ci Package CI} for details on
@@ -95,6 +101,18 @@ namespace bdep
"Don't prompt for confirmation before submitting."
}
+ string --interactive|-i
+ {
+ "<cf>[/<bp>]",
+ "Test the package interactively in the specified build configuration,
+ pausing the execution at the specified breakpoint. Valid breakpoint
+ values are \cb{error} (stop after first error), \cb{warning} (stop
+ after first warning), as well as the CI service-specific step ids
+ in which case the execution stops before performing the specified
+ step (see \l{bbot#arch-worker \cb{bbot} worker step ids}). If no
+ breakpoint is specified, then \cb{error} is assumed."
+ }
+
url --server
{
"<url>",
diff --git a/bdep/ci.cxx b/bdep/ci.cxx
index 797725f..18ebf7f 100644
--- a/bdep/ci.cxx
+++ b/bdep/ci.cxx
@@ -5,6 +5,7 @@
#include <sstream>
+#include <libbutl/path-pattern.mxx>
#include <libbutl/manifest-types.mxx>
#include <libbpkg/manifest.hxx>
@@ -176,17 +177,36 @@ namespace bdep
{
tracer trace ("ci");
- // Create the default override.
+ vector<manifest_name_value> overrides;
+
+ auto override = [&overrides] (string n, string v)
+ {
+ overrides.push_back (
+ manifest_name_value {move (n), move (v), // Name and value.
+ 0, 0, 0, 0, 0, 0, 0}); // Locations, etc.
+ };
+
+ // Add the default overrides.
//
- vector<manifest_name_value> overrides ({
- manifest_name_value {"build-email", "", // Name and value.
- 0, 0, 0, 0, 0, 0, 0}}); // Locations, etc.
+ override ("build-email", "");
// Validate and append the specified overrides.
//
if (o.overrides_specified ())
try
{
+ if (o.interactive_specified ())
+ {
+ for (const manifest_name_value& nv: o.overrides ())
+ {
+ if (nv.name == "builds" ||
+ nv.name == "build-include" ||
+ nv.name == "build-exclude")
+ fail << "'" << nv.name << "' override specified together with "
+ << "--interactive|-i";
+ }
+ }
+
bpkg::package_manifest::validate_overrides (o.overrides (),
"" /* name */);
@@ -276,6 +296,49 @@ namespace bdep
add_package (p.name);
}
+ // Extract the interactive mode configuration and breakpoint from the
+ // --interactive|-i option value, reducing the former to the build
+ // manifest value overrides.
+ //
+ // Both are present in the interactive mode and are absent otherwise.
+ //
+ optional<string> icfg;
+ optional<string> ibpk;
+
+ if (o.interactive_specified ())
+ {
+ if (pkgs.size () > 1)
+ fail << "multiple packages specified with --interactive|-i";
+
+ const string& s (o.interactive ());
+ validate_utf8_graphic (s, "--interactive|-i option value");
+
+ size_t p (s.find ('/'));
+
+ if (p != string::npos)
+ {
+ icfg = string (s, 0, p);
+ ibpk = string (s, p + 1);
+ }
+ else
+ icfg = s;
+
+ if (icfg->empty ())
+ fail << "invalid --interactive|-i option value '" << s
+ << "': configuration name is empty";
+
+ if (path_pattern (*icfg))
+ fail << "invalid --interactive|-i option value '" << s
+ << "': configuration name is a pattern";
+
+ override ("builds", "all");
+ override ("build-include", *icfg);
+ override ("build-exclude", "**");
+
+ if (!ibpk)
+ ibpk = "error";
+ }
+
// Get the server and repository URLs.
//
const url& srv (o.server_specified () ? o.server () : default_server);
@@ -310,6 +373,13 @@ namespace bdep
<< " version: " << p.version;
}
+ if (icfg)
+ {
+ assert (ibpk);
+ text << " config: " << *icfg << '\n'
+ << " b/point: " << *ibpk;
+ }
+
if (!yn_prompt ("continue? [y/n]"))
return 1;
}
@@ -334,6 +404,9 @@ namespace bdep
"package",
p.name.string () + '/' + p.version.string ()});
+ if (ibpk)
+ params.push_back ({parameter::text, "interactive", move (*ibpk)});
+
try
{
ostringstream os;
diff --git a/doc/cli.sh b/doc/cli.sh
index b407c73..dc44239 100755
--- a/doc/cli.sh
+++ b/doc/cli.sh
@@ -52,6 +52,7 @@ function compile ()
--link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$1%' \
--link-regex '%bpkg(#.+)?%../../bpkg/doc/build2-package-manager-manual.xhtml$1%' \
--link-regex '%brep(#.+)?%../../brep/doc/build2-repository-interface-manual.xhtml$1%' \
+--link-regex '%bbot(#.+)?%../../bbot/doc/build2-build-bot-manual.xhtml$1%' \
--link-regex '%bdep(#.+)?%build2-project-manager-manual.xhtml$1%' \
--link-regex '%intro(#.+)?%../../build2-toolchain/doc/build2-toolchain-intro.xhtml$1%' \
../bdep/$n.cli
diff --git a/tests/ci.testscript b/tests/ci.testscript
index 9aae4ea..d72d872 100644
--- a/tests/ci.testscript
+++ b/tests/ci.testscript
@@ -156,7 +156,7 @@ windows = ($cxx.target.class == 'windows')
--override 'build-error-email: error@example.com' \
--override 'builds: &gcc' \
--override 'build-include: linux*' \
- --override 'build-exclude: *' 2>>~"%EOE%"
+ --override 'build-exclude: *' 2>>~%EOE%
%CI request is queued.*%
%reference: .+%
EOE
@@ -233,6 +233,67 @@ windows = ($cxx.target.class == 'windows')
}
}
}
+
+ : interactive
+ :
+ {
+ +$clone_root_prj
+ +$init -C @cfg &prj-cfg/***
+
+ test.options += --no-progress
+
+ : valid
+ :
+ {
+ $clone_prj;
+
+ $* --interactive 'linux_debian_8-gcc_4.9/warning' 2>>~%EOE%
+ %CI request is queued.*%
+ %reference: .+%
+ EOE
+ }
+
+ : def-breakpoint
+ :
+ {
+ $clone_prj;
+
+ $* --interactive 'linux_debian_8-gcc_4.9' 2>>~%EOE%
+ %CI request is queued.*%
+ %reference: .+%
+ EOE
+ }
+
+ : config-empty
+ :
+ {
+ $clone_prj;
+
+ $* --interactive '/warning' 2>>EOE != 0
+ error: invalid --interactive|-i option value '/warning': configuration name is empty
+ EOE
+ }
+
+ : config-pattern
+ :
+ {
+ $clone_prj;
+
+ $* --interactive 'linux_debian_8-gcc_4.*' 2>>EOE != 0
+ error: invalid --interactive|-i option value 'linux_debian_8-gcc_4.*': configuration name is a pattern
+ EOE
+ }
+
+ : overrides
+ :
+ {
+ $clone_prj;
+
+ $* --interactive 'linux_debian_8-gcc_4.9' --builds '&gcc' 2>>EOE != 0
+ error: 'builds' override specified together with --interactive|-i
+ EOE
+ }
+ }
}
: multi-pkg
@@ -288,6 +349,17 @@ windows = ($cxx.target.class == 'windows')
EOE
}
+ : interactive
+ :
+ {
+ $clone_prj;
+ $init -C @cfg &prj-cfg/***;
+
+ $* --interactive 'linux_debian_8-gcc_4.9' 2>>EOE != 0
+ error: multiple packages specified with --interactive|-i
+ EOE
+ }
+
: prompt
:
{