Skip to main content

Overview

Gitea Actions is a built-in CI/CD system that enables automated workflows for building, testing, and deploying your code. With GitHub Actions compatibility, you can reuse existing workflows and actions from the broader ecosystem.

Key Features

GitHub Actions Compatible

  • Reuse GitHub Actions workflows
  • Use actions from marketplace
  • Compatible YAML syntax
  • Familiar workflow patterns

Self-Hosted Runners

  • Run on your infrastructure
  • Full control over environment
  • Custom runner labels
  • Secure execution

Matrix Builds

  • Test multiple versions
  • Cross-platform builds
  • Parallel execution
  • Efficient resource usage

Workflow Automation

  • Event-driven triggers
  • Scheduled workflows
  • Manual dispatch
  • Conditional execution

Getting Started

1

Enable Actions

Repository administrators must enable Actions in SettingsActions. Instance administrators must enable Actions in the Gitea configuration.
2

Create Workflow File

Create .gitea/workflows/ or .github/workflows/ directory in your repository:
mkdir -p .gitea/workflows
touch .gitea/workflows/ci.yml
3

Define Workflow

Write your workflow configuration in YAML format
4

Commit and Push

Commit the workflow file and push to trigger execution:
git add .gitea/workflows/ci.yml
git commit -m "Add CI workflow"
git push origin main

Workflow Syntax

Basic Workflow

name: CI Pipeline

# Trigger events
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  workflow_dispatch:  # Manual trigger

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm test
      
      - name: Build
        run: npm run build

Workflow Components

name: Workflow display nameon: Event triggers that start the workflow
  • push: When code is pushed
  • pull_request: When PR is created/updated
  • schedule: Cron-based scheduling
  • workflow_dispatch: Manual trigger
  • release: When release is published
jobs: Individual units of work
  • Run in parallel by default
  • Can have dependencies
  • Each runs in fresh environment
steps: Sequential tasks within a job
  • Execute in order
  • Share job environment
  • Can use actions or run commands

Action Run Model

// From models/actions/run.go
type ActionRun struct {
    ID                int64
    Title             string
    RepoID            int64
    Repo              *repo_model.Repository
    OwnerID           int64
    WorkflowID        string  // Workflow file name
    Index             int64   // Unique number per repo
    TriggerUserID     int64
    TriggerUser       *user_model.User
    Ref               string  // Branch/tag that triggered run
    CommitSHA         string
    Event             webhook_module.HookEventType
    EventPayload      string  // JSON payload
    Status            Status
    Started           timeutil.TimeStamp
    Stopped           timeutil.TimeStamp
    PreviousDuration  time.Duration
}

func (run *ActionRun) HTMLURL() string {
    if run.Repo == nil {
        return ""
    }
    return fmt.Sprintf("%s/actions/runs/%d", 
                      run.Repo.HTMLURL(), run.Index)
}

Triggers

Push Events

on:
  push:
    branches:
      - main
      - 'release/**'  # Branch patterns
    tags:
      - 'v*'          # Tag patterns
    paths:
      - 'src/**'      # Only when these paths change
      - '!docs/**'    # Ignore docs changes

Pull Request Events

on:
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
    branches:
      - main
    paths-ignore:
      - '**.md'       # Ignore markdown changes

Scheduled Workflows

on:
  schedule:
    # Run at 2:00 AM every day
    - cron: '0 2 * * *'
    # Run every Monday at 9:00 AM
    - cron: '0 9 * * 1'

Manual Dispatch

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy to'
        required: true
        type: choice
        options:
          - development
          - staging
          - production
      debug_enabled:
        description: 'Enable debug logging'
        required: false
        type: boolean
        default: false

Jobs and Steps

Job Dependencies

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm run build
  
  test:
    needs: build      # Wait for build to complete
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm test
  
  deploy:
    needs: [build, test]  # Wait for both
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - run: ./deploy.sh

Matrix Strategy

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: [16, 18, 20]
        exclude:
          - os: macos-latest
            node: 16
    
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node }}
      - run: npm test

Conditional Execution

steps:
  - name: Run on main branch only
    if: github.ref == 'refs/heads/main'
    run: echo "Main branch"
  
  - name: Run on PR only
    if: github.event_name == 'pull_request'
    run: echo "Pull request"
  
  - name: Run when tests pass
    if: success()
    run: echo "Tests passed"
  
  - name: Run on failure
    if: failure()
    run: echo "Something failed"
  
  - name: Always run
    if: always()
    run: echo "Cleanup"

Using Actions

Built-in Actions

steps:
  # Checkout repository
  - uses: actions/checkout@v3
    with:
      fetch-depth: 0  # Full history
  
  # Setup language runtime
  - uses: actions/setup-node@v3
    with:
      node-version: '18'
      cache: 'npm'
  
  # Upload artifacts
  - uses: actions/upload-artifact@v3
    with:
      name: build-output
      path: dist/
  
  # Download artifacts
  - uses: actions/download-artifact@v3
    with:
      name: build-output

Custom Actions

Create reusable actions in your repository or organization:
# .gitea/actions/my-action/action.yml
name: 'My Custom Action'
description: 'Does something useful'
inputs:
  input-param:
    description: 'Input parameter'
    required: true
outputs:
  result:
    description: 'Action result'
runs:
  using: 'composite'
  steps:
    - run: echo "${{ inputs.input-param }}"
      shell: bash
Use custom action:
steps:
  - uses: ./.gitea/actions/my-action
    with:
      input-param: 'value'

Secrets and Variables

Repository Secrets

Store sensitive data securely:
1

Add Secrets

Navigate to SettingsSecrets and add secrets like API keys, tokens, and passwords
2

Use in Workflows

steps:
  - name: Deploy
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
    run: ./deploy.sh
Secrets are encrypted and never exposed in logs. They’re only available to workflows in the repository where they’re defined.

Variables

env:
  # Workflow-level variables
  NODE_ENV: production
  API_URL: https://api.example.com

jobs:
  build:
    env:
      # Job-level variables
      BUILD_DIR: ./dist
    
    steps:
      - name: Build
        env:
          # Step-level variables
          CUSTOM_VAR: value
        run: npm run build

Context Variables

Access workflow metadata:
steps:
  - name: Print context
    run: |
      echo "Repository: ${{ github.repository }}"
      echo "Ref: ${{ github.ref }}"
      echo "SHA: ${{ github.sha }}"
      echo "Actor: ${{ github.actor }}"
      echo "Event: ${{ github.event_name }}"
      echo "Run ID: ${{ github.run_id }}"
      echo "Run Number: ${{ github.run_number }}"

Runners

Runner Labels

Target specific runners:
jobs:
  build-linux:
    runs-on: ubuntu-latest
  
  build-windows:
    runs-on: windows-latest
  
  build-mac:
    runs-on: macos-latest
  
  custom-runner:
    runs-on: [self-hosted, gpu, linux]

Self-Hosted Runners

Register custom runners:
1

Download Runner

Download the Gitea Actions runner for your platform from the Gitea releases page
2

Register Runner

./act_runner register \
  --instance https://gitea.example.com \
  --token YOUR_RUNNER_TOKEN \
  --name my-runner \
  --labels linux,x64,gpu
3

Start Runner

./act_runner daemon
Self-hosted runners can access your internal network and resources. Only use them with trusted repositories.

Artifacts and Caching

Artifacts

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm run build
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-artifacts
          path: |
            dist/
            build/
          retention-days: 7
  
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
      
      - run: ./deploy.sh

Caching Dependencies

steps:
  - uses: actions/checkout@v3
  
  - name: Cache node modules
    uses: actions/cache@v3
    with:
      path: ~/.npm
      key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
      restore-keys: |
        ${{ runner.os }}-node-
  
  - run: npm ci

Status Badges

Display workflow status in README:
![CI](https://gitea.example.com/user/repo/actions/workflows/ci.yml/badge.svg)

<!-- With branch -->
![CI](https://gitea.example.com/user/repo/actions/workflows/ci.yml/badge.svg?branch=main)

Notifications

Gitea Actions integrates with the notification system:

Success Notifications

  • Workflow completion
  • Job success
  • Deployment success
  • Custom success actions

Failure Notifications

  • Build failures
  • Test failures
  • Deployment errors
  • Timeout notifications

Example Workflows

name: Node.js CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - run: npm ci
      - run: npm run build
      - run: npm test

Best Practices

Performance
  • Use caching for dependencies
  • Run jobs in parallel when possible
  • Use matrix builds efficiently
  • Clean up artifacts regularly
Security
  • Store secrets securely
  • Limit secret exposure
  • Use minimal permissions
  • Pin action versions
  • Review third-party actions
Maintainability
  • Use descriptive job and step names
  • Document complex workflows
  • Reuse workflows with templates
  • Keep workflows DRY (Don’t Repeat Yourself)
  • Version control workflow files
Reliability
  • Handle failures gracefully
  • Use appropriate timeouts
  • Add retry logic for flaky tests
  • Monitor workflow execution
  • Set up failure notifications

See Also

Build docs developers (and LLMs) love