--- layout: "@/layouts/BlogPostLayout.astro" title: "Creating Automated Deployment Workflows with Gitea Actions" description: "Using a frontend project deployment as an example, this article provides a step-by-step guide on how to create automated deployment workflows using Gitea actions. For those who don't want to use Jenkins, Gitea actions is a good CI/CD solution." date: "2023-12-15" image: "https://images.unsplash.com/photo-1607799279861-4dd421887fb3?q=80&w=1470&auto=format&fit=crop" tags: ["Gitea", "Actions", "CI/CD", "Automated Deployment"] tagId: ["gitea", "actions", "cicd", "automation-deployment"] category: "DevOps" categoryId: "devops" readTime: "10 min read" --- Using a frontend project deployment as an example, this article will provide a step-by-step guide on how to create automated deployment workflows using Gitea actions. For those who don't want to use Jenkins, Gitea actions is a good `CI/CD` solution. ## Introduction After developing a project, we need to deploy it to a server so that users can access it. However, manual deployment for each update wastes time and energy. Therefore, we can use Gitea actions to create an automated workflow for quick project deployment. ## What is Gitea Actions Gitea actions is a feature of Gitea that allows us to create automated workflows for quick project deployment. Gitea actions can perform various tasks such as building, testing, and deploying. Gitea actions can use various programming languages and tools, such as Python, Java, Docker, etc. Additionally, Gitea actions is configured to be compatible with GitHub actions configuration as much as possible, so if you are already familiar with GitHub actions, you can also easily use Gitea actions. For more details, see the official documentation: [Gitea actions](https://docs.gitea.com/en/usage/actions/overview) ## Preparation Before we start creating this workflow, you need to prepare the following materials: 1. A server, preferably with root privileges (for installing tools) 2. A deployed Gitea repository, version at least >= `v1.19`, officially strongly recommended to use `v1.20` or higher 3. Docker environment (not required, used on the host where the runner is deployed) > Note: The author has prepared: one build server + one deployment (target) server. You can use just one server, but be mindful of environment isolation. Please ensure you have completed all preparations before proceeding with subsequent steps. For specific installation and configuration, please refer to the official documentation, which I won't repeat here. [Installation](https://docs.gitea.com/en/category/installation) If you use the **1panel panel**, you can complete the installation with one click from the app store, which is what the author used. >Note: In versions < `v1.21.0`, you need to enable the `actions` feature in the configuration file. Please refer to the official documentation [Configuration](https://docs.gitea.com/en/usage/actions/quickstart). In later versions, it is enabled by default. This tutorial uses Gitea version `v1.22.6`! ## Configuring Runner In Gitea actions, running Jobs is done through Runners, so we need to configure a Runner first for our subsequent deployment workflow. There are two installation methods: you can install directly on the host or through a docker container. Here, the author will install through docker. To avoid excessive resource consumption, you can install it on a separate host (PS: For users in China, you can choose a Hong Kong server, which will make running jobs faster 😄). The author chose a Hong Kong VPS as the host. ### Downloading act_Runner First, we need to download this tool to register or generate configurations [Download Link](https://gitea.com/gitea/act_runner/releases). Please select the version corresponding to your system on this page for download. After downloading, upload it to the server. Here, I uploaded it to the `/gitea_runner2` directory on the server. You can also use tools like `curl` to download directly. You can use the following command, but pay attention to the name and download link. My system is `Debian12 x86_64`, so I downloaded `act_runner-0.2.11-linux-amd64`. ```bash curl -o act_runner2 https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64 ``` After completion, set the execution permissions ```bash chmod +x act_runner2 # Note the filename, please modify according to your actual situation ./act_runner --version # Seeing the version information means success ``` ### Generating Configuration ``` ./act_runner2 generate-config > config.yaml ``` Generally, the default configuration is sufficient. If you have other requirements, please modify `config.yaml` yourself. **Since the author chose to install via docker, if you choose to install directly on the host, you can skip the subsequent installation steps and refer to the official documentation for installation [Direct Installation](https://docs.gitea.com/en/usage/actions/quickstart)** ### Registering Runner Here I choose to register through the `docker-compose.yml` configuration method **Note: Modify the parameters in the configuration according to your own situation. The following configuration is for reference only!!!** ```yaml version: "3.8" services: runner: image: gitea/act_runner:latest environment: CONFIG_FILE: /config.yaml GITEA_INSTANCE_URL: "" GITEA_RUNNER_REGISTRATION_TOKEN: "" GITEA_RUNNER_NAME: "act_vps_runner2" GITEA_RUNNER_LABELS: "act_vps_runner2" volumes: - /gitea_runner2/config.yaml:/config.yaml - /gitea_runner2/runner_data/data:/data - /gitea_runner2/runner_data/cache:/root/.cache - /var/run/docker.sock:/var/run/docker.sock ``` ### Configuration Explanation **GITEA_RUNNER_REGISTRATION_TOKEN** This parameter is the registration token, which needs to be obtained from your gitea. There are three levels in total. I directly chose the organization level, which can be obtained from the organization settings page, as shown in the following figure: ![image](https://pic1.imgdb.cn/item/6779f8dfd0e0a243d4ef14ab.png) For other instance configuration pages and explanations, please refer to the official documentation, which has detailed explanations. **If you cannot see the settings page, please ensure that you have the correct permissions and that Actions is enabled. Check the Gitea version!!!** ### Running and Generating Runner Since the author uses the 1panel panel, it can be directly orchestrated in the container options. If you don't use this type of visualization tool, you need to manually execute `docker-compose up -d` After success, you can check the container's operation and logs. The logs will display the registration success information, as shown in the following figures: ![image](https://pic1.imgdb.cn/item/677893b5d0e0a243d4eeccca.png) ![image](https://pic1.imgdb.cn/item/677893bad0e0a243d4eecccb.png) Then we return to the page where you obtained the runner token, refresh it, and you should see your runner, as shown in the following figure: ![image](https://pic1.imgdb.cn/item/6779f844d0e0a243d4ef1478.png) The name in the figure is based on the name you set during registration configuration. > At this point, our runner deployment is complete, and we can now use it in projects. ## Using Actions The usage of gitea actions is similar to github actions. If you are not familiar with this type of configuration, you can first learn about **github actions**. The author will use a `vitepress` project as an example. ### Creating Configuration Files 1. Create a `.gitea/workflows` directory in the project root directory 2. Create a `deploy.yaml` configuration file in this directory 3. Let's first write a test configuration to test environment variables, as shown below: ```yaml name: Deploy Test on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Print Environment Variables run: env - name: Print Current Directory run: pwd - name: List Files in Working Directory run: ls -la ``` Then commit the code to the repository, and we should be able to see the execution task in the repository's actions, as shown in the following figure: ![image](https://pic1.imgdb.cn/item/6779f972d0e0a243d4ef14da.png) > **PS: If you don't see actions execution, or even don't see the actions option, you may need to enable the actions option in the repository, organization, or management page** ### Configuring Build We modify the `deploy.yaml` configuration file to add build steps. I'm using pnpm here, please adjust some configurations according to your actual situation. I won't elaborate too much here. ````yaml name: Deploy docs for project run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀 on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest strategy: matrix: node-version: [18.x] steps: # TODO Temporary solution for https://github.com/go-gitea/gitea/issues/32481, waiting for gitea to release 1.23.0 for fix - name: Install git run: | if ! command -v git &> /dev/null; then apt-get update && apt-get install -y git else echo "git is already installed" fi - name: Checkout repository code uses: https://gitea.com/actions/checkout@v4 with: ref: 'main' - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} # Skip pnpm cache to reduce overhead - name: Install pnpm run: | if ! command -v pnpm &> /dev/null; then npm install -g pnpm@9 else echo "pnpm is already installed" fi - name: Check Node.js and pnpm versions run: | echo "pnpm version ===>" && pnpm -v echo "node version ===>" && node -v # Simplify node_modules handling without caching - name: Install dependencies run: | if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then echo "Dependencies are outdated or missing, installing..." pnpm install else echo "Dependencies are up-to-date, skipping installation." fi - name: Build docs run: pnpm run docs:build ```` > **Special note: Installing git is to fix the current issue in gitea actions where code cannot be checked out through `actions/checkout`. This issue is expected to be fixed in `v1.23.0`. Currently, we can only handle it this way. But from the author's observation, it seems to be related to the image version used. If it's `ubuntu-latest`, you might not need to install it. Please base it on your actual situation.** If everything goes smoothly, you should see the build task completed in the workflow, as shown in the figure: ![image](https://pic1.imgdb.cn/item/677bcf9bd0e0a243d4f00c7a.png) ### Deploying the Project The principle of code deployment is actually to connect to the target server via `ssh` and execute deployment scripts. Therefore, we need to configure SSH first, then use the `actions` [easingthemes/ssh-deploy](https://github.com/easingthemes/ssh-deploy) to connect to the target server and push the code. #### Configuring SSH This step is actually to configure a user for the server and support `SSH` login, which is password-free login. Therefore, we use the following commands in sequence on the **target server**. The author is using `Debian 12`, please adjust the commands according to your actual situation! ##### Creating a User (It is recommended to create a user to operate the deployment directory, do not use the root user!!!) ```bash sudo adduser deployuser # Please modify the username according to your actual situation ``` After successful creation, you can check if the `/home/deployuser` directory exists. If it doesn't exist, you may need to create it manually. ##### Creating Key Pairs We need to first switch to the `deployuser` user, then execute the following commands: ```bash # 1. Create public and private keys ssh-keygen -t rsa -b 4096 -C "" # Add the public key content to the authorized_keys file echo ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # Set correct permissions chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh ``` ##### Granting Read and Write Permissions to Specific Directories (Can be skipped) This requires a user with `root` privileges to operate: ```bash # 1. Create directory mkdir -p /var/www/html/project # 2. Modify directory permissions sudo chown deployuser:deployuser /var/www/project sudo chmod 700 /var/www/project ``` Since the author used `1panel` to manage websites, the directory is automatically generated, which differs from this, but the process steps are the same. Please modify according to your actual situation. #### Configuring Key Information in Gitea 1. In your gitea's personal, organization, or management actions page, click `Secrets`, copy the private key we just generated on the server to the `Secret`, and then click `Add Secret`. 2. Since we will need the server IP and username later, it is also recommended to configure them in secrets or variables for later use. Here, the author has configured the private key, server IP, and username in secrets, as shown in the figure: ![image](https://pic1.imgdb.cn/item/677bd9c0d0e0a243d4f011f2.png) At this point, we have completed the configuration required for deploying the project, and we can now start the deployment process. > PS: Since `easingthemes/ssh-deploy` needs to use `rsync` to execute script commands, this tool is required in both the image container and the target server. If it doesn't exist, you need to install it in advance, especially on the **target server**. Generally, this needs to be done by a root user or a user with installation permissions. ### Project Deployment We add the following code to `deploy.yml`, pay attention to the format!!! ````yaml - name: ssh deploy uses: easingthemes/ssh-deploy@v5.1.0 with: SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }} REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }} REMOTE_USER: ${{ secrets.SH_REMOTE_USER }} SOURCE: "/.vitepress/dist/" TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # Please modify to your deployment directory according to your actual situation EXCLUDE: "/node_modules/" ```` If everything goes smoothly, you will see the actions executed successfully, and there will be a dist directory in your deployment directory, as shown in the following figures: ![image](https://pic1.imgdb.cn/item/677bdd23d0e0a243d4f014a3.png) ![image](https://pic1.imgdb.cn/item/677bdd1bd0e0a243d4f014a1.png) Next, you just need to use tools like `nginx` to point to this directory, and it can be accessed. > PS: If you encounter errors in the above step, please carefully check the error logs. Based on the author's experience, it's most likely due to issues with SSH keys and permission handling. If you're not using `ubuntu-latest`, you may also need to install some necessary tools according to the error messages, such as `git`, `rsync`, etc. ### Complete Configuration ````yaml name: Deploy docs for project run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀 on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest strategy: matrix: node-version: [18.x] steps: - name: Checkout repository code uses: https://gitea.com/actions/checkout@v4 with: ref: 'main' - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} # Skip pnpm cache to reduce overhead - name: Install pnpm run: | if ! command -v pnpm &> /dev/null; then npm install -g pnpm@9 else echo "pnpm is already installed" fi - name: Check Node.js and pnpm versions run: | echo "pnpm version ===>" && pnpm -v echo "node version ===>" && node -v # Simplify node_modules handling without caching - name: Install dependencies run: | if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then echo "Dependencies are outdated or missing, installing..." pnpm install else echo "Dependencies are up-to-date, skipping installation." fi - name: Build docs run: pnpm run docs:build - name: ssh deploy uses: easingthemes/ssh-deploy@v5.1.0 with: SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }} REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }} REMOTE_USER: ${{ secrets.SH_REMOTE_USER }} SOURCE: "/.vitepress/dist/" TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # Please modify to your deployment directory according to your actual situation EXCLUDE: "/node_modules/" ````