Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
98900a3
Add airstack image-delete. Also change URDF check to consider env var…
OasisArtisan Apr 16, 2026
a07950c
Add delay before starting PX4 for airsim. This is allowing PX4 to con…
OasisArtisan Apr 16, 2026
9842876
Initial docker build and package build tests
OasisArtisan Apr 17, 2026
fb79a89
Compute docker image sizes and add compare_metrics.py to output clean…
OasisArtisan Apr 17, 2026
0db708c
Auto fetch airsim scene if user didn't specify path.
OasisArtisan Apr 17, 2026
1ec1945
Upgrade pegasus example from two to arbitrary number of drones equal…
OasisArtisan Apr 17, 2026
514b589
Initial liveliness checks.
OasisArtisan Apr 19, 2026
22e7fb8
Liveliness with properly grouped output table
OasisArtisan Apr 20, 2026
21a8b09
Add compute usage logging to liveliness
OasisArtisan Apr 20, 2026
307aac8
Parse metrics to support parsing single results file into markdown.
OasisArtisan Apr 21, 2026
18b1212
Add docs, add serivces and scripts for github ci/cd
andrewjong Apr 21, 2026
dbf425f
Tag test docker + add measuring realtime factor to liveliness
OasisArtisan Apr 22, 2026
95b52ab
Initial working autonomy (Takeoff, hover, land) tests.
OasisArtisan Apr 22, 2026
dacaeb4
Add airsim GT publishing and compute odom vs GT metrics
OasisArtisan Apr 23, 2026
26392b6
Hover measures drift from hover start not to target. Pass rates are r…
OasisArtisan Apr 23, 2026
3b2a827
Fix broken px4_ready now uses MAVROS connected and odom publication f…
OasisArtisan Apr 23, 2026
2922a7e
Standardize displayed parameterization order in results and tables
OasisArtisan Apr 23, 2026
acf59b1
Enforce module ordering
OasisArtisan Apr 23, 2026
175891f
Warn if testing build packages and packages are already built
OasisArtisan Apr 23, 2026
2b39a2b
Set version to 0.18.0-alpha.5
andrewjong Apr 23, 2026
3dd3bd9
Rename test_autonomy to test_takeoff_hover_land
andrewjong Apr 23, 2026
ba3c7a1
Update docs
andrewjong Apr 23, 2026
70651fd
Add help for airstack test
andrewjong Apr 23, 2026
3174535
Add video
andrewjong Apr 23, 2026
29faca8
Merge branch 'main' into omar/ci
andrewjong Apr 23, 2026
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
36 changes: 10 additions & 26 deletions .airstack/modules/dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,17 @@
# dev.sh - Development-related commands for AirStack
# This module provides commands for development tasks

# Function to run tests
# Run tests via the dockerized pytest runner. All args forward to pytest.
function cmd_dev_test {
log_info "Running tests..."

local test_path="$PROJECT_ROOT/tests"
local test_filter=""

# Parse arguments
for arg in "$@"; do
if [[ "$arg" == --path=* ]]; then
test_path="${arg#--path=}"
elif [[ "$arg" == --filter=* ]]; then
test_filter="${arg#--filter=}"
fi
done

if [ -n "$test_filter" ]; then
log_info "Running tests matching '$test_filter' in $test_path"
# Add your test command here, e.g.:
# pytest "$test_path" -k "$test_filter"
echo "Test command would run here with filter: $test_filter"
else
log_info "Running all tests in $test_path"
# Add your test command here, e.g.:
# pytest "$test_path"
echo "Test command would run here"
fi
check_docker
local compose_file="$PROJECT_ROOT/tests/docker/docker-compose.yaml"
local env_file="$PROJECT_ROOT/.env"
export AIRSTACK_PATH="$PROJECT_ROOT"
# Grant X access so sim containers spawned by tests in GUI mode
# (`pytest --gui`) can reach the host's X server. No-op otherwise.
xhost + || log_warn "xhost failed (is DISPLAY set? xhost installed?)"
docker compose --env-file "$env_file" -f "$compose_file" build --quiet
docker compose --env-file "$env_file" -f "$compose_file" run --rm test pytest "$@"
}

# Function to build documentation
Expand Down
7 changes: 4 additions & 3 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
PROJECT_NAME="airstack"
# If you've run ./airstack.sh setup, then this will auto-generate from the git commit hash every time a change is made
# to a Dockerfile or docker-compose.yaml file. Otherwise this can also be set explicitly to make a release version.
VERSION="0.18.0-alpha.5"
VERSION="0.18.0-alpha.6"
# Choose "dev" or "prebuilt". "dev" is for mounted code that must be built live. "prebuilt" is for built ros_ws baked into the image
DOCKER_IMAGE_BUILD_MODE="dev"
# Where to push and pull images from. Can replace with your docker hub username if using docker hub.
Expand All @@ -37,8 +37,9 @@ PLAY_SIM_ON_START="false"
# ===============================================

# ================= MS-AIRSIM =====================
MS_AIRSIM_ENV_DIR="../environments"
MS_AIRSIM_BINARY_PATH="/ms-airsim-env/AbandonedPark/LinuxNoEditor/AbandonedPark.sh"
# Do not set if you want airstack to fetch a simple blocks world.
# MS_AIRSIM_ENV_DIR=./simulation/ms-airsim/assets/scenes
# MS_AIRSIM_BINARY_PATH="/ms-airsim-env/Blocks/LinuxNoEditor/Blocks.sh"
# =================================================

# ================= ROBOT =====================
Expand Down
26 changes: 26 additions & 0 deletions .github/runners/airstack-runner.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[Unit]
Description=AirStack GitHub Actions Runner (ephemeral)
Documentation=https://docs.github.com/en/actions/hosting-your-own-runners
After=network-online.target docker.service
Wants=network-online.target

[Service]
User=runner
Group=runner
WorkingDirectory=/opt/actions-runner

# Place runtime configuration here (REPO_URL, RUNNER_LABELS, etc.).
# Each line: KEY=value (no quotes needed, no export keyword)
EnvironmentFile=/etc/github-runner-env

ExecStart=/opt/actions-runner/register-runner.sh

# Restart unconditionally so the loop survives transient API errors or reboots.
Restart=always
RestartSec=5

# Give the runner enough time to finish a long job before systemd kills it.
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target
96 changes: 96 additions & 0 deletions .github/runners/register-runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# AirStack ephemeral GitHub Actions runner loop.
#
# Registers a fresh runner, executes exactly one job, then loops to re-register.
# The --ephemeral flag tells the GitHub API to remove the runner after one job,
# preventing stale registrations and cross-job state pollution.
#
# Setup (one-time, on the OpenStack VM):
# 1. Create a non-root runner user:
# sudo useradd -m -s /bin/bash runner
# sudo usermod -aG docker runner
#
# 2. Download and unpack the GitHub Actions runner into RUNNER_DIR:
# sudo mkdir -p /opt/actions-runner
# cd /opt/actions-runner
# # Get the latest runner URL from:
# # https://github.com/actions/runner/releases
# curl -Lo actions-runner.tar.gz <URL>
# tar xzf actions-runner.tar.gz
# sudo chown -R runner:runner /opt/actions-runner
#
# 3. Store a GitHub PAT (repo scope for private repos, public_repo for public):
# echo "ghp_YOUR_TOKEN_HERE" | sudo tee /etc/github-runner-pat
# sudo chmod 600 /etc/github-runner-pat
# sudo chown runner:runner /etc/github-runner-pat
#
# 4. Copy this script into the runner directory and make it executable:
# sudo cp register-runner.sh /opt/actions-runner/register-runner.sh
# sudo chown runner:runner /opt/actions-runner/register-runner.sh
# sudo chmod +x /opt/actions-runner/register-runner.sh
#
# 5. Install the systemd unit (see airstack-runner.service) and enable it:
# sudo cp airstack-runner.service /etc/systemd/system/
# sudo systemctl daemon-reload
# sudo systemctl enable --now airstack-runner.service
#
# Configuration: set these in /etc/github-runner-env (loaded by the systemd unit)
# or export them before running this script manually.

set -euo pipefail

REPO_URL="${REPO_URL:-https://github.com/YOUR_ORG/AirStack}"
# Derived from REPO_URL for the registration token API call, e.g. "YOUR_ORG/AirStack"
REPO_PATH="${REPO_PATH:-$(echo "$REPO_URL" | sed 's|https://github.com/||')}"
RUNNER_DIR="${RUNNER_DIR:-/opt/actions-runner}"
PAT_FILE="${PAT_FILE:-/etc/github-runner-pat}"
RUNNER_LABELS="${RUNNER_LABELS:-self-hosted,airstack,gpu}"
RUNNER_GROUP="${RUNNER_GROUP:-Default}"

if [ ! -f "$PAT_FILE" ]; then
echo "ERROR: PAT file not found at $PAT_FILE" >&2
exit 1
fi

echo "Starting ephemeral runner loop for $REPO_URL"

while true; do
echo "[$(date -u +%FT%TZ)] Requesting registration token..."

TOKEN=$(curl -sf -X POST \
-H "Authorization: token $(cat "$PAT_FILE")" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${REPO_PATH}/actions/runners/registration-token" \
| jq -r .token)

if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
echo "ERROR: Failed to obtain registration token. Check PAT and repo path." >&2
sleep 30
continue
fi

echo "[$(date -u +%FT%TZ)] Configuring runner (ephemeral)..."

# --ephemeral: runner de-registers itself after completing one job.
# --replace: allows re-registration with the same name after a restart.
# Runner name encodes hostname + PID so parallel instances are unique.
"$RUNNER_DIR/config.sh" \
--url "$REPO_URL" \
--token "$TOKEN" \
--name "openstack-$(hostname -s)-$$" \
--labels "$RUNNER_LABELS" \
--runnergroup "$RUNNER_GROUP" \
--ephemeral \
--unattended \
--replace

echo "[$(date -u +%FT%TZ)] Runner configured. Waiting for a job..."

# run.sh blocks until the job completes, then returns (ephemeral runner exits cleanly).
"$RUNNER_DIR/run.sh" || true

echo "[$(date -u +%FT%TZ)] Job finished. Re-registering..."

# Brief pause to avoid hammering the API if config.sh / run.sh fail immediately.
sleep 2
done
Loading
Loading