diff --git a/.aspect/config.axl b/.aspect/config.axl index 89fbd405d..486ea5f65 100644 --- a/.aspect/config.axl +++ b/.aspect/config.axl @@ -10,8 +10,7 @@ task2 = task( def config(ctx: ConfigContext): ctx.tasks.add(task2, name = "added_by_config", group = []) - print("running config") - for task in ctx.tasks: - print(task.name, task.group) + # for task in ctx.tasks: + # print(task.name, task.group, task.binding) pass diff --git a/.aspect/delivery.axl b/.aspect/delivery.axl new file mode 100644 index 000000000..ed3ec13f1 --- /dev/null +++ b/.aspect/delivery.axl @@ -0,0 +1,329 @@ +""" +Delivery task that coordinates artifact delivery via Redis. + +Reads the delivery manifest for a commit, delivers each target via bazel run +with stamping enabled, and signs artifacts to prevent re-delivery. + +See: DELIVERY_REDIS_KEYS.md for key format documentation. +""" + +# Redis command helpers + +def _redis_cmd(ctx, redis_cfg, *cmd_args): + """Execute a redis-cli command and return the output.""" + host, port, use_tls = redis_cfg + + cmd = ctx.std.process.command("redis-cli") + cmd.args(["-h", host, "-p", str(port)]) + # Add connection timeout to prevent hanging on TLS mismatch + cmd.args(["-t", "5"]) + if use_tls: + cmd.arg("--tls") + cmd.args(list(cmd_args)) + cmd.stdout("piped") + cmd.stderr("piped") + + child = cmd.spawn() + output = child.wait_with_output() + + if not output.status.success: + fail("redis-cli failed: " + output.stderr) + + return output.stdout.strip() + +def _redis_get(ctx, redis_cfg, key): + """GET a value by key from Redis.""" + result = _redis_cmd(ctx, redis_cfg, "GET", key) + return None if result == "(nil)" else result + +def _redis_set(ctx, redis_cfg, key, value): + """SET a key-value pair in Redis.""" + return _redis_cmd(ctx, redis_cfg, "SET", key, value) + +def _redis_setnx(ctx, redis_cfg, key, value): + """SETNX - set if not exists. Returns True if key was set, False if it already existed.""" + result = _redis_cmd(ctx, redis_cfg, "SETNX", key, value) + return result == "1" + +def _redis_del(ctx, redis_cfg, key): + """DEL a key from Redis.""" + return _redis_cmd(ctx, redis_cfg, "DEL", key) + +def _redis_lrange(ctx, redis_cfg, key, start, stop): + """LRANGE to get list elements from Redis.""" + result = _redis_cmd(ctx, redis_cfg, "LRANGE", key, str(start), str(stop)) + if not result or result == "(empty list or set)": + return [] + # Parse redis-cli output format (numbered lines) + lines = result.split("\n") + items = [] + for line in lines: + # Format: "1) value" or just "value" + if ") " in line: + items.append(line.split(") ", 1)[1]) + elif line: + items.append(line) + return items + +# Key builders (match format from delivery-base.task.ts) + +def _artifact_metadata_key(ci_host, output_sha, workspace): + """ + Redis key for mapping of output sha -> metadata. + Format: :: + """ + return "{}:{}:{}".format(ci_host, output_sha, workspace) + +def _delivery_manifest_key(ci_host, commit_sha, workspace): + """ + Redis key for mapping of commit sha -> delivery target list. + Format: :: + """ + return "{}:{}:{}".format(ci_host, commit_sha, workspace) + +def _output_sha_lookup_key(ci_host, commit_sha, workspace, label): + """ + Redis key for reverse mapping of label -> output sha for a commit. + Format: output-sha::::