10 min read

Creating Automated Deployment Workflows with Gitea Actions

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.

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

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

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. 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. 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.

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

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

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!!!

version: "3.8"
services:
  runner:
    image: gitea/act_runner:latest
    environment:
      CONFIG_FILE: /config.yaml
      GITEA_INSTANCE_URL: "<your_gitea.com>"
      GITEA_RUNNER_REGISTRATION_TOKEN: "<your_registration_token_here>"
      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

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 image

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 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:
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

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.

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

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 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!

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:

# 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:

# 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

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!!!

      - name: ssh deploy
        uses: easingthemes/[email protected]
        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 image

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

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/[email protected]
        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/"
Joy Zhao

Joy Zhao

Crafting elegant solutions to complex problems with clean code and innovative thinking. Welcome to my personal dev workspace where ideas come to life.