diff --git a/.sai.json b/.sai.json
index c2c175f..2ddf952 100644
--- a/.sai.json
+++ b/.sai.json
@@ -3,10 +3,19 @@
"platforms": {
"rocky9/aarch64-a72a55-rk3588/gcc": {
- "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;cmake .. ${cmake};make -j;cpack -G RPM"
+ "build": [
+ "mkdir build destdir;cd build; CCACHE_DISABLE=1 cmake .. ${cmake}",
+ "make -j",
+ "SAI_CPACK=\"-G RPM\" ${cpack}"
+ ]
},
"netbsd-OSX-bigsur/x86_64-intel-i3/llvm": {
- "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";export MACOSX_DEPLOYMENT_TARGET=10.14 ; cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}",
+ "build": [
+ "mkdir build destdir; cd build; MACOSX_DEPLOYMENT_TARGET=10.14 ; cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} ",
+ "make -j && make -j DESTDIR=../destdir install",
+ "ctest -j4 --output-on-failure",
+ "SAI_CPACK=\"-G ZIP\" ${cpack}"
+ ],
"default": false
}
},
@@ -14,12 +23,12 @@
"configurations": {
"server+builder": {
"cmake": "",
- "cpack": "&& cpack -C DEBUG $SAI_CPACK",
+ "cpack": "cpack -C DEBUG $SAI_CPACK",
"artifacts": "build/sai-*.rpm"
},
"builder-only": {
"cmake": "-DSAI_SERVER=0 ",
- "cpack": "&& cpack -C DEBUG $SAI_CPACK",
+ "cpack": "cpack -C DEBUG $SAI_CPACK",
"artifacts": "build/sai-*.rpm"
}
}
diff --git a/src/builder/b-comms.c b/src/builder/b-comms.c
index 2ba95bb..12c1af2 100644
--- a/src/builder/b-comms.c
+++ b/src/builder/b-comms.c
@@ -286,7 +286,7 @@ saib_m_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len,
switch (ns->state) {
case NSSTATE_CHECKEDOUT:
saib_set_ns_state(ns, NSSTATE_BUILD);
- if (saib_spawn(ns)) {
+ if (saib_spawn_build(ns)) {
lwsl_err("%s: saib_spawn failed\n",
__func__);
saib_set_ns_state(ns, NSSTATE_FAILED);
diff --git a/src/builder/b-nspawn.c b/src/builder/b-nspawn.c
index 70a6404..43e0a33 100644
--- a/src/builder/b-nspawn.c
+++ b/src/builder/b-nspawn.c
@@ -161,6 +161,10 @@ sai_lsp_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si,
// lwsl_warn("%s: reap at %llu: we_killed_him: %d\n", __func__,
// (unsigned long long)lws_now_usecs(), we_killed_him);
+ int exit_code = -1;
+ char s[128];
+ int n;
+
saib_log_chunk_create(ns, ">saib> Reaping build process\n", 29, 3);
#if !defined(WIN32)
@@ -170,20 +174,23 @@ sai_lsp_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si,
if (we_killed_him & 1) {
lwsl_notice("%s: Process TIMED OUT by Sai\n", __func__);
+ exit_code = -1;
ns->retcode = SAISPRF_TIMEDOUT;
- goto ok;
+ goto fail;
}
if (we_killed_him & 2) {
lwsl_notice("%s: Process killed by Sai due to spew\n", __func__);
+ exit_code = -1;
ns->retcode = SAISPRF_TERMINATED;
- goto ok;
+ goto fail;
}
switch (si->si_code) {
case CLD_EXITED:
lwsl_notice("%s: Process Exited with exit code %d\n",
__func__, si->si_status);
+ exit_code = si->si_status;
ns->retcode = SAISPRF_EXIT | si->si_status;
if (ns->user_cancel)
ns->retcode = SAISPRF_TERMINATED;
@@ -198,12 +205,32 @@ sai_lsp_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si,
lwsl_notice("%s: SI code %d\n", __func__, si->si_code);
break;
}
-
-ok:
#else
- ns->retcode = SAISPRF_EXIT | (si->retcode & 0xff);
+ exit_code = si->retcode & 0xff;
+ ns->retcode = SAISPRF_EXIT | exit_code;
#endif
+ if (exit_code)
+ goto fail;
+
+ /* step succeeded */
+
+ n = lws_snprintf(s, sizeof(s), "Build step %d OK", ns->build_step + 1);
+ saib_log_chunk_create(ns, s, (size_t)n, 3);
+
+ ns->build_step++;
+ if (ns->build_step < ns->build_step_count) {
+ /* there are more steps, spawn the next one */
+ if (ns)
+ ns->op = NULL;
+ free(op);
+ saib_spawn_step(ns);
+ return;
+ }
+
+ /* all steps succeeded */
+ lwsl_notice("%s: all build steps succeeded\n", __func__);
+
saib_task_grace(ns);
saib_set_ns_state(ns, NSSTATE_DONE);
@@ -221,6 +248,21 @@ ok:
if (ns)
ns->op = NULL;
free(op);
+
+ return;
+
+fail:
+ n = lws_snprintf(s, sizeof(s), "Build step %d FAILED", ns->build_step + 1);
+ saib_log_chunk_create(ns, s, (size_t)n, 3);
+
+ saib_task_grace(ns);
+ saib_set_ns_state(ns, NSSTATE_FAILED);
+
+ saib_log_chunk_create(ns, NULL, 0, 2);
+
+ if (ns)
+ ns->op = NULL;
+ free(op);
}
#if defined(WIN32)
@@ -265,7 +307,34 @@ static const char * const runscript =
#endif
int
-saib_spawn(struct sai_nspawn *ns)
+saib_spawn_step(struct sai_nspawn *ns);
+
+int
+saib_spawn_build(struct sai_nspawn *ns)
+{
+ const char *p = ns->task->build;
+ int n;
+
+ ns->build_step = 0;
+ ns->build_step_count = 0;
+
+ lwsl_hexdump_err(ns->task->build, strlen(ns->task->build));
+
+ while ((p = strchr(p, '\n'))) {
+ ns->build_step_count++;
+ p++;
+ }
+ ns->build_step_count++;
+
+ n = lws_snprintf(ns->pending_mirror_log, sizeof(ns->pending_mirror_log),
+ "Starting build: %d steps", ns->build_step_count);
+ saib_log_chunk_create(ns, ns->pending_mirror_log, (size_t)n, 3);
+
+ return saib_spawn_step(ns);
+}
+
+int
+saib_spawn_step(struct sai_nspawn *ns)
{
struct lws_spawn_piped_info info;
struct saib_opaque_spawn *op;
@@ -300,7 +369,25 @@ saib_spawn(struct sai_nspawn *ns)
builder.home, st, ns->instance_idx);
#endif
- lwsl_hexdump_notice(ns->task->build, strlen(ns->task->build));
+ char one_step[4096];
+ const char *p_build = ns->task->build, *q;
+ int step = 0;
+
+ // lwsl_hexdump_notice(ns->task->build, strlen(ns->task->build));
+
+ while (step < ns->build_step && (p_build = strchr(p_build, '\n'))) {
+ p_build++;
+ step++;
+ }
+
+ if (p_build) {
+ q = strchr(p_build, '\n');
+ if (q)
+ lws_strnncpy(one_step, p_build, q - p_build, sizeof(one_step));
+ else
+ lws_strncpy(one_step, p_build, sizeof(one_step));
+ } else
+ one_step[0] = '\0';
#if defined(WIN32)
if (_sopen_s(&fd, args, _O_CREAT | _O_TRUNC | _O_WRONLY,
@@ -326,13 +413,13 @@ saib_spawn(struct sai_nspawn *ns)
n = lws_snprintf(st, sizeof(st), runscript, ns->instance_idx,
respath, ns->slp_control.sockpath,
ns->slp[0].sockpath, ns->slp[1].sockpath, builder.home,
- ns->inp, ns->task->build);
+ ns->inp, one_step);
#else
n = lws_snprintf(st, sizeof(st), runscript, builder.home, ns->fsm.ovname,
ns->project_name, ns->ref, ns->instance_idx,
respath, ns->slp_control.sockpath,
ns->slp[0].sockpath, ns->slp[1].sockpath,
- builder.home, ns->task->build);
+ builder.home, one_step);
#endif
/* but from the script's pov, it's chrooted at /home/sai */
diff --git a/src/builder/b-private.h b/src/builder/b-private.h
index e9a71ec..6de26bf 100644
--- a/src/builder/b-private.h
+++ b/src/builder/b-private.h
@@ -178,7 +178,10 @@ int
saib_overlay_unmount(struct sai_nspawn *ns);
int
-saib_spawn(struct sai_nspawn *ns);
+saib_spawn_build(struct sai_nspawn *ns);
+
+int
+saib_spawn_step(struct sai_nspawn *ns);
int
saib_prepare_mount(struct sai_builder *b, struct sai_nspawn *ns);
diff --git a/src/common/include/private.h b/src/common/include/private.h
index f497e31..061e7cd 100644
--- a/src/common/include/private.h
+++ b/src/common/include/private.h
@@ -192,6 +192,9 @@ struct sai_nspawn {
uint8_t stdcount;
uint8_t term_budget;
+ int build_step;
+ int build_step_count;
+
uint8_t finished_when_logs_drained:1;
uint8_t state_changed:1;
uint8_t user_cancel:1;
diff --git a/src/server/s-notification.c b/src/server/s-notification.c
index 6028beb..cf1019d 100644
--- a/src/server/s-notification.c
+++ b/src/server/s-notification.c
@@ -61,6 +61,7 @@ enum enum_paths {
static const char * const saifile_paths[] = {
"schema",
+ "platforms.*.build[]",
"platforms.*.build",
"platforms.*.default",
"platforms.*",
@@ -75,6 +76,7 @@ static const char * const saifile_paths[] = {
enum enum_saifile_paths {
LEJPNSAIF_SCHEMA,
+ LEJPNSAIF_PLAT_BUILD_STAGE,
LEJPNSAIF_PLAT_BUILD,
LEJPNSAIF_PLAT_DEFAULT,
LEJPNSAIF_PLAT_NAME,
@@ -690,14 +692,25 @@ sai_saifile_lejp_cb(struct lejp_ctx *ctx, char reason)
break;
case LEJPNSAIF_PLAT_BUILD:
+ case LEJPNSAIF_PLAT_BUILD_STAGE:
/*
* The overall build script for this platform
* is appended into the temp sn.platbuild
*/
+ if (reason != LEJPCB_VAL_STR_END)
+ break;
+
+ lwsl_err("%s: LEJPNSAIF_PLAT_BUILD_STAGE: %.*s\n", __func__, (int)ctx->npos, (const char *)ctx->buf);
+
n = strlen(sn->platbuild);
- if (n < sizeof(sn->platbuild) - 2)
+ if (n < sizeof(sn->platbuild) - 2) {
+ if (n) {
+ sn->platbuild[n++] = '\n';
+ sn->platbuild[n] = '\0';
+ }
lws_strnncpy(sn->platbuild + n, ctx->buf, ctx->npos,
sizeof(sn->platbuild) - n);
+ }
break;
case LEJPNSAIF_PLAT_DEFAULT: