summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tutorial/just-serve.md55
-rw-r--r--share/man/just-serve-config.5.md88
-rw-r--r--src/buildtool/main/TARGETS1
-rw-r--r--src/buildtool/main/serve.cpp209
-rw-r--r--test/end-to-end/just-mr/absent-roots.sh9
-rw-r--r--test/end-to-end/serve-service/serve_start_execute.sh7
-rw-r--r--test/end-to-end/serve-service/serve_start_execute_sharding.sh7
-rwxr-xr-xtest/end-to-end/with_serve_test_runner.py113
-rwxr-xr-xtest/utils/serve_service/test_runner.py41
9 files changed, 287 insertions, 243 deletions
diff --git a/doc/tutorial/just-serve.md b/doc/tutorial/just-serve.md
index 78afd49a..66ae9a7e 100644
--- a/doc/tutorial/just-serve.md
+++ b/doc/tutorial/just-serve.md
@@ -188,13 +188,17 @@ certification, such as
...
, "remote-service":
...
- , "server cert": "/etc/just-serve/certs/server.crt"
- , "server key": "/etc/just-serve/certs/server.key"
+ , "server cert":
+ {"root": "system", "path": "etc/just-serve/certs/server.crt"}
+ , "server key":
+ {"root": "system", "path": "etc/just-serve/certs/server.key"}
...
, "authentication":
- { "ca cert": "/etc/just-serve/certs/ca.crt"
- , "client cert": "/etc/just-serve/certs/client.crt"
- , "client key": "/etc/just-serve/certs/client.key"
+ { "ca cert": {"root": "system", "path": "etc/just-serve/certs/ca.crt"}
+ , "client cert":
+ {"root": "system", "path": "etc/just-serve/certs/client.crt"}
+ , "client key":
+ {"root": "system", "path": "etc/just-serve/certs/client.key"}
}
...
```
@@ -215,6 +219,11 @@ $ just-mr -R <serve_endpoint> [-r <execution_endpoint>] --tls-ca-cert <path_to_C
--tls-client-cert <path_to_client_cert> --tls-client-key <path_to_client_key> [...]
```
+Note that the serve configuration file requires location objects to be
+specified (which can be relative to the system root or to the current user's
+home directory), while the command line argument paths are expected to be
+either relative to the invocation directory or absolute.
+
### Known repositories
A simple way to maintain the dependencies of a project is to store its list of
@@ -228,9 +237,9 @@ extended, for example, with
``` {.jsonc srcname=".just-servec"}
...
, "repositories":
- [ "third-party-distfiles"
- , "repos/project-foo"
- , "repos/project-bar"
+ [ {"root": "system", "path": "var/repos/third-party-distfiles"}
+ , {"root": "system", "path": "var/repos/project-foo"}
+ , {"root": "system", "path": "var/repos/project-bar"}
]
...
```
@@ -244,7 +253,7 @@ configuration file can be extended, for example, with
``` {.jsonc srcname=".just-servec"}
...
-, "local build root": "/var/cache/serve-build-root"
+, "local build root": {"root": "system", "path": "var/cache/serve-build-root"}
...
```
@@ -264,7 +273,7 @@ extend the `"remote service"` field accordingly
...
, "remote-service":
...
- , "pid file": "/var/run/info.json"
+ , "pid file": {"root": "system", "path": "var/run/info.json"}
...
...
```
@@ -369,7 +378,7 @@ Let us start with a basic `.just-servec` configuration file, on which we can
then expand step-by-step
``` {.jsonc srcname=".just-servec"}
-{ "local build root": "serve-build-root"
+{ "local build root": {"root": "system", "path": "var/cache/serve-build-root"}
, "remote service": {"port": 9999}
}
```
@@ -420,10 +429,10 @@ to avoid clients having to fetch archives from the network.
The typical way a project keeps track of their third-party packages is under
some version control, e.g., a Git repository. Assuming the referenced fmtlib
archive is available in such a Git repository, we can create a local checkout
-at path `repos/distfiles`. Then the following command should pass
+at path `/var/repos/distfiles`. Then the following command should pass
``` sh
-$ git -C repos/distfiles cat-file -t fd4144c2835f89516cac0db1f3c7b73562555dca
+$ git -C /var/repos/distfiles cat-file -t fd4144c2835f89516cac0db1f3c7b73562555dca
blob
$
```
@@ -433,9 +442,9 @@ adding its path to the known repository list in the `.just-servec` configuration
file, which will become
``` {.jsonc srcname=".just-servec"}
-{ "local build root": "/var/cache/serve-build-root"
+{ "local build root": {"root": "system", "path": "var/cache/serve-build-root"}
, "remote service": {"port": 9999}
-, "repositories": ["repos/distfiles"]
+, "repositories": [{"root": "system", "path": "var/repos/distfiles"}]
}
```
@@ -459,7 +468,7 @@ dependency. We will start with the serve service setup.
As we want to be able to easily change the commit we are interested in whenever
we expect the latest version of this repository in our project, on the serve
server we will create a local Git checkout of `"rules-cc"` stored at
-`repos/rules-cc`. This means that a client can easily update its build
+`/var/repos/rules-cc`. This means that a client can easily update its build
description to point to whichever commit it needs, while the serve server will
have to ensure this checkout is always kept updated (usually automatized, for
example via a cron job). The configuration file of the serve service will need
@@ -467,9 +476,12 @@ thus to be updated to include this checkout location, so `.just-servec` now
reads
``` {.jsonc srcname=".just-servec"}
-{ "local build root": "/var/cache/serve-build-root"
+{ "local build root": {"root": "system", "path": "var/cache/serve-build-root"}
, "remote service": {"port": 9999}
-, "repositories": ["repos/distfiles", "repos/rules-cc"]
+, "repositories":
+ [ {"root": "system", "path": "var/repos/distfiles"}
+ , {"root": "system", "path": "var/repos/rules-cc"}
+ ]
}
```
@@ -535,9 +547,12 @@ We are now ready to see how this setup works. At this point the `repos.json` is
and the `.just-servec` configuration file is
``` {.jsonc srcname=".just-servec"}
-{ "local build root": "/var/cache/serve-build-root"
+{ "local build root": {"root": "system", "path": "var/cache/serve-build-root"}
, "remote service": {"port": 9999}
-, "repositories": ["repos/distfiles", "repos/rules-cc"]
+, "repositories":
+ [ {"root": "system", "path": "var/repos/distfiles"}
+ , {"root": "system", "path": "var/repos/rules-cc"}
+ ]
}
```
diff --git a/share/man/just-serve-config.5.md b/share/man/just-serve-config.5.md
index 6a961842..7274d661 100644
--- a/share/man/just-serve-config.5.md
+++ b/share/man/just-serve-config.5.md
@@ -14,24 +14,32 @@ JSON object is equivalent. We assume, that in JSON objects, each key
occurs at most once; it is implementation defined how repetitions of the
same key are treated.
+Location objects
+----------------
+
+The general syntax and semantics of a location object are described in
+**`just-mrrc`**(5). Here we use a restricted form where the value for key
+*`"root"`* can only be either *`"home"`* or *`"system"`*. This is because
+`just serve` is not aware of the concept of workspaces.
+
The just-serve configuration format
-----------------------------------
The configuration file is given by a JSON object.
- - The value for the key *`"local build root"`* is a string specifying the path
- to use as the root for local CAS, cache, and build directories. The path will
- be created if it does not exist already.
+ - The value for the key *`"local build root"`* is a single location object,
+ specifying the path to use as the root for local CAS, cache, and build
+ directories. The path will be created if it does not exist already.
- - The value for the key *`"repositories"`* is a list of strings specifying
- paths to Git repositories for **`just`** **`serve`** to use as additional
- object lookup locations. The paths are to be used in the order given and
- only if requested objects are not found in the local build root.
+ - The value for the key *`"repositories"`* is a list of location objects,
+ specifying paths to Git repositories for **`just`** **`serve`** to use as
+ additional object lookup locations. The paths are to be used in the order
+ given and only if requested objects are not found in the local build root.
- The value for the key *`"logging"`* is a JSON object specifying logging
options.
- For subkey *`"files"`* the value is a list of strings specifying one or more
- local log files to use.
+ For subkey *`"files"`* the value is a list of location objects, specifying
+ one or more local log files to use.
For subkey *`"limit"`* the value is an integer setting the default for
the log limit.
For subkey *`"restrict stderr limit"`* the value is an integer setting a
@@ -44,12 +52,12 @@ The configuration file is given by a JSON object.
- The value for the key *`"authentication"`* is a JSON object specifying
client-side authentication options for **`just`** **`serve`** when
communicating with the remote execution endpoint.
- For subkey *`"ca cert"`* the value is a string specifying the path to a TLS
- CA certificate.
- For subkey *`"client cert"`* the value is a string specifying the path to a
- TLS client certificate.
- For subkey *`"client key"`* the value is a string specifying the path to a
- TLS client key.
+ For subkey *`"ca cert"`* the value is a single location object, specifying
+ the path to a TLS CA certificate.
+ For subkey *`"client cert"`* the value is a single location object,
+ specifying the path to a TLS client certificate.
+ For subkey *`"client key"`* the value is a single location object,
+ specifying the path to a TLS client key.
- The value for the key *`"remote service"`* is a JSON object specifying the
server arguments for running **`just`** **`serve`** as a service.
@@ -57,15 +65,17 @@ The configuration file is given by a JSON object.
If unset, the loopback device is used.
For subkey *`"port"`* the value specifies the port to which the service is to
listen. If unset, the service will choose to the first available one.
- For subkey *`"pid file"`* the value specifies a file to which the pid should
- be stored in plain text. If the file exists, it will be overwritten.
- For subkey *`"info file"`* the value specifies a file to which the used port,
- interface, and pid should be stored in JSON format. If the file exists, it
- will be overwritten.
- For subkey *`"server cert"`* the value is a string specifying the path to a
- TLS server certificate.
- For subkey *`"server key"`* the value is a string specifying the path to a
- TLS server key.
+ For subkey *`"pid file"`* the value is a single location object, specifying
+ the path to a file to which the pid should be stored in plain text. If the
+ file exists, it will be overwritten.
+ For subkey *`"info file"`* the value specifies a single location object,
+ specifying the path to a file file to which the used port, interface, and
+ pid should be stored in JSON format. If the file exists, it will be
+ overwritten.
+ For subkey *`"server cert"`* the value is a single location object,
+ specifying the path to a TLS server certificate.
+ For subkey *`"server key"`* the value is a single location object,
+ specifying the path to a TLS server key.
- The value for the key *`"execution endpoint"`* is a JSON object specifying
the arguments of a remote execution endpoint to be used by **`just`**
@@ -120,25 +130,33 @@ EXAMPLE
An example serve configuration file could look as follows.
```jsonc
-{ "local build root": "/var/just-serve/root"
+{ "local build root": {"root": "system", "path": "var/just-serve/root"}
, "authentication":
- { "ca cert": "/etc/just-serve/certs/ca.crt"
- , "client cert": "/etc/just-serve/certs/client.crt"
- , "client key": "/etc/just-serve/certs/client.key"
+ { "ca cert":
+ {"root": "system", "path": "etc/just-serve/certs/ca.crt"}
+ , "client cert":
+ {"root": "system", "path": "etc/just-serve/certs/client.crt"}
+ , "client key":
+ {"root": "system", "path": "etc/just-serve/certs/client.key"}
}
, "remote service":
{ "interface": "192.0.2.1"
, "port": 9999
- , "pid file": "/var/run/just-serve/server.pid"
- , "server cert": "/etc/just-serve/certs/server.crt"
- , "server key": "/etc/just-serve/certs/server.key"
+ , "pid file":
+ {"root": "system", "path": "var/run/just-serve/server.pid"}
+ , "server cert":
+ {"root": "system", "path": "etc/just-serve/certs/server.crt"}
+ , "server key":
+ {"root": "system", "path": "etc/just-serve/certs/server.key"}
}
, "execution endpoint": {"address": "198.51.100.1:8989"}
, "repositories":
- [ "/var/just-serve/repos/third-party-distfiles"
- , "/var/just-serve/repos/project-foo"
- , "/var/just-serve/repos/project-bar"
+ [ {"root": "system", "path": "var/just-serve/repos/third-party-distfiles"}
+ , {"root": "system", "path": "var/just-serve/repos/project-foo"}
+ , {"root": "system", "path": "var/just-serve/repos/project-bar"}
]
+, "logging":
+ {"files": [{"root": "home", "path": ".log/just-serve/latest"}]}
, "jobs": 8
, "build": {"build jobs": 128}
, "max-attempts": 10
@@ -150,4 +168,4 @@ An example serve configuration file could look as follows.
See also
========
-**`just`**(1)
+**`just`**(1), **`just-mrrc`**(5)
diff --git a/src/buildtool/main/TARGETS b/src/buildtool/main/TARGETS
index f1d5aa99..91f711ac 100644
--- a/src/buildtool/main/TARGETS
+++ b/src/buildtool/main/TARGETS
@@ -262,6 +262,7 @@
, "private-deps":
[ ["@", "json", "", "json"]
, ["src/buildtool/build_engine/expression", "expression"]
+ , ["src/buildtool/common", "location"]
, ["src/buildtool/file_system", "file_system_manager"]
, ["src/buildtool/logging", "log_level"]
, ["src/buildtool/logging", "logging"]
diff --git a/src/buildtool/main/serve.cpp b/src/buildtool/main/serve.cpp
index 1c321c0b..0eaf174e 100644
--- a/src/buildtool/main/serve.cpp
+++ b/src/buildtool/main/serve.cpp
@@ -14,22 +14,48 @@
#include "src/buildtool/main/serve.hpp"
-#include <chrono>
-#include <cstddef>
-
#ifndef BOOTSTRAP_BUILD_TOOL
+#include <chrono>
+#include <cstddef>
+#include <cstdlib>
+#include <filesystem>
#include <fstream>
+#include <optional>
+#include <string>
+#include <utility>
+#include <variant>
+#include <vector>
#include "nlohmann/json.hpp"
#include "src/buildtool/build_engine/expression/configuration.hpp"
#include "src/buildtool/build_engine/expression/expression.hpp"
+#include "src/buildtool/common/location.hpp"
#include "src/buildtool/common/remote/retry_parameters.hpp"
#include "src/buildtool/file_system/file_system_manager.hpp"
#include "src/buildtool/logging/log_level.hpp"
#include "src/buildtool/logging/logger.hpp"
#include "src/buildtool/main/exit_codes.hpp"
+namespace {
+
+/// \brief Overlay for ReadLocationObject accepting an ExpressionPtr and no
+/// workspace root and that can std::exit
+[[nodiscard]] auto ReadLocation(ExpressionPtr const& location)
+ -> std::optional<std::pair<std::filesystem::path, std::filesystem::path>> {
+ if (location.IsNotNull()) {
+ auto res = ReadLocationObject(location->ToJson(), std::nullopt);
+ if (res.index() == 0) {
+ Logger::Log(LogLevel::Error, std::get<0>(res));
+ std::exit(kExitFailure);
+ }
+ return std::get<1>(res);
+ }
+ return std::nullopt;
+}
+
+} // namespace
+
[[nodiscard]] auto ParseRetryCliOptions(Configuration const& config) noexcept
-> bool {
auto max_attempts = config["max-attempts"];
@@ -119,43 +145,39 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
std::exit(kExitFailure);
}
// read local build root
- auto local_root = serve_config["local build root"];
- if (local_root.IsNotNull()) {
- if (not local_root->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for key "
- "\"local build root\" has to be a string, but found {}",
- clargs->serve.config.string(),
- local_root->ToString());
- std::exit(kExitFailure);
- }
- clargs->endpoint.local_root = local_root->String();
+ auto local_root = ReadLocation(serve_config["local build root"]);
+ if (local_root) {
+ clargs->endpoint.local_root = local_root->first;
}
// read paths of additional lookup repositories
auto repositories = serve_config["repositories"];
if (repositories.IsNotNull()) {
if (not repositories->IsList()) {
- Logger::Log(
- LogLevel::Error,
- "In serve service config file {}:\nValue for key "
- "\"repositories\" has to be a list of strings, but found {}",
- clargs->serve.config.string(),
- repositories->ToString());
+ Logger::Log(LogLevel::Error,
+ "In serve service config file {}:\nValue for key "
+ "\"repositories\" has to be a list, but found {}",
+ clargs->serve.config.string(),
+ repositories->ToString());
std::exit(kExitFailure);
}
auto const& repos_list = repositories->List();
clargs->serve.repositories.reserve(clargs->serve.repositories.size() +
repos_list.size());
for (auto const& repo : repos_list) {
- if (not repo->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nExpected each "
- "repository path to be a string, but found {}",
- clargs->serve.config.string(),
- repo->ToString());
- std::exit(kExitFailure);
+ auto repo_root = ReadLocation(repo);
+ if (repo_root) {
+ if (not FileSystemManager::IsDirectory(repo_root->first)) {
+ // warn the user that the path might not exist or is not
+ // a directory
+ Logger::Log(LogLevel::Warning,
+ "In serve service config file {}:\nProvided "
+ "known repository path {} does not exist or "
+ "is not a directory!",
+ clargs->serve.config.string(),
+ repo_root->first.string());
+ }
+ clargs->serve.repositories.emplace_back(repo_root->first);
}
- clargs->serve.repositories.emplace_back(repo->String());
}
}
// read logging arguments
@@ -212,17 +234,11 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
auto const& files_list = files->List();
clargs->log.log_files.reserve(clargs->log.log_files.size() +
files_list.size());
- for (auto const& file : files_list) {
- if (not file->IsString()) {
- Logger::Log(
- LogLevel::Error,
- "In serve service config file {}:\nExpected each log "
- "file path to be a string, but found {}",
- clargs->serve.config.string(),
- file->ToString());
- std::exit(kExitFailure);
+ for (auto const& log_file : files_list) {
+ auto path = ReadLocation(log_file);
+ if (path) {
+ clargs->log.log_files.emplace_back(path->first);
}
- clargs->log.log_files.emplace_back(file->String());
}
}
// read in limit field
@@ -269,46 +285,22 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
std::exit(kExitFailure);
}
// read the TLS CA certificate
- auto cacert = auth_args->Get("ca cert", Expression::none_t{});
- if (cacert.IsNotNull()) {
- if (not cacert->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "authentication key \"ca cert\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- cacert->ToString());
- std::exit(kExitFailure);
- }
- clargs->auth.tls_ca_cert = cacert->String();
+ auto cacert =
+ ReadLocation(auth_args->Get("ca cert", Expression::none_t{}));
+ if (cacert) {
+ clargs->auth.tls_ca_cert = cacert->first;
}
// read the TLS client certificate
- auto client_cert = auth_args->Get("client cert", Expression::none_t{});
- if (client_cert.IsNotNull()) {
- if (not client_cert->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "authentication key \"client cert\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- client_cert->ToString());
- std::exit(kExitFailure);
- }
- clargs->cauth.tls_client_cert = client_cert->String();
+ auto client_cert =
+ ReadLocation(auth_args->Get("client cert", Expression::none_t{}));
+ if (client_cert) {
+ clargs->cauth.tls_client_cert = client_cert->first;
}
// read the TLS client key
- auto client_key = auth_args->Get("client key", Expression::none_t{});
- if (client_key.IsNotNull()) {
- if (not client_key->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "authentication key \"client key\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- client_key->ToString());
- std::exit(kExitFailure);
- }
- clargs->cauth.tls_client_key = client_key->String();
+ auto client_key =
+ ReadLocation(auth_args->Get("client key", Expression::none_t{}));
+ if (client_key) {
+ clargs->cauth.tls_client_key = client_key->first;
}
}
// read remote service arguments
@@ -361,62 +353,28 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
clargs->service.port = std::nearbyint(val);
}
// read the pid file
- auto pid_file = remote_service->Get("pid file", Expression::none_t{});
- if (pid_file.IsNotNull()) {
- if (not pid_file->IsString()) {
- Logger::Log(
- LogLevel::Error,
- "In serve service config file {}:\nValue for remote "
- "service key \"pid file\" has to be a string, but found {}",
- clargs->serve.config.string(),
- pid_file->ToString());
- std::exit(kExitFailure);
- }
- clargs->service.pid_file = pid_file->String();
+ auto pid_file =
+ ReadLocation(remote_service->Get("pid file", Expression::none_t{}));
+ if (pid_file) {
+ clargs->service.pid_file = pid_file->first;
}
// read the info file
- auto info_file = remote_service->Get("info file", Expression::none_t{});
- if (info_file.IsNotNull()) {
- if (not info_file->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "remote service key \"info file\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- info_file->ToString());
- std::exit(kExitFailure);
- }
- clargs->service.info_file = info_file->String();
+ auto info_file = ReadLocation(
+ remote_service->Get("info file", Expression::none_t{}));
+ if (info_file) {
+ clargs->service.info_file = info_file->first;
}
// read the TLS server certificate
- auto server_cert =
- remote_service->Get("server cert", Expression::none_t{});
- if (server_cert.IsNotNull()) {
- if (not server_cert->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "remote service key \"server cert\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- server_cert->ToString());
- std::exit(kExitFailure);
- }
- clargs->sauth.tls_server_cert = server_cert->String();
+ auto server_cert = ReadLocation(
+ remote_service->Get("server cert", Expression::none_t{}));
+ if (server_cert) {
+ clargs->sauth.tls_server_cert = server_cert->first;
}
// read the TLS server key
- auto server_key =
- remote_service->Get("server key", Expression::none_t{});
- if (server_key.IsNotNull()) {
- if (not server_key->IsString()) {
- Logger::Log(LogLevel::Error,
- "In serve service config file {}:\nValue for "
- "remote service key \"server key\" has to be a "
- "string, but found {}",
- clargs->serve.config.string(),
- server_key->ToString());
- std::exit(kExitFailure);
- }
- clargs->sauth.tls_server_key = server_key->String();
+ auto server_key = ReadLocation(
+ remote_service->Get("server key", Expression::none_t{}));
+ if (server_key) {
+ clargs->sauth.tls_server_key = server_key->first;
}
}
// read execution endpoint arguments
@@ -522,6 +480,7 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
clargs->build.timeout =
std::size_t(timeout->Number()) * std::chrono::seconds{1};
}
+ // read target-cache writing strategy
auto strategy = build_args->Get("target-cache write strategy",
Expression::none_t{});
if (strategy.IsNotNull()) {
@@ -546,7 +505,7 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
}
clargs->tc.target_cache_write_strategy = *s_value;
}
-
+ // read local launcher
auto launcher = build_args->Get("local launcher", Expression::none_t{});
if (launcher.IsNotNull()) {
if (not launcher->IsList()) {
diff --git a/test/end-to-end/just-mr/absent-roots.sh b/test/end-to-end/just-mr/absent-roots.sh
index 853d2149..db3779f5 100644
--- a/test/end-to-end/just-mr/absent-roots.sh
+++ b/test/end-to-end/just-mr/absent-roots.sh
@@ -66,9 +66,12 @@ cat repos.json
# Make the repository available via 'just serve'
cat > .just-servec <<EOF
-{ "repositories": ["${REPO_ROOT}"]
-, "remote service": {"info file": "${INFOFILE}", "pid file": "${PIDFILE}"}
-, "local build root": "${SERVE_LBR}"
+{ "repositories": [{"root": "system", "path": "${REPO_ROOT}"}]
+, "remote service":
+ { "info file": {"root": "system", "path": "${INFOFILE}"}
+ , "pid file": {"root": "system", "path": "${PIDFILE}"}
+ }
+, "local build root": {"root": "system", "path": "${SERVE_LBR}"}
}
EOF
echo "Serve service configuration:"
diff --git a/test/end-to-end/serve-service/serve_start_execute.sh b/test/end-to-end/serve-service/serve_start_execute.sh
index 1c405d07..c9ebffba 100644
--- a/test/end-to-end/serve-service/serve_start_execute.sh
+++ b/test/end-to-end/serve-service/serve_start_execute.sh
@@ -34,8 +34,11 @@ readonly PIDFILE="${PWD}/pid.txt"
COMPAT=""
cat > .just-servec <<EOF
{ "repositories": []
-, "remote service": {"info file": "${INFOFILE}", "pid file": "${PIDFILE}"}
-, "local build root": "${LBR}"
+, "remote service":
+ { "info file": {"root": "system", "path": "${INFOFILE}"}
+ , "pid file": {"root": "system", "path": "${PIDFILE}"}
+ }
+, "local build root": {"root": "system", "path": "${LBR}"}
EOF
if [ "${COMPATIBLE:-}" = "YES" ]
then
diff --git a/test/end-to-end/serve-service/serve_start_execute_sharding.sh b/test/end-to-end/serve-service/serve_start_execute_sharding.sh
index d6486841..6997c612 100644
--- a/test/end-to-end/serve-service/serve_start_execute_sharding.sh
+++ b/test/end-to-end/serve-service/serve_start_execute_sharding.sh
@@ -115,8 +115,11 @@ ls -R "${SERVE_LBR}"
#
cat > .just-servec <<EOF
{ "repositories": []
-, "remote service": {"info file": "${INFOFILE}", "pid file": "${PIDFILE}"}
-, "local build root": "${SERVE_LBR}"
+, "remote service":
+ { "info file": {"root": "system", "path": "${INFOFILE}"}
+ , "pid file": {"root": "system", "path": "${PIDFILE}"}
+ }
+, "local build root": {"root": "system", "path": "${SERVE_LBR}"}
}
EOF
echo "Serve service configuration:"
diff --git a/test/end-to-end/with_serve_test_runner.py b/test/end-to-end/with_serve_test_runner.py
index 94703603..a71758fd 100755
--- a/test/end-to-end/with_serve_test_runner.py
+++ b/test/end-to-end/with_serve_test_runner.py
@@ -59,19 +59,19 @@ def get_remote_execution_address(d: Json) -> str:
dump_results()
-TEMP_DIR = os.path.realpath("scratch")
+TEMP_DIR = os.path.abspath(os.path.realpath("scratch"))
os.makedirs(TEMP_DIR, exist_ok=True)
-WORK_DIR = os.path.realpath("work")
+WORK_DIR = os.path.abspath(os.path.realpath("work"))
os.makedirs(WORK_DIR, exist_ok=True)
-REMOTE_DIR = os.path.realpath("remote")
+REMOTE_DIR = os.path.abspath(os.path.realpath("remote"))
os.makedirs(REMOTE_DIR, exist_ok=True)
REMOTE_LBR = os.path.join(REMOTE_DIR, "build-root")
g_REMOTE_EXECUTION_ADDRESS: str = ""
-SERVE_DIR = os.path.realpath("serve")
+SERVE_DIR = os.path.abspath(os.path.realpath("serve"))
os.makedirs(SERVE_DIR, exist_ok=True)
SERVE_LBR = os.path.join(SERVE_DIR, "build-root")
@@ -80,7 +80,7 @@ standalone_serve = json.loads(sys.argv[2])
remote_proc = None
-PATH=subprocess.run(
+PATH = subprocess.run(
["env", "--", "sh", "-c", "echo -n $PATH"],
stdout=subprocess.PIPE,
).stdout.decode('utf-8')
@@ -88,43 +88,43 @@ PATH=subprocess.run(
remotestdout = open("remotestdout", "w")
remotestderr = open("remotestderr", "w")
if not standalone_serve:
- # start just execute as remote service
- REMOTE_INFO = os.path.join(REMOTE_DIR, "remote-info.json")
-
- if os.path.exists(REMOTE_INFO):
- print(f"Warning: removing unexpected info file {REMOTE_INFO}")
- os.remove(REMOTE_INFO)
-
- remote_cmd = [
- "./bin/just",
- "execute",
- "-L",
- json.dumps(["env", "PATH=" + PATH]),
- "--info-file",
- REMOTE_INFO,
- "--local-build-root",
- REMOTE_LBR,
- "--log-limit",
- "6",
- "--plain-log",
- ]
-
- if compatible:
- remote_cmd.append("--compatible")
-
- remote_proc = subprocess.Popen(
- remote_cmd,
- stdout=remotestdout,
- stderr=remotestderr,
- )
-
- while not os.path.exists(REMOTE_INFO):
- time.sleep(1)
-
- with open(REMOTE_INFO) as f:
- info = json.load(f)
-
- g_REMOTE_EXECUTION_ADDRESS = get_remote_execution_address(info)
+ # start just execute as remote service
+ REMOTE_INFO = os.path.join(REMOTE_DIR, "remote-info.json")
+
+ if os.path.exists(REMOTE_INFO):
+ print(f"Warning: removing unexpected info file {REMOTE_INFO}")
+ os.remove(REMOTE_INFO)
+
+ remote_cmd = [
+ "./bin/just",
+ "execute",
+ "-L",
+ json.dumps(["env", "PATH=" + PATH]),
+ "--info-file",
+ REMOTE_INFO,
+ "--local-build-root",
+ REMOTE_LBR,
+ "--log-limit",
+ "6",
+ "--plain-log",
+ ]
+
+ if compatible:
+ remote_cmd.append("--compatible")
+
+ remote_proc = subprocess.Popen(
+ remote_cmd,
+ stdout=remotestdout,
+ stderr=remotestderr,
+ )
+
+ while not os.path.exists(REMOTE_INFO):
+ time.sleep(1)
+
+ with open(REMOTE_INFO) as f:
+ info = json.load(f)
+
+ g_REMOTE_EXECUTION_ADDRESS = get_remote_execution_address(info)
# start just serve service
SERVE_INFO = os.path.join(SERVE_DIR, "serve-info.json")
@@ -134,7 +134,10 @@ serve_config: Json = {}
if standalone_serve:
serve_config = {
- "local build root": SERVE_LBR,
+ "local build root": {
+ "root": "system",
+ "path": SERVE_LBR
+ },
"logging": {
"limit": 6,
"plain": True
@@ -143,7 +146,10 @@ if standalone_serve:
"compatible": compatible
},
"remote service": {
- "info file": SERVE_INFO
+ "info file": {
+ "root": "system",
+ "path": SERVE_INFO
+ }
},
"build": {
"local launcher": ["env", "PATH=" + PATH]
@@ -151,7 +157,10 @@ if standalone_serve:
}
else:
serve_config = {
- "local build root": SERVE_LBR,
+ "local build root": {
+ "root": "system",
+ "path": SERVE_LBR
+ },
"logging": {
"limit": 6,
"plain": True
@@ -161,11 +170,14 @@ else:
"compatible": compatible
},
"remote service": {
- "info file": SERVE_INFO
+ "info file": {
+ "root": "system",
+ "path": SERVE_INFO
+ }
},
}
-repositories: List[str] = []
+repositories: List[Dict[str, str]] = [] # list of location objects
repos_env: Dict[str, str] = {}
REPOS_DIR = os.path.realpath("repos")
@@ -214,7 +226,7 @@ for repo in repo_data:
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
- repositories.append(target)
+ repositories.append({"root": "system", "path": target})
repos_env["COMMIT_%d" % count] = subprocess.run(
["git", "log", "-n", "1", "--format=%H"],
stdout=subprocess.PIPE,
@@ -255,8 +267,9 @@ ENV = dict(
os.environ,
TEST_TMPDIR=TEMP_DIR,
TMPDIR=TEMP_DIR,
- REMOTE_EXECUTION_ADDRESS= g_REMOTE_EXECUTION_ADDRESS if not standalone_serve else SERVE_ADDRESS,
- REMOTE_LBR=REMOTE_LBR if not standalone_serve else SERVE_LBR,
+ REMOTE_EXECUTION_ADDRESS=(g_REMOTE_EXECUTION_ADDRESS
+ if not standalone_serve else SERVE_ADDRESS),
+ REMOTE_LBR=(REMOTE_LBR if not standalone_serve else SERVE_LBR),
SERVE=SERVE_ADDRESS,
SERVE_LBR=SERVE_LBR, # expose the serve build root to the test env
**repos_env)
diff --git a/test/utils/serve_service/test_runner.py b/test/utils/serve_service/test_runner.py
index b043b363..01d5c0c8 100755
--- a/test/utils/serve_service/test_runner.py
+++ b/test/utils/serve_service/test_runner.py
@@ -40,13 +40,13 @@ def dump_results() -> None:
dump_results()
-TEMP_DIR = os.path.realpath("scratch")
+TEMP_DIR = os.path.abspath(os.path.realpath("scratch"))
os.makedirs(TEMP_DIR, exist_ok=True)
-WORK_DIR = os.path.realpath("work")
+WORK_DIR = os.path.abspath(os.path.realpath("work"))
os.makedirs(WORK_DIR, exist_ok=True)
-REMOTE_DIR = os.path.realpath("remote")
+REMOTE_DIR = os.path.abspath(os.path.realpath("remote"))
os.makedirs(REMOTE_DIR, exist_ok=True)
SERVE_CONFIG_FILE = os.path.realpath("just-servec")
@@ -70,18 +70,47 @@ if os.path.exists(REMOTE_SERVE_INFO):
# Run 'just serve'
+PATH = subprocess.run(
+ ["env", "--", "sh", "-c", "echo -n $PATH"],
+ stdout=subprocess.PIPE,
+).stdout.decode('utf-8')
+
+compatible: bool = False
+with open("compatible-remote.json") as f:
+ s = json.load(f)
+ if s:
+ compatible = True
+
with open(SERVE_CONFIG_FILE, "w") as f:
f.write(
json.dumps({
- "repositories": [TEST_SERVE_REPO_1, TEST_SERVE_REPO_2],
+ "repositories": [{
+ "root": "system",
+ "path": TEST_SERVE_REPO_1
+ }, {
+ "root": "system",
+ "path": TEST_SERVE_REPO_2
+ }],
"logging": {
"limit": 6,
"plain": True
},
"remote service": {
- "info file": REMOTE_SERVE_INFO
+ "info file": {
+ "root": "system",
+ "path": REMOTE_SERVE_INFO
+ }
+ },
+ "local build root": {
+ "root": "system",
+ "path": SERVE_LBR
+ },
+ "execution endpoint": {
+ "compatible": compatible
},
- "local build root": SERVE_LBR
+ "build": {
+ "local launcher": ["env", "PATH=" + PATH]
+ }
}))
serve_cmd = ["./bin/just", "serve", SERVE_CONFIG_FILE]