-
Notifications
You must be signed in to change notification settings - Fork 29
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
Gitea support #323
Comments
Hi @hulto! As long as Gitea/Forgejo supports:
It should be possible. However, I think there is an inherent danger in trying to support 2 different forges in the same project, as they may deviate significantly in the future and it may become cumbersome or downright impossible to consolidate. It may be wise to attempt to rearchitect parts of GARM and split off the bits that deal with the interaction between GARM and the forge. Similar to how providers work. But that would be a huge undertaking. In the short term, if gitea has the above mentioned features, an attempt could be made to support it, if you have the time. Up to this point the focus has been to support GitHub and GHES. So the code mostly revolves around that assumption. But I think some thin abstractions could make gitea fit. My experience with gitea is limited, so I am not sure how much I could help, but if I can, I will. If you want to tackle this, I suggest creating a proof of concept, hacked with an axe, just to see if it's feasible. Something that won't take months of your time, just to find that we can't merge it. If having the two forges coexist does not seem possible, another option would be to fork GARM, yank out github and replace it with gitea. The we can merge back if/when the architecture of GARM permits pluggable forges, as we could then separately maintain plugins for gitea, github, etc. So, plenty of options 😊. |
I got so far with gitea + garm that the jobs are listed. By patching random stuff on both gitea and garm.
My problems are dropped error messages due to security.
Does garm only try to create runners if it could fetch runner installation packages?
|
Adding Gitea will be a bit more involved. There are a few assumptions in GARM that are related to GitHub. Each entity (Repo, Org, Enterprise) has a "pool manager" (needs to be reworked). That pool manager makes sure that the runners in each pool are properly created, deleted, etc. To ensure that GARM itselt has valid credentials to manage resources inside an entity, we periodically fetch the tools. We need them anyway, and in some cases, tools have a bearer token we need to ass to be able to download them (GHES). So checking for tools has a dual purpose:
For Gitea we don't have enterprises, which is fine. But if Gitea doesn't have "organizations", only repos and global, we need to create a new entity type. We also need to determine how webhooks work in Gitea. For example, in GitHub we can have an enterprise which has multiple orgs which in turn have multiple repos. I can install GARM at all 3 levels. If we have repo "testrepo" in org "testorg" which is part of "testenterprise" and I have GARM installed on all 3 levels, then whenever "testrepo" triggers a workflow, all 3 will send a webhook to GARM for the same job. Does Gitea have a similar behavior? If so, we need a way to determine who triggered that webhook, so we know which pools are entitled to react and create a runner. To get this to work we will need to:
There are probably more points to consider, but if we are to add Gitea support, I need to cleanup the code a bit and remove some assumptions that are tightly coupled to GitHub. I would like to do this anyway, because I want us to be able to support Gitea as well as Forgejo. Porentially others in the future. It might take a while though. In the meantime if you'd like to create a PoC, do not let me discourage you 🙂 . |
Gitea has
For me this is only now this missing header then Gitea is able to use the GitHub code of garm garm/apiserver/controllers/controllers.go Line 108 in 99f5660
I hardcoded repository in the POC.
Not needed at first, I used PAT like GitHub. Gitea does it very good to behave like the GitHub Rest Api. Oidc etc. are enhancements. e.g. the runner registration token retrieval is 100% the same if the GHES config does not append
Currently no. At first I just thought this is straight forward (by just needed to provide a custom runner setup template), but yes this is sightly more complex, I come back to this topic in March. This seems to be a used endpoint as well DeleteRunner not available as well |
Yes it really blocked progress, so the lxd pluginhas created runners for me by just returning the json from GitHub docs from Gitea for runner downloads. (at least until this feature is replicated, could also be skipped in a garm POC).
I omited the code I used, so ping me if you want the information. Added Gitea as repository level GHES instance. Now I'am at step adding an extra spec to download and setup act_runner instead of GitHub's runner (while I have a way to proxy GitHub runners to gitea e.g. binary compatible, this is not my goal right now) For arm64 systems only.... due to act_runner url
Debugging tips for the runner setup of the lxd garm backend would help me a lot. runnerinstalltemplate gitea prototype label For arm64 systems only.... due to act_runner url #!/bin/bash
set -e
set -o pipefail
{{- if .EnableBootDebug }}
set -x
{{- end }}
CALLBACK_URL="{{ .CallbackURL }}"
METADATA_URL="{{ .MetadataURL }}"
BEARER_TOKEN="{{ .CallbackToken }}"
RUN_HOME="/home/{{ .RunnerUsername }}/actions-runner"
if [ -z "$METADATA_URL" ];then
echo "no token is available and METADATA_URL is not set"
exit 1
fi
function call() {
PAYLOAD="$1"
[[ $CALLBACK_URL =~ ^(.*)/status(/)?$ ]] || CALLBACK_URL="${CALLBACK_URL}/status"
curl --retry 5 --retry-delay 5 --retry-connrefused --fail -s -X POST -d "${PAYLOAD}" -H 'Accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" "${CALLBACK_URL}" || echo "failed to call home: exit code ($?)"
}
function systemInfo() {
if [ -f "/etc/os-release" ];then
. /etc/os-release
fi
OS_NAME=${NAME:-""}
OS_VERSION=${VERSION_ID:-""}
AGENT_ID=${1:-null}
# strip status from the callback url
[[ $CALLBACK_URL =~ ^(.*)/status(/)?$ ]] && CALLBACK_URL="${BASH_REMATCH[1]}" || true
SYSINFO_URL="${CALLBACK_URL}/system-info/"
PAYLOAD="{\"os_name\": \"$OS_NAME\", \"os_version\": \"$OS_VERSION\", \"agent_id\": $AGENT_ID}"
curl --retry 5 --retry-delay 5 --retry-connrefused --fail -s -X POST -d "${PAYLOAD}" -H 'Accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" "${SYSINFO_URL}" || true
}
function sendStatus() {
MSG="$1"
call "{\"status\": \"installing\", \"message\": \"$MSG\"}"
}
function success() {
MSG="$1"
ID=${2:-null}
call "{\"status\": \"idle\", \"message\": \"$MSG\", \"agent_id\": $ID}"
}
function fail() {
MSG="$1"
call "{\"status\": \"failed\", \"message\": \"$MSG\"}"
exit 1
}
function downloadAndExtractRunner() {
sendStatus "downloading tools from https://dl.gitea.com/act_runner/0.2.11/act_runner-0.2.11-linux-arm64"
mkdir -p "$RUN_HOME" || fail "failed to create actions-runner folder"
curl --retry 5 --retry-delay 5 --retry-connrefused --fail -L -o "$RUN_HOME/act_runner" "https://dl.gitea.com/act_runner/0.2.11/act_runner-0.2.11-linux-arm64" || fail "failed to download tools"
sudo chown {{ .RunnerUsername }}:{{ .RunnerGroup }} -R /home/{{ .RunnerUsername }} || fail "failed to change owner"
sudo chmod +x "$RUN_HOME/act_runner" || fail "failed to change permissions"
sudo tee "$RUN_HOME/act_runner.service" <<EOF
[Unit]
Description=act_runner
After=network.target
[Service]
User={{ .RunnerUsername }}
Environment=HOME=/home/{{ .RunnerUsername }}
ExecStart=$RUN_HOME/act_runner daemon
WorkingDirectory=$RUN_HOME
KillMode=process
KillSignal=SIGINT
TimeoutStopSec=5min
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable $RUN_HOME/act_runner.service
}
if [ ! -d "$RUN_HOME" ];then
downloadAndExtractRunner
cd "$RUN_HOME"
else
sendStatus "using cached runner found in $RUN_HOME"
cd "$RUN_HOME"
fi
sendStatus "configuring runner"
{{- if .UseJITConfig }}
{{- else}}
GITHUB_TOKEN=$(curl --retry 5 --retry-delay 5 --retry-connrefused --fail -s -X GET -H 'Accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" "${METADATA_URL}/runner-registration-token/")
set +e
attempt=1
while true; do
ERROUT=$(mktemp)
{{- if .GitHubRunnerGroup }}
{{- else}}
# --ephemeral once supported
# "{{ .RunnerLabels }}" once `:` supported
./act_runner register --no-interactive --instance "$(echo "{{ .RepoURL }}" | cut -d'/' -f1-3)" --token "$GITHUB_TOKEN" --name "{{ .RunnerName }}" --labels "ubuntu,generic" 2>$ERROUT
{{- end}}
if [ $? -eq 0 ]; then
rm $ERROUT || true
sendStatus "runner successfully configured after $attempt attempt(s)"
break
fi
LAST_ERR=$(cat $ERROUT)
echo "$LAST_ERR"
if [ $attempt -gt 5 ];then
rm $ERROUT || true
fail "failed to configure runner: $LAST_ERR"
fi
sendStatus "failed to configure runner (attempt $attempt): $LAST_ERR (retrying in 5 seconds)"
attempt=$((attempt+1))
rm $ERROUT || true
sleep 5
done
set -e
{{- end}}
if [ -e "/sys/fs/selinux" ];then
sudo chcon -R -h user_u:object_r:bin_t:s0 /home/runner/ || fail "failed to change selinux context"
fi
AGENT_ID=""
{{- if .UseJITConfig }}
{{- else}}
sudo systemctl start act_runner || fail "failed to start service"
{{- end}}
systemInfo $AGENT_ID
success "runner successfully installed" $AGENT_ID This branch of Gitea used by the POC: https://github.com/ChristopherHX/gitea/tree/workflow_job_webhook PRs pending for non stub parts
Version of GARM that can configure go-github for gitea: https://github.com/actions-oss/gitea-garm-poc, otherwise didn't need edits if my version of gitea is used. The Open Bugs
|
Amazing progress! I am currently fighting off a flu or something. Will have some input for you as soon as my brain works again. |
Hey!
I just started playing with Garm and I'm really enjoying it!
I'd like to use it with my gitea server as well as some GitHub repos.
Are there plans to add support for Gitea? If not is that something I can contribute?
The text was updated successfully, but these errors were encountered: