diff --git a/.forgejo/README.md b/.forgejo/README.md new file mode 100644 index 0000000..34153a0 --- /dev/null +++ b/.forgejo/README.md @@ -0,0 +1,187 @@ +# Forgejo Actions Configuration + +This directory contains Forgejo Actions workflows for the Baktainer project. Forgejo Actions provides Continuous Integration similar to GitHub Actions but runs on Forgejo instances. + +## Directory Structure + +``` +.forgejo/ +├── workflows/ +│ ├── ci.yml # Main CI pipeline (test + build) +│ ├── test.yml # Test-only workflow +│ ├── build.yml # Build-only workflow +│ └── docker.yml # Advanced Docker workflow +└── README.md # This file +``` + +## Workflows + +### 1. `ci.yml` - Main CI Pipeline +- **Triggers**: Push to main, tags, and pull requests +- **Jobs**: Test → Build → Notify +- **Features**: + - Runs RSpec tests in Ruby 3.3 Alpine container + - Builds and pushes Docker images to Docker Hub + - Provides status notifications + +### 2. `test.yml` - Test-Only Workflow +- **Triggers**: Push to main and pull requests +- **Jobs**: Test +- **Features**: + - Runs unit and integration tests separately + - Generates coverage reports + - Uploads test artifacts + +### 3. `build.yml` - Build-Only Workflow +- **Triggers**: Push to main and tags +- **Jobs**: Build → Notify +- **Features**: + - Builds Docker images after tests pass + - Supports versioned tags + - Provides build status notifications + +### 4. `docker.yml` - Advanced Docker Workflow +- **Triggers**: Push to main and tags +- **Jobs**: Test → Build +- **Features**: + - Uses Docker Buildx for advanced builds + - Implements Docker layer caching + - Automatic metadata extraction + +## Key Differences from GitHub Actions + +### 1. Directory Location +- **GitHub**: `.github/workflows/` +- **Forgejo**: `.forgejo/workflows/` + +### 2. Runner Types +- Uses `runs-on: docker` for containerized jobs +- Can specify custom container images with `container:` + +### 3. Action Compatibility +- Most GitHub Actions work with Forgejo Actions +- Actions are sourced from configured action repositories +- Uses same syntax for `actions/checkout@v4`, `docker/build-push-action@v5`, etc. + +### 4. Environment Variables +- Same `${{ github.* }}` variables available +- Same secret management with `${{ secrets.* }}` + +## Required Secrets + +Configure these secrets in your Forgejo repository settings: + +| Secret | Description | Example | +|--------|-------------|---------| +| `DOCKER_USERNAME` | Docker Hub username | `jamez001` | +| `DOCKER_PASSWORD` | Docker Hub password or token | `dckr_pat_...` | +| `DOCKER_IMAGE_NAME` | Docker image name | `jamez001/baktainer` | + +## Configuration Requirements + +### 1. Enable Repository Actions +1. Go to `/{owner}/{repository}/settings` +2. Click on "Repository" tab +3. Check "Enable Repository Actions" + +### 2. Forgejo Runner Setup +- Forgejo Actions requires a separate Forgejo Runner +- Runner must be configured by the Forgejo administrator +- Runner supports Docker, LXC, or host-based execution + +### 3. Action Repository Configuration +- Actions are sourced from configured repositories +- Default actions available at https://data.forgejo.org +- Administrator can configure custom action sources + +## Workflow Features + +### Testing +- **Ruby 3.3** with Alpine Linux +- **RSpec** test suite with JUnit XML output +- **Coverage reporting** with simplecov +- **Artifact upload** for test results + +### Building +- **Multi-stage Docker builds** from Alpine Ruby base +- **Automatic tagging** with version tags +- **Docker Hub integration** with secure authentication +- **Build notifications** with status reporting + +### Caching +- **Ruby gem caching** for faster builds +- **Docker layer caching** (in advanced workflow) +- **Dependency caching** between runs + +## Usage Examples + +### Manual Workflow Trigger +```bash +# Push to main (triggers ci.yml) +git push origin main + +# Create and push version tag (triggers build) +git tag v0.1.1 +git push origin v0.1.1 + +# Create pull request (triggers test.yml) +git push origin feature-branch +# Then create PR in Forgejo UI +``` + +### Monitoring Workflow Status +1. Navigate to repository in Forgejo +2. Click on "Actions" tab +3. View workflow runs and logs +4. Check artifact downloads + +## Troubleshooting + +### Common Issues + +1. **Actions not running** + - Check if Repository Actions are enabled + - Verify Forgejo Runner is installed and running + - Check workflow file syntax + +2. **Docker build failures** + - Verify Docker Hub credentials in secrets + - Check Dockerfile syntax + - Ensure runner has Docker access + +3. **Test failures** + - Check Ruby version compatibility + - Verify system dependencies in Alpine + - Review test output in workflow logs + +### Debugging Steps + +1. **Check workflow syntax**: + ```bash + # Validate YAML syntax + yamllint .forgejo/workflows/ci.yml + ``` + +2. **Test locally**: + ```bash + # Run tests in similar environment + docker run --rm -v $(pwd):/app -w /app ruby:3.3-alpine sh -c \ + "apk add --no-cache build-base libffi-dev linux-headers postgresql-dev git && \ + cd app && bundle install && bundle exec rspec" + ``` + +3. **Check logs**: + - View detailed logs in Forgejo Actions UI + - Check runner logs on server + - Verify secret configuration + +## Migration from GitHub Actions + +The workflows in this directory are designed to be compatible with the existing GitHub Actions in `.github/workflows/`. Key adaptations made: + +1. **Runner specification**: Changed from `ubuntu-latest` to `docker` with container specification +2. **Dependency installation**: Added explicit Alpine package installation +3. **Simplified caching**: Adapted caching strategy for Forgejo environment +4. **Container-based execution**: Optimized for Docker container runtime + +Both GitHub Actions and Forgejo Actions can coexist in the same repository, allowing for gradual migration or dual CI/CD setup. \ No newline at end of file diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml new file mode 100644 index 0000000..7feaaa1 --- /dev/null +++ b/.forgejo/workflows/build.yml @@ -0,0 +1,63 @@ +name: Build Docker Image + +on: + push: + branches: + - main + tags: + - 'v*.*.*' + +jobs: + build: + runs-on: docker + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract version tag + id: version + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + echo "VERSION_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + fi + + - name: Set image tags + id: tags + run: | + IMAGE_NAME=${{ secrets.DOCKER_IMAGE_NAME }} + TAGS="${IMAGE_NAME}:latest" + if [ -n "${{ steps.version.outputs.VERSION_TAG }}" ]; then + TAGS="$TAGS,${IMAGE_NAME}:${{ steps.version.outputs.VERSION_TAG }}" + fi + echo "tags=$TAGS" >> $GITHUB_OUTPUT + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.tags.outputs.tags }} + + notify: + needs: build + runs-on: docker + if: always() + + steps: + - name: Notify build status + run: | + if [ "${{ needs.build.result }}" == "success" ]; then + echo "✅ Docker image built and pushed successfully" + echo "🏷️ Tags: ${{ needs.build.outputs.tags }}" + else + echo "❌ Docker image build failed" + exit 1 + fi \ No newline at end of file diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..a3d0cd8 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,118 @@ +name: CI Pipeline + +on: + push: + branches: + - main + tags: + - 'v*.*.*' + pull_request: + branches: + - main + +jobs: + test: + runs-on: docker + container: + image: ruby:3.3-alpine + defaults: + run: + working-directory: ./app + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + apk add --no-cache build-base libffi-dev linux-headers postgresql-dev git curl tzdata + + - name: Install bundler + run: gem install bundler -v 2.6.7 + + - name: Cache Ruby gems + uses: actions/cache@v4 + with: + path: app/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('app/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Install Ruby dependencies + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: Run RSpec tests + run: | + mkdir -p tmp + bundle exec rspec \ + --format progress \ + --format RspecJunitFormatter \ + --out tmp/rspec_results.xml + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: rspec-results + path: app/tmp/rspec_results.xml + + build: + needs: test + runs-on: docker + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract version tag + id: version + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + echo "VERSION_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + fi + + - name: Set image tags + id: tags + run: | + IMAGE_NAME=${{ secrets.DOCKER_IMAGE_NAME }} + TAGS="${IMAGE_NAME}:latest" + if [ -n "${{ steps.version.outputs.VERSION_TAG }}" ]; then + TAGS="$TAGS,${IMAGE_NAME}:${{ steps.version.outputs.VERSION_TAG }}" + fi + echo "tags=$TAGS" >> $GITHUB_OUTPUT + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.tags.outputs.tags }} + + notify: + needs: [test, build] + runs-on: docker + if: always() + + steps: + - name: Notify pipeline status + run: | + echo "📊 Pipeline Status Report:" + echo "🧪 Tests: ${{ needs.test.result }}" + if [ "${{ needs.build.result }}" != "skipped" ]; then + echo "🐳 Build: ${{ needs.build.result }}" + fi + + if [ "${{ needs.test.result }}" == "success" ]; then + echo "✅ All tests passed!" + else + echo "❌ Tests failed" + fi \ No newline at end of file diff --git a/.forgejo/workflows/docker.yml b/.forgejo/workflows/docker.yml new file mode 100644 index 0000000..95e3750 --- /dev/null +++ b/.forgejo/workflows/docker.yml @@ -0,0 +1,86 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + tags: + - 'v*.*.*' + +jobs: + test: + runs-on: docker + container: + image: ruby:3.3-alpine + defaults: + run: + working-directory: ./app + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + apk add --no-cache build-base libffi-dev linux-headers postgresql-dev git + + - name: Install Ruby dependencies + run: | + gem install bundler -v 2.6.7 + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: Run RSpec tests + run: | + mkdir -p tmp + bundle exec rspec \ + --format progress \ + --format RspecJunitFormatter \ + --out tmp/rspec_results.xml + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: rspec-results + path: app/tmp/rspec_results.xml + + build: + needs: test + runs-on: docker + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKER_IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.forgejo/workflows/test.yml b/.forgejo/workflows/test.yml new file mode 100644 index 0000000..d8a3f06 --- /dev/null +++ b/.forgejo/workflows/test.yml @@ -0,0 +1,64 @@ +name: Run Tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test: + runs-on: docker + container: + image: ruby:3.3-alpine + defaults: + run: + working-directory: ./app + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + apk add --no-cache build-base libffi-dev linux-headers postgresql-dev git curl tzdata + + - name: Install bundler + run: gem install bundler -v 2.6.7 + + - name: Cache Ruby gems + uses: actions/cache@v4 + with: + path: app/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('app/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Install Ruby dependencies + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: Run unit tests + run: | + echo "🧪 Running unit tests..." + bundle exec rspec spec/unit/ --format documentation + + - name: Run integration tests + run: | + echo "🧪 Running integration tests..." + bundle exec rspec spec/integration/ --format documentation + + - name: Generate coverage report + run: | + echo "📊 Generating coverage report..." + COVERAGE=true bundle exec rspec --format progress + + - name: Upload coverage results + uses: actions/upload-artifact@v4 + if: always() + with: + name: coverage-report + path: app/coverage/ \ No newline at end of file