Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions .aspect/config.axl
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@ def config(ctx: ConfigContext):
# assert we can call a lambda with a global bind from another module in a config script
lambda_with_global_bind()("assert")

# Configure the UserTaskConfig fragment globally
user_config = ctx.fragments[UserTaskConfig]
user_config.message = "hello axl"
user_config.count = 2
user_config.customize_message = lambda s: _customize_message(s, "!")

# add a new task
ctx.tasks.add(_user_task)

# customize a task
for task in ctx.tasks:
if task.name == "user_task" and task.group == ["user"]:
task.config = UserTaskConfig(
message = "hello axl",
count = 2,
customize_message = lambda s: _customize_message(s, "!")
)
23 changes: 12 additions & 11 deletions .aspect/user-task.axl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
load("./lambda.axl", "lambda_with_global_bind")

UserTaskConfig = record(
message=field(str, "hello world"),
count=field(int, 1),
customize_message = field(typing.Callable[[str], str], default = lambda s: s),
UserTaskConfig = fragment(
message=attr(str, "hello world"),
count=attr(int, 1),
customize_message = attr(typing.Callable[[str], str], lambda s: s),
)

def _impl(ctx: TaskContext) -> int:
Expand All @@ -13,18 +13,19 @@ def _impl(ctx: TaskContext) -> int:
lambda_with_global_bind()("assert")

# do something that makes uses the task config
config = ctx.fragments[UserTaskConfig]
print(ctx)
print(ctx.config)
print(ctx.config.count)
print(ctx.config.message)
print(ctx.config.customize_message)
for i in range(ctx.config.count):
print(ctx.config.customize_message(ctx.config.message))
print(config)
print(config.count)
print(config.message)
print(config.customize_message)
for i in range(config.count):
print(config.customize_message(config.message))
return 0

user_task = task(
group = ["user"],
implementation = _impl,
args = {},
config = UserTaskConfig(),
fragments = [UserTaskConfig],
)
35 changes: 35 additions & 0 deletions .buildkite/hooks/pre-command
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/sh
set -eu

# Bazel startup options for CI
export BAZEL_STARTUP_OPTS="--nohome_rc --output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ --output_base=/mnt/ephemeral/output/aspect-cli/__main__"

# Build bazel remote flags from environment variables set by configure_workflows_env
BAZEL_REMOTE_FLAGS=""
[ -n "${ASPECT_WORKFLOWS_BES_BACKEND:-}" ] && BAZEL_REMOTE_FLAGS="${BAZEL_REMOTE_FLAGS} --bes_backend=${ASPECT_WORKFLOWS_BES_BACKEND}"
[ -n "${ASPECT_WORKFLOWS_BES_RESULTS_URL:-}" ] && BAZEL_REMOTE_FLAGS="${BAZEL_REMOTE_FLAGS} --bes_results_url=${ASPECT_WORKFLOWS_BES_RESULTS_URL}"
[ -n "${ASPECT_WORKFLOWS_REMOTE_CACHE:-}" ] && BAZEL_REMOTE_FLAGS="${BAZEL_REMOTE_FLAGS} --remote_cache=${ASPECT_WORKFLOWS_REMOTE_CACHE}"
[ -n "${ASPECT_WORKFLOWS_REMOTE_BYTESTREAM_URI_PREFIX:-}" ] && BAZEL_REMOTE_FLAGS="${BAZEL_REMOTE_FLAGS} --remote_bytestream_uri_prefix=${ASPECT_WORKFLOWS_REMOTE_BYTESTREAM_URI_PREFIX}"
export BAZEL_REMOTE_FLAGS

export BAZEL_BUILD_OPTS="--config=ci ${BAZEL_REMOTE_FLAGS}"

# Skip if bazel is not installed
if ! command -v bazel >/dev/null 2>&1; then
echo "DEBUG: bazel not found, skipping"
exit 0
fi

# We use a short timeout so we capture the "Another command (pid=X)" message without
# blocking indefinitely.
LOCK_OUTPUT=$(timeout 5 bazel $BAZEL_STARTUP_OPTS info 2>&1) || true
BUSY_PID=$(echo "$LOCK_OUTPUT" | grep -o '(pid=[0-9]*)' | grep -o '[0-9]*') || true
if [ -n "$BUSY_PID" ]; then
/etc/aspect/workflows/bin/signal_instance_unhealthy
exit 78
fi

# Build aspect-cli so version.axl can pick it up from bazel-bin/
echo "--- Building aspect-cli"
# bazel in aspect workflows runners is actually old aspect-cli.
bazel --aspect:disable_plugins $BAZEL_STARTUP_OPTS build $BAZEL_BUILD_OPTS -c dbg --remote_download_toplevel --show_progress_rate_limit=1 //:cli
180 changes: 100 additions & 80 deletions .buildkite/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -1,85 +1,105 @@
# Generated by: aspect workflows migrate --host=buildkite
# Source: .aspect/workflows/config_aws.yaml
# DO NOT EDIT - regenerate with 'aspect workflows migrate'

env:
ASPECT_DEBUG: "1"
steps:
- label: ":aspect: Test"
- key: __main__::warm
label: ":aspect: Building CLI"
agents:
queue: aspect-huge
command: |
echo "--- :aspect-build: Workflows environment"
/etc/aspect/workflows/bin/configure_workflows_env
env | sort | grep ^ASPECT_WORKFLOWS_
echo "--- :stethoscope: Agent health check"
/etc/aspect/workflows/bin/agent_health_check
echo "--- :bazel: bazel test //..."
pwd
rosetta bazelrc > /etc/bazel.bazelrc
bazel \
--nohome_rc \
--output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ \
--output_base=/mnt/ephemeral/output/aspect-cli/__main__ \
test \
--config=workflows \
--config=ci \
--test_output=summary \
--show_progress_rate_limit=1 \
-- //...
echo "--- :bazel: bazel build //:launcher //:cli"
bazel \
--nohome_rc \
--output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ \
--output_base=/mnt/ephemeral/output/aspect-cli/__main__ \
build \
--config=workflows \
--config=ci \
--test_output=summary \
--show_progress_rate_limit=1 \
--remote_download_outputs="toplevel" \
-- //:launcher //:cli
# Use cquery to get the actual output paths (handles platform transitions on Linux)
WORKSPACE_ROOT=$$(pwd)
LAUNCHER=$$WORKSPACE_ROOT/$$(bazel --nohome_rc --output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ --output_base=/mnt/ephemeral/output/aspect-cli/__main__ cquery --config=workflows --config=ci --output=files //crates/aspect-launcher)
CLI=$$WORKSPACE_ROOT/$$(bazel --nohome_rc --output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ --output_base=/mnt/ephemeral/output/aspect-cli/__main__ cquery --config=workflows --config=ci --output=files //crates/aspect-cli)
echo "--- :aspect: aspect tests axl"
$$LAUNCHER tests axl
echo "--- :aspect: aspect demo template-demo"
$$LAUNCHER demo template-demo
echo "--- :aspect: aspect user user_task"
$$LAUNCHER user user_task
echo "--- :aspect: aspect user user_task_reexport"
$$LAUNCHER user user_task_reexport
echo "--- :aspect: aspect user user-task-manual"
$$LAUNCHER user user-task-manual
echo "--- :aspect: aspect user user-task-added-by-config"
$$LAUNCHER user user-task-added-by-config
echo "--- :aspect: aspect user user-task-subdir (in crates/aspect-cli)"
(
cd crates/aspect-cli
$$LAUNCHER user user-task-subdir
)
echo "--- :aspect: aspect help"
$$LAUNCHER help
echo "--- :aspect: aspect-launcher --version"
$$LAUNCHER --version
echo "--- :aspect: aspect-cli --version"
$$CLI --version
echo "--- :aspect: aspect version"
$$LAUNCHER version
- label: ":broom: Format"
timeout_in_minutes: 20
retry:
automatic:
- exit_status: 78
limit: 1
command:
- echo "Pre-command builds and uploads CLI to remote cache"
- key: __main__::test
depends_on:
- __main__::warm
label: ":aspect: Test"
agents:
queue: aspect-default
command: |
echo "--- :aspect-build: Workflows environment"
/etc/aspect/workflows/bin/configure_workflows_env
env | sort | grep ^ASPECT_WORKFLOWS_
echo "--- :stethoscope: Agent health check"
/etc/aspect/workflows/bin/agent_health_check
echo "--- :bazel: bazel run //tools/format:format.check"
pwd
rosetta bazelrc > /etc/bazel.bazelrc
bazel \
--nohome_rc \
--output_user_root=/mnt/ephemeral/bazel/aspect-cli/__main__ \
--output_base=/mnt/ephemeral/output/aspect-cli/__main__ \
run \
--config=workflows \
--config=ci \
--show_progress_rate_limit=1 \
//tools/format:format.check
timeout_in_minutes: 20
retry:
automatic:
- exit_status: 78
limit: 1
command:
- |
echo "--- :bazel: aspect test //..."
ASPECT_DEBUG=1 aspect test //... --bazel_flag=--build_tests_only
- key: __main__::build
depends_on:
- __main__::warm
label: ":aspect: Build"
agents:
queue: aspect-huge
timeout_in_minutes: 20
retry:
automatic:
- exit_status: 78
limit: 1
command:
- |
echo "--- :bazel: aspect build //:launcher //:cli"
aspect build //:launcher //:cli
# Use cquery to get the actual output paths (handles platform transitions on Linux)
WORKSPACE_ROOT=$$(pwd)
LAUNCHER=$$WORKSPACE_ROOT/$$(bazel $$BAZEL_STARTUP_OPTS cquery $$BAZEL_BUILD_OPTS --output=files //crates/aspect-launcher)
CLI=$$WORKSPACE_ROOT/$$(bazel $$BAZEL_STARTUP_OPTS cquery $$BAZEL_BUILD_OPTS --output=files //crates/aspect-cli)
echo "--- :aspect: aspect tests axl"
$$LAUNCHER tests axl
echo "--- :aspect: aspect demo template-demo"
$$LAUNCHER demo template-demo
echo "--- :aspect: aspect user user_task"
$$LAUNCHER user user_task
echo "--- :aspect: aspect user user_task_reexport"
$$LAUNCHER user user_task_reexport
echo "--- :aspect: aspect user user-task-manual"
$$LAUNCHER user user-task-manual
echo "--- :aspect: aspect user user-task-added-by-config"
$$LAUNCHER user user-task-added-by-config
echo "--- :aspect: aspect user user-task-subdir (in crates/aspect-cli)"
(
cd crates/aspect-cli
$$LAUNCHER user user-task-subdir
)
echo "--- :aspect: aspect help"
$$LAUNCHER help
echo "--- :aspect: aspect-launcher --version"
$$LAUNCHER --version
echo "--- :aspect: aspect-cli --version"
$$CLI --version
echo "--- :aspect: aspect version"
$$LAUNCHER version
- key: __main__::format
label: ":broom: Format"
depends_on:
- __main__::warm
agents:
queue: aspect-default
timeout_in_minutes: 20
retry:
automatic:
- exit_status: 78
limit: 1
command:
- |
echo "--- :bazel: bazel run //tools/format:format.check"
bazel $$BAZEL_STARTUP_OPTS run $$BAZEL_BUILD_OPTS //tools/format:format.check
- key: __main__::delivery
label: ":package: Delivery"
depends_on:
- __main__::warm
agents:
queue: aspect-default
timeout_in_minutes: 20
retry:
automatic:
- exit_status: 78
limit: 1
command:
- aspect delivery --build_url $BUILDKITE_BUILD_URL --commit_sha $BUILDKITE_COMMIT --force_target //:hello -- //:hello //:hello2
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/aspect-cli/.aspect/config.axl
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
def config(ctx: ConfigContext):
print("running crates/aspect-cli/.aspect/config.axl")
pass
5 changes: 5 additions & 0 deletions crates/aspect-cli/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rust_binary(
"@crates//:clap",
"@crates//:miette",
"@crates//:reqwest",
"@crates//:sha256",
"@crates//:starlark",
"@crates//:tokio",
"@crates//:thiserror",
Expand All @@ -24,6 +25,10 @@ rust_binary(
"//crates/aspect-telemetry",
"//crates/axl-runtime",
],
compile_data = glob([
"src/builtins/**/*.axl",
"src/builtins/**/*.aspect",
]),
visibility = ["//:__pkg__"],
)

Expand Down
1 change: 1 addition & 0 deletions crates/aspect-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ opentelemetry_sdk = "0.31.0"
opentelemetry-otlp = {version = "0.31.0", features = ["grpc-tonic", "tls-roots"]}
opentelemetry-semantic-conventions = "0.31.0"
reqwest = { version = "0.12.22", default-features = false, features = ["http2", "charset", "system-proxy", "rustls-tls", "stream"] }
sha256 = "1.6.0"
starlark = "0.13.0"
thiserror = "2.0.17"
tokio = { version = "1.47.1", features = ["macros", "rt", "rt-multi-thread"] }
Expand Down
12 changes: 12 additions & 0 deletions crates/aspect-cli/src/builtins/aspect/MODULE.aspect
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use_task("build.axl", "build")
use_task("test.axl", "test")
use_task("axl_add.axl", "add")

# Configure delivery
use_config("config/delivery.axl", "configure_delivery")

# Configure builtins
use_config("config/builtins.axl", "configure_builtins")

# Configure artifact uploads
use_config("config/artifacts.axl", "configure_artifacts")
41 changes: 41 additions & 0 deletions crates/aspect-cli/src/builtins/aspect/bazel.axl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Bazel exit code constants.

These correspond to the exit codes defined in Bazel's ExitCode.java:
https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/util/ExitCode.java
"""

exit_codes = struct(
SUCCESS = 0,
BUILD_FAILURE = 1,
PARSING_FAILURE = 1,
COMMAND_LINE_ERROR = 2,
TESTS_FAILED = 3,
PARTIAL_ANALYSIS_FAILURE = 3,
NO_TESTS_FOUND = 4,
RUN_FAILURE = 6,
ANALYSIS_FAILURE = 7,
INTERRUPTED = 8,
LOCK_HELD_NOBLOCK_FOR_LOCK = 9,
REMOTE_ENVIRONMENTAL_ERROR = 32,
OOM_ERROR = 33,
REMOTE_ERROR = 34,
LOCAL_ENVIRONMENTAL_ERROR = 36,
BLAZE_INTERNAL_ERROR = 37,
TRANSIENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR = 38,
REMOTE_CACHE_EVICTED = 39,
PERSISTENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR = 45,
EXTERNAL_DEPS_ERROR = 48,
)

# https://bazel.build/run/scripts#exit-codes
def default_retry(code: int) -> bool:
"""Returns True if the given exit code is retryable.

Retryable codes are those indicating transient infrastructure failures
where re-running the command may succeed:
- BLAZE_INTERNAL_ERROR (37): Bazel server crash.
- LOCAL_ENVIRONMENTAL_ERROR (36): Local env failure, often caused by
a queued command failing because the server is crashing.
"""
return code == exit_codes.BLAZE_INTERNAL_ERROR or code == exit_codes.LOCAL_ENVIRONMENTAL_ERROR
Loading