136 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| date: "2023-04-27T15:00:00+08:00"
 | |
| title: "Design of Gitea Actions"
 | |
| slug: "usage/actions/design"
 | |
| weight: 40
 | |
| draft: false
 | |
| toc: false
 | |
| menu:
 | |
|   sidebar:
 | |
|     parent: "actions"
 | |
|     name: "Design"
 | |
|     weight: 40
 | |
|     identifier: "actions-design"
 | |
| ---
 | |
| 
 | |
| # Design of Gitea Actions
 | |
| 
 | |
| Gitea Actions has multiple components. This document describes them individually.
 | |
| 
 | |
| **Table of Contents**
 | |
| 
 | |
| {{< toc >}}
 | |
| 
 | |
| ## Act
 | |
| 
 | |
| The [nektos/act](https://github.com/nektos/act) project is an excellent tool that allows you to run your GitHub Actions locally.
 | |
| We were inspired by this and wondered if it would be possible to run actions for Gitea.
 | |
| 
 | |
| However, while [nektos/act](https://github.com/nektos/act) is designed as a command line tool, what we actually needed was a Go library with modifications specifically for Gitea.
 | |
| So we forked it as [gitea/act](https://gitea.com/gitea/act).
 | |
| 
 | |
| This is a soft fork that will periodically follow the upstream.
 | |
| Although some custom commits have been added, we will try our best to avoid changing too much of the original code.
 | |
| 
 | |
| The forked act is just a shim or adapter for Gitea's specific usage.
 | |
| There are some additional commits that have been made, such as:
 | |
| 
 | |
| - Outputting execution logs to logger hook so they can be reported to Gitea
 | |
| - Disabling the GraphQL URL, since Gitea doesn't support it
 | |
| - Starting a new container for every job instead of reusing to ensure isolation.
 | |
| 
 | |
| These modifications have no reason to be merged into the upstream.
 | |
| They don't make sense if the user just wants to run trusted actions locally.
 | |
| 
 | |
| However, there may be overlaps in the future, such as a required bug fix or new feature needed by both projects.
 | |
| In these cases, we will contribute the changes back to the upstream repository.
 | |
| 
 | |
| ## Act runner
 | |
| 
 | |
| Gitea's runner is called act runner because it's based on act.
 | |
| 
 | |
| Like other CI runners, we designed it as an external part of Gitea, which means it should run on a different server than Gitea.
 | |
| 
 | |
| To ensure that the runner connects to the correct Gitea instance, we need to register it with a token.
 | |
| Additionally, the runner will introduce itself to Gitea and declare what kind of jobs it can run by reporting its labels.
 | |
| 
 | |
| Earlier, we mentioned that `runs-on: ubuntu-latest` in a workflow file means that the job will be run on a runner with the `ubuntu-latest` label.
 | |
| But how does the runner know to run `ubuntu-latest`? The answer lies in mapping the label to an environment.
 | |
| That's why when you add custom labels during registration, you will need to input some complex content like `my_custom_label:docker://centos:7`.
 | |
| This means that the runner can take the job which needs to run on `my_custom_label`, and it will run it via a docker container with the image `centos:7`.
 | |
| 
 | |
| Docker isn't the only option, though.
 | |
| The act also supports running jobs directly on the host.
 | |
| This is achieved through labels like `linux_arm:host`.
 | |
| This label indicates that the runner can take a job that needs to run on `linux_arm` and run it directly on the host.
 | |
| 
 | |
| The label's design follows the format `label[:schema[:args]]`.
 | |
| If the schema is omitted, it defaults to `host`.
 | |
| So,
 | |
| 
 | |
| - `my_custom_label:docker://node:18`: Run jobs labeled with `my_custom_label` using the `node:18` Docker image.
 | |
| - `my_custom_label:host`: Run jobs labeled with `my_custom_label` directly on the host.
 | |
| - `my_custom_label`: Same as `my_custom_label:host`.
 | |
| - `my_custom_label:vm:ubuntu-latest`: (Example only, not implemented) Run jobs labeled with `my_custom_label` using a virtual machine with the `ubuntu-latest` ISO.
 | |
| 
 | |
| ## Communication protocol
 | |
| 
 | |
| As act runner is an independent part of Gitea, we needed a protocol for runners to communicate with the Gitea instance.
 | |
| However, we did not think it was a good idea to have Gitea listen on a new port.
 | |
| Instead, we wanted to reuse the HTTP port, which means we needed a protocol that is compatible with HTTP.
 | |
| We chose to use gRPC over HTTP.
 | |
| 
 | |
| We use [actions-proto-def](https://gitea.com/gitea/actions-proto-def) and [actions-proto-go](https://gitea.com/gitea/actions-proto-go) to wire them up.
 | |
| More information about gRPC can be found on [its website](https://grpc.io/).
 | |
| 
 | |
| ## Network architecture
 | |
| 
 | |
| Let's examine the overall network architecture.
 | |
| This will help you troubleshoot some problems and explain why it's a bad idea to register a runner with a loopback address of the Gitea instance.
 | |
| 
 | |
| 
 | |
| 
 | |
| There are four network connections marked in the picture, and the direction of the arrows indicates the direction of establishing the connections.
 | |
| 
 | |
| ### Connection 1, act runner to Gitea instance
 | |
| 
 | |
| The act runner must be able to connect to Gitea to receive tasks and send back the execution results.
 | |
| 
 | |
| ### Connection 2, job containers to Gitea instance
 | |
| 
 | |
| The job containers have different network namespaces than the runner, even if they are on the same machine.
 | |
| They need to connect to Gitea to fetch codes if there is `actions/checkout@v3` in the workflow, for example.
 | |
| Fetching code is not always necessary to run some jobs, but it is required in most cases.
 | |
| 
 | |
| If you use a loopback address to register a runner, the runner can connect to Gitea when it is on the same machine.
 | |
| However, if a job container tries to fetch code from localhost, it will fail because Gitea is not in the same container.
 | |
| 
 | |
| ### Connection 3, act runner to internet
 | |
| 
 | |
| When you use some actions like `actions/checkout@v3`, the act runner downloads the scripts, not the job containers.
 | |
| By default, it downloads from [gitea.com](http://gitea.com/), so it requires access to the internet.
 | |
| It also downloads some docker images from Docker Hub by default, which also requires internet access.
 | |
| 
 | |
| However, internet access is not strictly necessary.
 | |
| You can configure your Gitea instance to fetch actions or images from your intranet facilities.
 | |
| 
 | |
| In fact, your Gitea instance can serve as both the actions marketplace and the image registry.
 | |
| You can mirror actions repositories from GitHub to your Gitea instance, and use them as normal.
 | |
| And [Gitea Container Registry](https://docs.gitea.io/en-us/usage/packages/container/) can be used as a Docker image registry.
 | |
| 
 | |
| ### Connection 4, job containers to internet
 | |
| 
 | |
| When using actions such as `actions/setup-go@v4`, it may be necessary to download resources from the internet to set up the Go language environment in job containers.
 | |
| Therefore, access to the internet is required for the successful completion of these actions.
 | |
| 
 | |
| However, it is optional as well.
 | |
| You can use your own custom actions to avoid relying on internet access, or you can use your packaged Docker image to run jobs with all dependencies installed.
 | |
| 
 | |
| ## Summary
 | |
| 
 | |
| Using Gitea Actions only requires ensuring that the runner can connect to the Gitea instance.
 | |
| Internet access is optional, but not having it will require some additional work.
 | |
| In other words: The runner works best when it can query the internet itself, but you don't need to expose it to the internet (in either direction).
 | |
| 
 | |
| If you encounter any network issues while using Gitea Actions, hopefully the image above can help you troubleshoot them.
 |