Skip to content

Commit

Permalink
Restructure scripts
Browse files Browse the repository at this point in the history
Update README.md
  • Loading branch information
dormant-user committed Sep 11, 2024
1 parent e73ba9c commit 2fd57c2
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 160 deletions.
8 changes: 3 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,9 @@ RUN mkdir actions-runner && cd actions-runner \
# Install additional dependencies
RUN chown -R docker ~docker && /home/docker/actions-runner/bin/installdependencies.sh

# Add start script and make it executable
ADD scripts/start.sh start.sh
ADD scripts/detector.sh detector.sh
RUN chmod +x start.sh
RUN chmod +x detector.sh
# Copy ALL scripts make them executable
COPY scripts/* .
RUN chmod +x *.sh

# Set the user to "docker" so all subsequent commands are run as the docker user
USER docker
Expand Down
48 changes: 38 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,51 @@ docker compose up -d
- **LABELS** - Runner labels (comma separated). Uses `"docker-node,${os_name}-${architecture}"`
- **REUSE_EXISTING** - Re-use existing configuration. Defaults to `false`

> `REUSE_EXISTING` can come in handy when a container restarts due to a problem,
> or when a container is terminated without gracefully shutting down.
> [!NOTE]
> `REUSE_EXISTING` flag can be useful when a container restarts due to an issue or
> when a container is reused after being terminated without shutting down gracefully.
> <details>
> <summary><strong>More info</strong></summary>
>
> Following files/directories are created (commonly across `macOS`, `Linux` and `Windows` runners)
> only when the runner has been configured
> - `_work`
> - `_diag`
> - `.runner`
> - `.credentials`
> - `.credentials_rsaparams`
>
> So, a simple check on one or more of these files' presence should confirm if the runner has been configured already
>
> **Note:** Warnings like the ones below are common, and GitHub typically reconnects the runner automatically.
> ```text
> A session for this runner already exists.
> ```
> ```
> Runner connect error: The actions runner i-058175xh7908r2u46 already has an active session.. Retrying until reconnected.
> ```
> </details>
> [!WARNING]
Using this image **without** the env var `GIT_REPOSITORY` will create an organization level runner.
Using self-hosted runners in public repositories pose some considerable security threats.
> - [#self-hosted-runner-security]
> - [#restricting-the-use-of-self-hosted-runners]
> - [#configuring-required-approval-for-workflows-from-public-forks]
>
> **Author Note:** _Be mindful of the env vars you set when spinning up containers_
<details>
<summary><strong>Env vars for startup notifications</strong></summary>
<summary><strong>Env vars for notifications</strong></summary>
> This project supports [ntfy] and [telegram bot] for startup notifications.
> This project supports [ntfy] and [telegram bot] for startup/shutdown notifications.
**NTFY**
Choose ntfy setup instructions with [basic][ntfy-setup-basic] **OR** [authentication][ntfy-setup-auth] abilities
- **NTFY_USERNAME** - Ntfy username for authentication _(if topic is protected)_
- **NTFY_PASSWORD** - Ntfy password for authentication _(if topic is protected)_
- **NTFY_URL** - Ntfy endpoint for notifications.
- **NTFY_TOPIC** - Topic to which the notifications have to be sent.
- **NTFY_USERNAME** - Ntfy username for authentication _(if topic is protected)_
- **NTFY_PASSWORD** - Ntfy password for authentication _(if topic is protected)_
**Telegram**
Expand All @@ -63,16 +83,22 @@ Steps for telegram bot configuration
1. Use [BotFather] to create a telegram bot token
2. Send a test message to the Telegram bot you created
3. Use the URL https://api.telegram.org/bot{token}/getUpdates to get the Chat ID
- You can also use Thread ID to send notifications to a particular thread within a chat window
- You can also use Thread ID to send notifications to a particular thread within a group
```shell
export TELEGRAM_BOT_TOKEN="your-bot-token"
export CHAT_ID=$(curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" | jq -r '.result[0].message.chat.id')
export THREAD_ID=$(curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" | jq -r '.result[0]|.update_id')
```
- **TELEGRAM_BOT_TOKEN** - Telegram Bot token
- **TELEGRAM_CHAT_ID** - Chat ID to which the notifications have to be sent.
- **THREAD_ID** - Optional thread ID to send notifications to a specific thread.

> **Note:** To send notifications to threads, the bot should be added to a group with [Topics][telegram-topics] enabled.<br>
> Send a message to the bot in a group thread
> ```shell
> export THREAD_ID=$(curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" | jq -r '.result[0]|.update_id')
> ```
</details>
Expand Down Expand Up @@ -105,6 +131,8 @@ docker build --build-arg RUNNER_VERSION=$RUNNER_VERSION -t runner .
[ntfy-setup-basic]: https://docs.ntfy.sh/install/
[ntfy-setup-auth]: https://community.home-assistant.io/t/setting-up-private-and-secure-ntfy-messaging-for-ha-notifications/632952
[BotFather]: https://t.me/botfather
[telegram-topics]: https://telegram.org/blog/topics-in-groups-collectible-usernames
[telegram-threads]: https://core.telegram.org/api/threads

[#restricting-the-use-of-self-hosted-runners]: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#restricting-the-use-of-self-hosted-runners
[#self-hosted-runner-security]: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security
Expand Down
37 changes: 37 additions & 0 deletions scripts/config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

repo_level_runner() {
# https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-registration-token-for-a-repository
REG_TOKEN=$(curl -sX POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: Bearer ${GIT_TOKEN}" \
"https://api.github.com/repos/${GIT_OWNER}/${GIT_REPOSITORY}/actions/runners/registration-token" \
| jq .token --raw-output)
cd "/home/docker/actions-runner" || exit 1
./config.sh --unattended \
--work "${WORK_DIR}" \
--labels "${LABELS}" \
--token "${REG_TOKEN}" \
--name "${RUNNER_NAME}" \
--runnergroup "${RUNNER_GROUP}" \
--url "https://github.com/${GIT_OWNER}/${GIT_REPOSITORY}"
}

org_level_runner() {
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#restricting-the-use-of-self-hosted-runners
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security
# https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-registration-token-for-an-organization
REG_TOKEN=$(curl -sX POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: Bearer ${GIT_TOKEN}" \
"https://api.github.com/orgs/${GIT_OWNER}/actions/runners/registration-token" \
| jq .token --raw-output)
cd "/home/docker/actions-runner" || exit 1
./config.sh \
--work "${WORK_DIR}" \
--labels "${LABELS}" \
--token "${REG_TOKEN}" \
--name "${RUNNER_NAME}" \
--runnergroup "${RUNNER_GROUP}" \
--url "https://github.com/${GIT_OWNER}"
}
91 changes: 91 additions & 0 deletions scripts/notify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/bin/bash

NOTIFICATION_TITLE="GitHub Actions Runner - Docker Node"

ntfy_fn() {
# Send NTFY notification
body="$1"

if [[ -n "$NTFY_TOPIC" && -n "$NTFY_URL" ]]; then
# Remove trailing '/' if present
# https://github.com/binwiederhier/ntfy/issues/370
NTFY_URL=${NTFY_URL%/}
response=$(curl -s -o /tmp/ntfy -w "%{http_code}" -X POST \
-u "$NTFY_USERNAME:$NTFY_PASSWORD" \
-H "X-Title: ${NOTIFICATION_TITLE}" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "${body}" \
"$NTFY_URL/$NTFY_TOPIC")
status_code="${response: -3}"
if [ "$status_code" -eq 200 ]; then
log "Ntfy notification was successful"
elif [[ -f "/tmp/ntfy" ]]; then
log "Failed to send ntfy notification"
response_payload="$(cat /tmp/ntfy)"
reason=$(echo "$response_payload" | jq '.error')
# Output the extracted description or the full response if jq fails
if [ "$reason" != "null" ]; then
log "[$status_code]: $reason"
else
log "[$status_code]: $(cat /tmp/ntfy)"
fi
else
log "Failed to send ntfy notification - ${status_code}"
fi
rm -f /tmp/ntfy
else
log "Ntfy notifications is not setup"
fi
}

telegram_fn() {
# Send Telegram notification
body="$1"

if [[ -n "$TELEGRAM_BOT_TOKEN" && -n "$TELEGRAM_CHAT_ID" ]]; then
notification_preference=${DISABLE_TELEGRAM_NOTIFICATION:-false}

# Base JSON payload
message=$(printf "*%s*\n\n%s" "${NOTIFICATION_TITLE}" "${body}")
payload=$(jq -n \
--arg chat_id "$TELEGRAM_CHAT_ID" \
--arg text "$message" \
--arg parse_mode "markdown" \
--arg disable_notification "$notification_preference" \
'{
chat_id: $chat_id,
text: $text,
parse_mode: $parse_mode,
disable_notification: $disable_notification
}')

# Add 'message_thread_id' if TELEGRAM_THREAD_ID is available and not null
if [ -n "$TELEGRAM_THREAD_ID" ]; then
payload=$(echo "$payload" | jq --arg thread_id "$TELEGRAM_THREAD_ID" '. + {message_thread_id: $thread_id}')
fi

response=$(curl -s -o /tmp/telegram -w "%{http_code}" -X POST \
-H 'Content-Type: application/json' \
-d "$payload" \
"https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage")
status_code="${response: -3}"
if [ "$status_code" -eq 200 ]; then
log "Telegram notification was successful"
elif [[ -f "/tmp/telegram" ]]; then
log "Failed to send telegram notification"
response_payload="$(cat /tmp/telegram)"
reason=$(echo "$response_payload" | jq '.description')
# Output the extracted description or the full response if jq fails
if [ "$reason" != "null" ]; then
log "[$status_code]: $reason"
else
log "[$status_code]: $(cat /tmp/telegram)"
fi
else
log "Failed to send telegram notification - ${status_code}"
fi
rm -f /tmp/telegram
else
log "Telegram notifications is not setup"
fi
}
19 changes: 19 additions & 0 deletions scripts/squire.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
log() {
dt_stamp=$(date -u +"%Y-%m-%d %H:%M:%SZ")
echo "${dt_stamp}: $1"
}

instance_id() {
# Use randomly generated instance IDs (AWS format) as default runner names
letters=$(tr -dc '[:lower:]' < /dev/urandom | head -c 4)
digits=$(tr -dc '0-9' < /dev/urandom | head -c 12)
eid=$(echo "$letters$digits" | fold -w1 | shuf | tr -d '\n')
echo "i-0$eid"
}

cleanup() {
log "Removing runner..."
ntfy_fn "Removing runner: '${RUNNER_NAME}'"
telegram_fn "Removing runner: '${RUNNER_NAME}'"
./config.sh remove --token "${REG_TOKEN}"
}
Loading

0 comments on commit 2fd57c2

Please sign in to comment.