diff --git a/orchestrator/dispatch/bootstrap b/orchestrator/dispatch/bootstrap index 4284a30..4c8cdda 100644 Binary files a/orchestrator/dispatch/bootstrap and b/orchestrator/dispatch/bootstrap differ diff --git a/orchestrator/dispatch/function.zip b/orchestrator/dispatch/function.zip index c998cfb..66c9c2e 100644 Binary files a/orchestrator/dispatch/function.zip and b/orchestrator/dispatch/function.zip differ diff --git a/orchestrator/dispatch/main.go b/orchestrator/dispatch/main.go index b000b68..6b798fc 100644 --- a/orchestrator/dispatch/main.go +++ b/orchestrator/dispatch/main.go @@ -110,28 +110,28 @@ var labelToSpot = map[string]spotConfig{ // --- Config from env --- type cfg struct { - GiteaURL string - GiteaToken string - ExecFnName string - AMI string // pre-baked AMI with Go, Node, Docker, AWS CLI, act_runner - Subnet string - SecurityGroup string - DDBTable string + GiteaURL string + GiteaToken string // API token (for fetching workflows, setting commit status) + RunnerToken string // Runner registration token (for act_runner register) + ExecFnName string + AMI string // pre-baked AMI with Go, Node, Docker, AWS CLI, act_runner + Subnet string + SecurityGroup string + DDBTable string InstanceProfile string - Region string } func loadCfg() cfg { return cfg{ GiteaURL: os.Getenv("GITEA_URL"), GiteaToken: os.Getenv("GITEA_TOKEN"), + RunnerToken: os.Getenv("RUNNER_TOKEN"), ExecFnName: os.Getenv("EXECUTOR_FUNCTION_NAME"), AMI: os.Getenv("RUNNER_AMI"), Subnet: os.Getenv("SUBNET"), SecurityGroup: os.Getenv("SECURITY_GROUP"), DDBTable: os.Getenv("DDB_TABLE"), - InstanceProfile: os.Getenv("INSTANCE_PROFILE"), // IAM instance profile ARN - Region: os.Getenv("AWS_REGION"), + InstanceProfile: os.Getenv("INSTANCE_PROFILE"), } } @@ -144,8 +144,11 @@ set -euo pipefail exec > /var/log/tinqs-ci.log 2>&1 echo "=== Tinqs CI Runner: %s ===" -INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) -REGION=%s + +# Get instance metadata (IMDSv2) +TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") +INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id) +REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region) # Self-termination trap — kill instance on exit (success or failure) cleanup() { @@ -154,8 +157,12 @@ cleanup() { } trap cleanup EXIT -# act_runner is pre-installed in the AMI at /usr/local/bin/act_runner -cd /tmp +# Source Go/Node paths from AMI +export PATH=$PATH:/usr/local/go/bin +export HOME=/root + +# Create proper working directory for act_runner +mkdir -p /opt/runner && cd /opt/runner # Register as ephemeral runner (picks one job, then exits) act_runner register --no-interactive \ @@ -164,11 +171,24 @@ act_runner register --no-interactive \ --name %s \ --labels "%s:host" +# Configure runner to use /opt/runner as workdir +cat > .runner.yaml << 'RUNCFG' +log: + level: info +runner: + capacity: 1 + timeout: 30m +host: + workdir_parent: /opt/runner/work +RUNCFG + +mkdir -p /opt/runner/work + # Run — blocks until the job completes, then exits (ephemeral mode) -act_runner daemon +act_runner daemon --config .runner.yaml echo "=== Runner exited, cleanup will terminate instance ===" -`, runnerName, c.Region, c.GiteaURL, c.GiteaToken, runnerName, label) +`, runnerName, c.GiteaURL, c.RunnerToken, runnerName, label) return base64.StdEncoding.EncodeToString([]byte(script)) }