/ opencodehub / scripts / runner.sh
Swadhin Biswas chore(infra): harden deployment, backups, and production docs · 3/6/2026
16d8399
150 lines · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/bash
set -e

echo "OpenCodeHub Runner Starting..."

# Wait for Docker daemon if using DinD
if [ -S /var/run/docker.sock ]; then
    echo "Docker socket found"
else
    echo "Waiting for Docker daemon..."
    while ! docker info >/dev/null 2>&1; do
        sleep 1
    done
fi

echo "Docker daemon ready"

# Register runner with server
register_runner() {
    local response=$(curl -sf "${SERVER_URL}/api/runners/register" \
        -H "Content-Type: application/json" \
        -d "{\"token\": \"${RUNNER_TOKEN}\", \"name\": \"$(hostname)\"}")

    if [ $? -eq 0 ]; then
        echo "Runner registered successfully"
        RUNNER_ID=$(echo "$response" | jq -r '.id')
        export RUNNER_ID
    else
        echo "Failed to register runner"
        exit 1
    fi
}

# Poll for jobs
poll_jobs() {
    while true; do
        local response=$(curl -sf "${SERVER_URL}/api/runners/${RUNNER_ID}/jobs" \
            -H "Authorization: Bearer ${RUNNER_TOKEN}")

        if [ $? -eq 0 ] && [ "$(echo "$response" | jq -r '.job')" != "null" ]; then
            local job=$(echo "$response" | jq -r '.job')
            run_job "$job"
        fi

        sleep 5
    done
}

# Run a job
run_job() {
    local job="$1"
    local job_id=$(echo "$job" | jq -r '.id')
    local repo_url=$(echo "$job" | jq -r '.repository.clone_url')
    local ref=$(echo "$job" | jq -r '.ref')
    local workflow=$(echo "$job" | jq -r '.workflow')

    echo "Running job: $job_id"

    # Update job status
    curl -sf "${SERVER_URL}/api/jobs/${job_id}/status" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${RUNNER_TOKEN}" \
        -d '{"status": "in_progress"}'

    # Create work directory
    local work_dir="${RUNNER_WORK_DIR}/${job_id}"
    mkdir -p "$work_dir"
    cd "$work_dir"

    # Clone repository
    git clone --depth 1 --branch "$ref" "$repo_url" .

    # Parse and run workflow
    local exit_code=0

    # Run workflow steps (simplified - real implementation uses pipeline.ts)
    if [ -f ".github/workflows/${workflow}" ]; then
        echo "Running workflow: ${workflow}"

        # Extract and run steps
        local jobs=$(yq -r '.jobs | keys[]' ".github/workflows/${workflow}")

        for job_name in $jobs; do
            echo "Running job: $job_name"

            # Get container image
            local image=$(yq -r ".jobs.${job_name}.[\"runs-on\"]" ".github/workflows/${workflow}")
            case "$image" in
                "ubuntu-latest") image="ubuntu:22.04" ;;
                "ubuntu-22.04") image="ubuntu:22.04" ;;
                *) image="node:20" ;;
            esac

            # Run steps in container
            local steps=$(yq -r ".jobs.${job_name}.steps | length" ".github/workflows/${workflow}")

            for ((i=0; i<steps; i++)); do
                local step_name=$(yq -r ".jobs.${job_name}.steps[$i].name // \"Step $i\"" ".github/workflows/${workflow}")
                local step_run=$(yq -r ".jobs.${job_name}.steps[$i].run // \"\"" ".github/workflows/${workflow}")

                if [ -n "$step_run" ] && [ "$step_run" != "null" ]; then
                    echo "Running step: $step_name"

                    docker run --rm \
                        -v "$work_dir:/workspace" \
                        -w /workspace \
                        -e CI=true \
                        -e GITHUB_SHA="$ref" \
                        "$image" \
                        /bin/sh -c "$step_run" || exit_code=$?

                    if [ $exit_code -ne 0 ]; then
                        echo "Step failed with exit code: $exit_code"
                        break 2
                    fi
                fi
            done
        done
    fi

    # Update job status
    local conclusion="success"
    if [ $exit_code -ne 0 ]; then
        conclusion="failure"
    fi

    curl -sf "${SERVER_URL}/api/jobs/${job_id}/status" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${RUNNER_TOKEN}" \
        -d "{\"status\": \"completed\", \"conclusion\": \"${conclusion}\"}"

    # Cleanup
    cd /
    rm -rf "$work_dir"

    echo "Job completed: $job_id ($conclusion)"
}

# Main
if [ -n "$RUNNER_TOKEN" ] && [ -n "$SERVER_URL" ]; then
    register_runner
    poll_jobs
else
    echo "RUNNER_TOKEN and SERVER_URL must be set"
    echo "Running in standalone mode..."

    # Keep container running
    tail -f /dev/null
fi