Skip to content

Commit

Permalink
Simplify and cleanup entry points and tests
Browse files Browse the repository at this point in the history
Pull Request: #7 (main)
  • Loading branch information
dimikot committed Mar 2, 2024
1 parent 740c9ac commit c856ecf
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 108 deletions.
15 changes: 6 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,19 @@ jobs:
uses: actions/checkout@v2
- name: Start test Docker containers
run: |
ssh-keygen -t ed25519 -qf /tmp/key -N ""
export CI_STORAGE_HOST_SSH_KEY="$(cat /tmp/key)"
set -o xtrace
cd docker
# Boot ci-storage-host container. It will have a default empty slot.
# Boot ci-storage-host container in background.
docker compose up ci-storage-host -d --build
# Now boot self-hosted-runner container. It will connect to
# ci-storage-host container and load the empty slot from there, then
# register a GitHub self-hosted runner and remain waiting for jobs.
# ci-storage-host container and load a test (non-existent) ci-storage
# slot from there, then register a GitHub self-hosted runner and
# remain waiting for jobs.
docker compose up self-hosted-runner --build
env:
GH_REPOSITORY: ${{ github.repository }}
GH_LABELS: ci-storage-test
GH_TOKEN: ${{ secrets.CI_PAT }}
GH_TOKEN: ${{ secrets.CI_PAT }}

# The test job with ci-storage-test tag which is initially queued, but then is
# picked up by the self-hosted-runner container booted in the previous job. In
Expand All @@ -80,6 +79,4 @@ jobs:
action: "store"
storage-host: "ci-storage-host"
- name: Kill self-hosted runner container
run: |
cd /home/ubuntu/actions-runner
kill -SIGINT $(cat runner.pid)
run: kill -SIGINT $(cat cd ~user/entrypoint.pid)
10 changes: 10 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"recommendations": [
"GitHub.vscode-github-actions",
"jeff-hykin.better-dockerfile-syntax",
"mads-hartmann.bash-ide-vscode",
"ms-python.black-formatter",
"ms-python.python",
"timonwong.shellcheck",
]
}
20 changes: 20 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "git grok: push local commits as individual PRs",
"detail": "Install git-grok first: https://github.com/dimikot/git-grok",
"type": "shell",
"command": "git grok",
"problemMatcher": [],
"hide": false
},
{
"label": "git rebase --interactive",
"detail": "Opens a UI for interactive rebase (install \"Git rebase shortcuts\" extension).",
"type": "shell",
"command": "GIT_EDITOR=\"code --wait\" git rebase -i",
"problemMatcher": []
}
]
}
3 changes: 1 addition & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ inputs:
description: "Remove slots created earlier than this many seconds ago. If not set, uses the ci-storage tool default 4 hours."
required: false
slot-id:
description: 'Id of the slot to store to or load from; use "*" to load a random most recent slot. If empty, uses "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" value.'
description: 'Id of the slot to store to or load from; use "*" to load a random most recent slot; use "?" to load a random most recent slot and skip if it does not exist. If empty, uses "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" value.'
required: false
local-dir:
description: 'Local directory path to store from or load to. If not set, uses "." (the current work directory).'
Expand All @@ -27,7 +27,6 @@ inputs:
required: false
verbose:
description: "If set, prints the list of transferred files."
type: boolean
required: false
runs:
using: "composite"
Expand Down
18 changes: 11 additions & 7 deletions ci-storage
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def main():
"--slot-id",
type=str,
required=True,
help='id of the slot to store to or load from; use "*" to load a random most recent slot',
help='id of the slot to store to or load from; use "*" to load a random most recent slot; use "?" to load a random most recent slot and skip if it does not exist',
)
parser.add_argument(
"--local-dir",
Expand Down Expand Up @@ -162,8 +162,8 @@ def action_store(
exclude: list[str],
verbose: bool,
):
if slot_id == "*":
raise UserException('slot_id="*" is not allowed for "store" action')
if slot_id == "*" or slot_id == "?":
raise UserException(f'slot_id="{slot_id}" is not allowed for "store" action')
slot_id = normalize_slot_id(slot_id)
slot_ids_and_ages = list_slots(storage_host=storage_host, storage_dir=storage_dir)
slot_id_recent = slot_ids_and_ages[0][0] if len(slot_ids_and_ages) else None
Expand Down Expand Up @@ -208,14 +208,18 @@ def action_load(
exclude: list[str],
verbose: bool,
):
if slot_id == "*":
if slot_id == "*" or slot_id == "?":
slot_ids_and_ages = list_slots(
storage_host=storage_host, storage_dir=storage_dir
)
if len(slot_ids_and_ages) == 0:
raise UserException(
'to use slot_id="*", there must be at least one slot in the storage.'
)
if slot_id == "?":
print(f'No slots found, and slot-id="{slot_id}", so skipping.')
return
else:
raise UserException(
f'to use slot-id="{slot_id}", there must be at least one slot in the storage.'
)
slot_id = slot_ids_and_ages[0][0]
else:
slot_id = normalize_slot_id(slot_id)
Expand Down
11 changes: 11 additions & 0 deletions docker/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This key (as well as docker-compose.yml) is only used in tests, so it's safe
# to have it here.
CI_STORAGE_HOST_PRIVATE_KEY_TEST_ONLY="-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBZgbuAsWHfeYshNJacifV30KxJVFKr4/B4WnvxO8x2jAAAAKgm2KyUJtis
lAAAAAtzc2gtZWQyNTUxOQAAACBZgbuAsWHfeYshNJacifV30KxJVFKr4/B4WnvxO8x2jA
AAAECRcPB4jRqJEgNBvFPA6+k5HPT5/ZbXnD2KUyE+oJFfA1mBu4CxYd95iyE0lpyJ9XfQ
rElUUqvj8Hhae/E7zHaMAAAAHmRtaXRyeUBEbWl0cnktTWFjQm9vay1NMS5sb2NhbAECAw
QFBgc=
-----END OPENSSH PRIVATE KEY-----"
CI_STORAGE_HOST_PUBLIC_KEY_TEST_ONLY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFmBu4CxYd95iyE0lpyJ9XfQrElUUqvj8Hhae/E7zHaM"
17 changes: 7 additions & 10 deletions docker/ci-storage-host/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@ ARG BASE_IMAGE="ubuntu:22.04"

FROM $BASE_IMAGE

ENV GH_REPOSITORY=""
ENV CI_STORAGE_HOST_SSH_KEY=""
ENV CI_STORAGE_HOST_PUBLIC_KEY=""

ENV DEBIAN_FRONTEND=noninteractive
RUN true \
&& apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends \
awscli rsync openssh-server \
mc gcc git curl wget pv psmisc unzip vim nano telnet net-tools bash-completion \
libssl-dev apt-transport-https build-essential ca-certificates locales pkg-config \
openssh-server \
jq gh rsync python3 mc git curl wget pv psmisc unzip vim nano telnet net-tools apt-transport-https ca-certificates locales \
&& sed -i -e "s|#PermitRootLogin.*|PermitRootLogin no|" /etc/ssh/sshd_config \
&& useradd -m ubuntu \
&& mkdir -p /home/ubuntu/.ssh \
&& chown -R ubuntu:ubuntu /home/ubuntu/.ssh \
&& chmod 700 /home/ubuntu/.ssh
&& useradd -m user \
&& mkdir -p ~user/.ssh ~user/ci-storage \
&& chown -R user:user ~user \
&& chmod 700 ~user/.ssh

COPY --chmod=755 entrypoint.sh /

Expand Down
9 changes: 9 additions & 0 deletions docker/ci-storage-host/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# A Simple Container with SSH Server

Build an image from this Dockerfile to launch a simple SSH server with rsync.

- Pre-creates /home/user/ci-storage directory.
- Copies public key in CI_STORAGE_HOST_PUBLIC_KEY to user's authorized_keys.

One ci-storage-host contain may serve multiple GitHub repositories. Each of them
will have own directory in /home/user/ci-storage (managed by ci-storage tool).
24 changes: 8 additions & 16 deletions docker/ci-storage-host/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
#!/bin/bash
#
# A container which holds ci-storage saved slots. Its ~ubuntu/ci-storage should
# be persistent across container restarts.
# A container which holds ci-storage saved slots. Its ~user/ci-storage should be
# persistent across container restarts (e.g. point to an AWS EBS volume).
#
set -u -e

if [ "${CI_STORAGE_HOST_SSH_KEY:-}" = "" ]; then
echo "CI_STORAGE_HOST_SSH_KEY is not set, exiting..."
if [[ "${CI_STORAGE_HOST_PUBLIC_KEY:=''}" == "" ]]; then
echo "CI_STORAGE_HOST_PUBLIC_KEY must be set to a valid SSH public key."
exit 1
fi

cd /home/ubuntu
authorized_keys=~user/.ssh/authorized_keys

echo "$CI_STORAGE_HOST_SSH_KEY" > .ssh/id_ed25519
chmod 600 .ssh/id_ed25519
ssh-keygen -f .ssh/id_ed25519 -y > .ssh/authorized_keys
chown -R ubuntu:ubuntu .ssh

# This code is for simplifying the CI tests and allow self-hosted-runner to boot
# in docker-compose. In real world, the 1st slot created should contain the real
# files (e.g. a cloned git repo).
if [ ! -e ci-storage -a "${GH_REPOSITORY:-}" != "" ]; then
mkdir -p ci-storage/$GH_REPOSITORY/initial
chown -R ubuntu:ubuntu ci-storage
if [[ ! -f $authorized_keys ]] || ! grep -qF "$CI_STORAGE_HOST_PUBLIC_KEY" $authorized_keys; then
echo "$CI_STORAGE_HOST_PUBLIC_KEY" >> $authorized_keys
chown user:user $authorized_keys
fi

mkdir -p /var/run/sshd
Expand Down
6 changes: 6 additions & 0 deletions docker/compose-up.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
set -e

echo "Booting containters on the local laptop for debugging purposes..."

GH_REPOSITORY=$(gh repo view --json owner,name -q '.owner.login + "/" + .name') GH_TOKEN=$(gh auth token) docker compose up --build "$@"
30 changes: 30 additions & 0 deletions docker/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: "3.4"
services:
ci-storage-host:
build:
context: ci-storage-host
dockerfile: Dockerfile
healthcheck:
test: ["CMD", "bash", "-c", "netstat -ltn | grep -c :22"]
interval: 1s
timeout: 3s
retries: 10
ports:
- 10022:22
environment:
- CI_STORAGE_HOST_PUBLIC_KEY=${CI_STORAGE_HOST_PUBLIC_KEY_TEST_ONLY?}
self-hosted-runner:
build:
context: self-hosted-runner
additional_contexts:
root: ..
dockerfile: Dockerfile
depends_on:
ci-storage-host:
condition: service_healthy
environment:
- GH_REPOSITORY=${GH_REPOSITORY:-dimikot/ci-storage}
- GH_LABELS=${GH_LABELS:-ci-storage}
- GH_TOKEN
- CI_STORAGE_HOST=${CI_STORAGE_HOST:-ci-storage-host}
- CI_STORAGE_HOST_PRIVATE_KEY=${CI_STORAGE_HOST_PRIVATE_KEY_TEST_ONLY?}
23 changes: 0 additions & 23 deletions docker/docker-compose.yml

This file was deleted.

35 changes: 16 additions & 19 deletions docker/self-hosted-runner/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ARG BASE_IMAGE="ubuntu:22.04"

FROM $BASE_IMAGE

ARG RUNNER_VERSION="2.314.1"
Expand All @@ -8,24 +7,22 @@ ENV GH_REPOSITORY=""
ENV GH_LABELS=""
ENV GH_TOKEN=""
ENV CI_STORAGE_HOST=""
ENV CI_STORAGE_HOST_SSH_KEY=""
ENV CI_STORAGE_HOST_PRIVATE_KEY=""

ENV DEBIAN_FRONTEND=noninteractive
RUN true \
&& apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends \
awscli jq gh rsync openssh-client \
mc gcc git curl wget pv psmisc unzip vim nano telnet net-tools bash-completion \
libssl-dev apt-transport-https build-essential ca-certificates locales pkg-config \
&& useradd -m ubuntu
openssh-client \
jq gh rsync python3 mc git curl wget pv psmisc unzip vim nano telnet net-tools apt-transport-https ca-certificates locales \
&& useradd -m user

USER ubuntu
USER user
RUN true \
&& mkdir -p /home/ubuntu/.ssh \
&& chmod 700 /home/ubuntu/.ssh \
&& mkdir /home/ubuntu/actions-runner \
&& cd /home/ubuntu/actions-runner \
&& mkdir -p ~user/.ssh \
&& chmod 700 ~user/.ssh \
&& mkdir ~user/actions-runner \
&& cd ~user/actions-runner \
&& arch=$(dpkg --print-architecture) \
&& case "$arch" in \
x86_64|amd64) arch=linux-x64 ;; \
Expand All @@ -35,19 +32,19 @@ RUN true \
&& curl --no-progress-meter -L https://github.com/actions/runner/releases/download/v$RUNNER_VERSION/actions-runner-$arch-$RUNNER_VERSION.tar.gz | tar xz

USER root
RUN /home/ubuntu/actions-runner/bin/installdependencies.sh \
apt-get autoremove \
RUN ~user/actions-runner/bin/installdependencies.sh \
&& apt-get autoremove \
&& apt-get clean \
&& apt-get autoclean \
&& rm -rf /var/lib/apt/lists/*

USER ubuntu
COPY --chmod=755 --chown=ubuntu:ubuntu entrypoint.sh /home/ubuntu
USER user
COPY --chmod=755 --chown=user:user entrypoint.sh /home/user
COPY --chmod=755 --from=root ci-storage /usr/bin/ci-storage

WORKDIR /home/ubuntu
WORKDIR /home/user
ENTRYPOINT ["./entrypoint.sh"]

# If overridden in the derived image, evals this as "ubuntu" user as a shell
# script after config.sh, but before run.sh.
# If overridden in the derived image, evals this as a shell script after
# config.sh, but before run.sh.
CMD []
4 changes: 4 additions & 0 deletions docker/self-hosted-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ self-hosted runners as you want. An example scenario:
artifacts of someone else. If the job then uses ci-storage GitHub action to
restore the files from a slot, it will be very quick, because most of the
files are already there.

The container in this Dockerfile is serves only one particular GitHub repository
(controlled by GH_REPOSITORY environment variable at boot time). To serve
different repositories, boot different containers.
Loading

0 comments on commit c856ecf

Please sign in to comment.