-
Notifications
You must be signed in to change notification settings - Fork 6
PoC of ephemeral Forgejo runner(s) #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
theseal
wants to merge
57
commits into
testing
Choose a base branch
from
jocar-forgejo-runner
base: testing
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 54 commits
Commits
Show all changes
57 commits
Select commit
Hold shift + click to select a range
2311780
Gather forgejo classes together
theseal 6ad67fc
Initial commit
theseal 0dce843
Syntax error
theseal 0d5e709
Must be a file
theseal dcfe50f
Collect everything in /opt
theseal e0a75f7
Establish trust
theseal 2817eca
Puppet-lint
theseal 9096236
Wrong target
theseal 0d19d31
Download the image in where we will run runner
theseal 62296ef
Wrong path
theseal 2013a27
No checksum available
theseal f9150a7
Verify image
theseal af921fc
Verify image if changed
theseal 14989b0
Variables in command
theseal eee10cb
Signture as well
theseal 83f761a
Simply
theseal 1d99ae6
Unpack
theseal a2557b3
Errors
theseal 0d28f5b
First attempt to create user
theseal e405939
Wrong variable
theseal b949e68
Create homes
theseal 88d928a
Wrapper to execute runner
theseal 6080752
Syntax error
theseal 25a4180
Declare before use
theseal 04f8e4c
the "runner"
theseal c656c0d
podman needs virtiofsd in path
theseal c87345d
Run a global script instead of personal
theseal d54916a
Syntax error
theseal b5d3dfd
There is something wrong with podmans mounts
theseal 65db749
Something is broken with podmans volume mount
theseal bdf423a
Script is run by root
theseal 8bad4e8
Run with systemd
theseal 152a556
This is a template
theseal 8e91de2
New syntax and image in modern podman
theseal c023f18
Depends
theseal ccd2e59
Moar depends
theseal 8808a04
Config for runner
theseal 46770d1
Full username
theseal fa9ed06
Wrong owner
theseal 9ec904a
Get secret from hiera
theseal 3f4133a
Registrer if not already
theseal fda21c0
Syntax error
theseal a369168
Syntax error
theseal 3b65c91
Fetch from repo
theseal eeb0ed3
Use pre existing config
theseal 0456386
Syntax error
theseal ec073fc
Clean up non clean exits
theseal 76975af
Readability
theseal 5c8273b
Enable each runner
theseal cee2165
Depend
theseal c0db19c
Forgot to add the code
theseal 9bdb83a
Podman needs the proxy
theseal 528616e
Syntax error
theseal c9eb416
Should not be executable
theseal ce89348
Linting
theseal c9a3561
Moar lints
theseal c1c7a28
Enable ipv6 for containers and let them run as privileged as we isola…
mikaelfrykholm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| [Unit] | ||
| Description=forgejo-runner as %i | ||
| After=network.target | ||
|
|
||
| [Service] | ||
| Type=simple | ||
| User=%i | ||
| Group=%i | ||
| TimeoutStartSec=0 | ||
| TimeoutStopSec=30 | ||
| Restart=always | ||
| RestartSec=10 | ||
| ExecStart=/opt/forgejo-runner/libexec/runner-systemd-wrapper | ||
| Restart=on-failure | ||
|
|
||
| [Install] | ||
| WantedBy=multi-user.target |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # A class to install and manage Forgejo runner(s) | ||
| class sunet::forgejo::runner ( | ||
| String $version = '11.1.2', | ||
| String $version_sha256sum = '6442d46db2434a227e567a116c379d0eddbe9e7a3f522596b25d31979fd59c8d', | ||
| String $machine_image = 'quay.io/podman/machine-os:5.4', | ||
| Integer $runners = 4, | ||
| String $forgejo_instance = "platform.sunet.se", | ||
| ) { | ||
|
|
||
| include sunet::packages::podman | ||
| include sunet::packages::virtiofsd | ||
| include sunet::packages::qemu_system_x86 | ||
| include sunet::packages::gvproxy | ||
|
|
||
| file {'/usr/lib/podman/gvproxy': | ||
| ensure => 'link', | ||
| target => '/usr/bin/gvproxy' | ||
| } | ||
|
|
||
| $registration_token = lookup('forgejo_registration_token', undef, undef, 'NOT_SET_IN_HIERA'); | ||
|
|
||
| file {'/opt/forgejo-runner': | ||
| ensure => 'directory', | ||
|
||
| } | ||
| file {'/opt/forgejo-runner/bin': | ||
| ensure => 'directory', | ||
|
||
| } | ||
|
|
||
| file {'/opt/forgejo-runner/images': | ||
| ensure => 'directory', | ||
|
||
| } | ||
|
|
||
| file {'/opt/forgejo-runner/libexec': | ||
| ensure => 'directory', | ||
|
||
| } | ||
|
|
||
| file { '/opt/forgejo-runner/bin/forgejo-runner': | ||
| ensure => 'file', | ||
| source => "https://code.forgejo.org/forgejo/runner/releases/download/v${version}/forgejo-runner-${version}-linux-amd64", | ||
| checksum => 'sha256', | ||
| checksum_value => $version_sha256sum, | ||
| mode => '0755', | ||
| } | ||
|
|
||
| file { '/opt/forgejo-runner/libexec/runner-systemd-wrapper': | ||
| ensure => 'file', | ||
|
||
| content => template('sunet/forgejo/runner-systemd-wrapper.erb'), | ||
| mode => '0755', | ||
|
||
| } | ||
|
|
||
| file { '/opt/forgejo-runner/libexec/runner-wrapper': | ||
| ensure => 'file', | ||
| content => template('sunet/forgejo/runner-wrapper.erb'), | ||
| mode => '0755', | ||
| } | ||
|
|
||
| file { '/etc/systemd/system/[email protected]': | ||
| ensure => 'file', | ||
| content => file('sunet/forgejo/forgejo-runner.service'), | ||
| mode => '0644', | ||
| } | ||
|
|
||
| range(0, $runners - 1).each |$runner|{ | ||
| $user = "runner-${runner}" | ||
|
|
||
| user { $user: | ||
| ensure => 'present', | ||
| groups => ['kvm'], | ||
| home => "/home/${user}", | ||
| managehome => true, | ||
| notify => Exec["linger_user_${runner}"] | ||
| } | ||
|
|
||
| exec { "linger_user_${runner}": | ||
| command => "/usr/bin/loginctl enable-linger ${user}", | ||
| refreshonly => true, | ||
| } | ||
|
|
||
| file { "/home/${user}/runner.config": | ||
| ensure => 'file', | ||
| content => template('sunet/forgejo/runner.config.erb'), | ||
| mode => '0700', | ||
| owner => $user, | ||
| } | ||
|
|
||
| service { "sunet-forgejo-runner@${user}": | ||
| ensure => 'running', | ||
| enable => true, | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # gvproxy | ||
| class sunet::packages::gvproxy { | ||
| package { 'gvproxy': ensure => installed } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,4 @@ | ||
| # Install podman from kubic | ||
| class sunet::packages::podman( | ||
| ) { | ||
| include sunet::packages::curl | ||
| include sunet::packages::gpg | ||
| include stdlib | ||
|
|
||
| if $facts['os']['name'] == 'Ubuntu' { | ||
| $reponame = 'xUbuntu' | ||
| } else { | ||
| $reponame = $facts['os']['name'] | ||
| } | ||
| exec { 'podman_repo_key': | ||
| creates => '/etc/apt/trusted.gpg.d/libcontainers.gpg', | ||
| command => "curl https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/${reponame}_${facts['os']['release']['major']}/Release.key | gpg --dearmor > /etc/apt/trusted.gpg.d/libcontainers.gpg", | ||
| unless => 'test -f /etc/apt/trusted.gpg.d/libcontainers.gpg', | ||
| } | ||
| -> file { 'podman_repo_file': | ||
| ensure => file, | ||
| name => '/etc/apt/sources.list.d/libcontainers.list', | ||
| content => "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/${reponame}_${facts['os']['release']['major']}/ /\n", | ||
| } | ||
| -> exec { 'podman_update': | ||
| command => 'apt update', | ||
| unless => 'dpkg -l podman' | ||
| } | ||
| -> package { 'podman': | ||
| ensure => latest | ||
| } | ||
| # podman | ||
| class sunet::packages::podman { | ||
| package { 'podman': ensure => installed } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # qemu-system-x86 | ||
| class sunet::packages::qemu_system_x86 { | ||
| package { 'qemu-system-x86': ensure => installed } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # virtiofsd | ||
| class sunet::packages::virtiofsd { | ||
| package { 'virtiofsd': ensure => installed } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| XDG_RUNTIME_DIR=/run/user/$(id -u) | ||
| export XDG_RUNTIME_DIR | ||
|
|
||
| PATH="${PATH}:/usr/libexec/" | ||
|
|
||
| cp /opt/forgejo-runner/libexec/runner-wrapper ${HOME}/ | ||
| cp /opt/forgejo-runner/bin/forgejo-runner ${HOME}/ | ||
|
|
||
|
|
||
| if [ ! -f "/home/$(whoami)/.runner" ]; then | ||
| # Registration needed | ||
| /opt/forgejo-runner/bin/forgejo-runner --config "/home/$(whoami)/runner.config" register --no-interactive --instance "https://<%= @forgejo_instance %>" --token "<%= @registration_token %>" --name "$(hostname -f):$(whoami)" | ||
| fi | ||
|
|
||
| podman machine rm -f | ||
|
|
||
| while true; do | ||
|
|
||
| podman machine init --image "docker://<%= @machine_image %>" --memory 4096 --rootful --now | ||
| podman machine ssh "/home/$(whoami)/runner-wrapper $(whoami)" | ||
| podman machine rm -f | ||
|
|
||
| sleep 1 | ||
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| while true; do | ||
| /home/$1/forgejo-runner --config /home/$1/runner.config one-job 2>&1 | sed '/^Error: could not fetch task/,$b;$q1' | ||
|
|
||
| # Match for Error: could not fetch task in sed | ||
| # aka no jobs to fetch | ||
| # Try again lateer | ||
| if [ "${PIPESTATUS[1]}" -eq "0" ]; then | ||
| sleep 5 | ||
| continue | ||
| else | ||
| break | ||
| fi | ||
| done | ||
|
|
||
| echo "Exiting to destroy VM - BOOM" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| # Example configuration file, it's safe to copy this as the default config file without any modification. | ||
|
|
||
| # You don't have to copy this file to your instance, | ||
| # just run `forgejo-runner generate-config > config.yaml` to generate a config file. | ||
|
|
||
| # | ||
| # The value of level or job_level can be trace, debug, info, warn, error or fatal | ||
| # | ||
| log: | ||
| # | ||
| # What is displayed in the output of the runner process but not sent | ||
| # to the Forgejo instance. | ||
| # | ||
| level: info | ||
| # | ||
| # What is sent to the Forgejo instance and therefore | ||
| # visible in the web UI for a given job. | ||
| # | ||
| job_level: info | ||
|
|
||
| runner: | ||
| # Where to store the registration result. | ||
| file: /home/<%= @user %>/.runner | ||
| # Execute how many tasks concurrently at the same time. | ||
| capacity: 1 | ||
| # Extra environment variables to run jobs. | ||
| envs: | ||
| A_TEST_ENV_NAME_1: a_test_env_value_1 | ||
| A_TEST_ENV_NAME_2: a_test_env_value_2 | ||
| # Extra environment variables to run jobs from a file. | ||
| # It will be ignored if it's empty or the file doesn't exist. | ||
| env_file: .env | ||
| # The timeout for a job to be finished. | ||
| # Please note that the Forgejo instance also has a timeout (3h by default) for the job. | ||
| # So the job could be stopped by the Forgejo instance if it's timeout is shorter than this. | ||
| timeout: 3h | ||
| # The timeout for the runner to wait for running jobs to finish when | ||
| # shutting down because a TERM or INT signal has been received. Any | ||
| # running jobs that haven't finished after this timeout will be | ||
| # cancelled. | ||
| # If unset or zero the jobs will be cancelled immediately. | ||
| shutdown_timeout: 3h | ||
| # Whether skip verifying the TLS certificate of the instance. | ||
| insecure: false | ||
| # The timeout for fetching the job from the Forgejo instance. | ||
| fetch_timeout: 5s | ||
| # The interval for fetching the job from the Forgejo instance. | ||
| fetch_interval: 2s | ||
| # The interval for reporting the job status and logs to the Forgejo instance. | ||
| report_interval: 1s | ||
| # The labels of a runner are used to determine which jobs the runner can run, and how to run them. | ||
| # Like: ["macos-arm64:host", "ubuntu-latest:docker://node:20-bookworm", "ubuntu-22.04:docker://node:20-bookworm"] | ||
| # If it's empty when registering, it will ask for inputting labels. | ||
| # If it's empty when executing the `daemon`, it will use labels in the `.runner` file. | ||
| labels: [] | ||
|
|
||
| cache: | ||
| # | ||
| # When enabled, workflows will be given the ACTIONS_CACHE_URL environment variable | ||
| # used by the https://code.forgejo.org/actions/cache action. The server at this | ||
| # URL must implement a compliant REST API and it must also be reachable from | ||
| # the container or host running the workflows. | ||
| # | ||
| # See also https://forgejo.org/docs/next/user/actions/advanced-features/#cache | ||
| # | ||
| # When it is not enabled, none of the following options apply. | ||
| # | ||
| # It works as follows: | ||
| # | ||
| # - the workflow is given a one time use ACTIONS_CACHE_URL | ||
| # - a cache proxy listens to ACTIONS_CACHE_URL | ||
| # - the cache proxy securely communicates with the cache server using | ||
| # a shared secret | ||
| # | ||
| enabled: true | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # Only used for the internal cache server. | ||
| # | ||
| # If external_server is not set, the Forgejo runner will spawn a | ||
| # cache server that will be used by the cache proxy. | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # The port bound by the internal cache server. | ||
| # 0 means to use a random available port. | ||
| # | ||
| port: 0 | ||
| # | ||
| # The directory to store the cache data. | ||
| # | ||
| # If empty, the cache data will be stored in $HOME/.cache/actcache. | ||
| # | ||
| dir: "" | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # Only used for the external cache server. | ||
| # | ||
| # If external_server is set, the internal cache server is not | ||
| # spawned. | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # The URL of the cache server. The URL should generally end with | ||
| # "/". The cache proxy will forward requests to the external | ||
| # server. The requests are authenticated with the "secret" that is | ||
| # shared with the external server. | ||
| # | ||
| external_server: "" | ||
| # | ||
| # The shared cache secret used to secure the communications between | ||
| # the cache proxy and the cache server. | ||
| # | ||
| # If empty, it will be generated to a new secret automatically when | ||
| # the server starts and it will stay the same until it restarts. | ||
| # | ||
| secret: "" | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # Common to the internal and external cache server | ||
| # | ||
| ####################################################################### | ||
| # | ||
| # The IP or hostname (195.84.20.30 or example.com) to use when constructing | ||
| # ACTIONS_CACHE_URL which is the URL of the cache proxy. | ||
| # | ||
| # If empty it will be detected automatically. | ||
| # | ||
| # If the containers or host running the workflows reside on a | ||
| # different network than the Forgejo runner (for instance when the | ||
| # docker server used to create containers is not running on the same | ||
| # host as the Forgejo runner), it may be impossible to figure that | ||
| # out automatically. In that case you can specify which IP or | ||
| # hostname to use to reach the internal cache server created by the | ||
| # Forgejo runner. | ||
| # | ||
| host: "" | ||
| # | ||
| # The port bound by the internal cache proxy. | ||
| # 0 means to use a random available port. | ||
| # | ||
| proxy_port: 0 | ||
| # | ||
| # Overrides the ACTIONS_CACHE_URL variable passed to workflow | ||
| # containers. The URL should generally not end with "/". This should only | ||
| # be used if the runner host is not reachable from the workflow containers, | ||
| # and requires further setup. | ||
| # | ||
| actions_cache_url_override: "" | ||
|
|
||
| container: | ||
| # Specifies the network to which the container will connect. | ||
| # Could be host, bridge or the name of a custom network. | ||
| # If it's empty, create a network automatically. | ||
| network: "" | ||
| # Whether to create networks with IPv6 enabled. Requires the Docker daemon to be set up accordingly. | ||
| # Only takes effect if "network" is set to "". | ||
| enable_ipv6: false | ||
| # Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker). | ||
| privileged: false | ||
| # And other options to be used when the container is started (eg, --volume /etc/ssl/certs:/etc/ssl/certs:ro). | ||
| options: | ||
| # The parent directory of a job's working directory. | ||
| # If it's empty, /workspace will be used. | ||
| workdir_parent: | ||
| # Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob | ||
| # You can specify multiple volumes. If the sequence is empty, no volumes can be mounted. | ||
| # For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to: | ||
| # valid_volumes: | ||
| # - data | ||
| # - /etc/ssl/certs | ||
| # If you want to allow any volume, please use the following configuration: | ||
| # valid_volumes: | ||
| # - '**' | ||
| valid_volumes: [] | ||
| # overrides the docker client host with the specified one. | ||
| # If "-" or "", an available docker host will automatically be found. | ||
| # If "automount", an available docker host will automatically be found and mounted in the job container (e.g. /var/run/docker.sock). | ||
| # Otherwise the specified docker host will be used and an error will be returned if it doesn't work. | ||
| docker_host: "-" | ||
| # Pull docker image(s) even if already present | ||
| force_pull: false | ||
| # Rebuild local docker image(s) even if already present | ||
| force_rebuild: false | ||
|
|
||
| host: | ||
| # The parent directory of a job's working directory. | ||
| # If it's empty, $HOME/.cache/act/ will be used. | ||
| workdir_parent: |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.