No description
Find a file
2026-04-16 08:49:21 -04:00
action.yml feat: formatting git patch according to porter's handbook guidelines 2026-04-14 16:31:49 -04:00
diff.sh feat: adding support for Makefile.crate files 2026-04-16 08:49:21 -04:00
README.md docs: updated README 2026-04-13 21:18:21 -04:00
upload.sh feat: formatting git patch according to porter's handbook guidelines 2026-04-14 16:31:49 -04:00

ports-diff Action

Generate a FreeBSD ports diff using a shallow git clone, with optional artifact upload.

Features

  • Creates a diff file for a FreeBSD port against the upstream ports tree
  • Handles both new ports (creates full diff) and existing ports (diff against HEAD)
  • Follows FreeBSD Porter's Handbook submission format - generates staged diff suitable for git am
  • Copies .git directory for clean working copies (avoids shallow clone corruption and permission issues)
  • Optional artifact upload using Forgejo Actions v4 artifact API
  • Pure POSIX shell implementation - no Node.js required
  • Works with Forgejo 14.0+ Actions

Usage

Basic Usage (no artifact upload)

- uses: ./.forgejo/actions/ports-diff
  with:
    port-path: ./
    port: nickel
    category: lang

With Artifact Upload

- uses: ./.forgejo/actions/ports-diff
  with:
    port-path: ./
    port: nickel
    category: lang
    upload-artifact: 'true'
    artifact-name: 'nickel-ports-diff'  # optional, defaults to "{port}-ports-diff"

Using Outputs

- uses: ./.forgejo/actions/ports-diff
  id: diff
  with:
    port-path: ./
    port: nickel
    category: lang
    upload-artifact: 'true'

- name: Display results
  run: |
    echo "Diff file: ${{ steps.diff.outputs.diff-file }}"
    echo "Artifact ID: ${{ steps.diff.outputs.artifact-id }}"
    echo "Artifact URL: ${{ steps.diff.outputs.artifact-url }}"

Inputs

Input Description Required Default
port-path Path to the port on disk Yes -
port Port name (e.g., nginx, postgresql15) Yes -
category Port category (e.g., www, databases) Yes -
upload-artifact Upload the diff file as a workflow artifact No 'false'
artifact-name Name for the uploaded artifact No '{port}-ports-diff'

Outputs

Output Description
diff-file Path to the generated diff file
artifact-id ID of the uploaded artifact (only set if upload-artifact: 'true')
artifact-url URL to download the uploaded artifact (only set if upload-artifact: 'true')

Artifact Upload Implementation

The artifact upload is implemented as a pure POSIX shell script that uses the Forgejo Actions v4 artifact API directly, without requiring Node.js or the official actions/upload-artifact action.

Requirements

The upload script requires the following tools:

  • sh (POSIX shell)
  • curl
  • tar
  • gzip
  • jq (JSON parsing)
  • base64
  • stat
  • sha256sum (or shasum on macOS)

All of these are typically available in standard Forgejo runner environments.

How It Works

The upload script implements the v4 artifact protocol:

  1. CreateArtifact: POST to /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact

    • Requests a signed upload URL
    • Uses ACTIONS_RUNTIME_TOKEN for authentication (automatically provided by the runner)
    • Extracts workflow run and job IDs from the JWT token payload
  2. Upload: PUT to the signed upload URL

    • Uploads the tar.gz artifact file
    • Forgejo requires &comp=block appended to the URL
  3. FinalizeArtifact: POST to /twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact

    • Finalizes the artifact with SHA256 hash and size
    • Makes the artifact available in the UI

Differences from Package Registry Approach

This implementation uses the Actions artifact API instead of the package registry API:

Package Registry Actions Artifact API
Authentication Requires ARTIFACT_MANAGER_TOKEN secret Uses ACTIONS_RUNTIME_TOKEN (auto-provided)
API Endpoint /api/packages/{owner}/generic/... /twirp/github.actions.results.api.v1.ArtifactService/...
File Format Raw file upload tar.gz archive
UI Integration No workflow integration Appears in Actions workflow UI
Extra Setup Requires manual token creation No setup required

Example Workflow

name: Generate FreeBSD Port Diff

on:
  push:
    branches: [main]

jobs:
  generate-diff:
    runs-on: freebsd-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Generate and upload diff
        id: diff
        uses: ./.forgejo/actions/ports-diff
        with:
          port-path: ./
          port: nickel
          category: lang
          upload-artifact: 'true'

      - name: Show artifact URL
        run: |
          echo "Download the diff from: ${{ steps.diff.outputs.artifact-url }}"

Troubleshooting

The action avoids common git issues by copying the .git directory and creating a fresh working tree:

How it works:

  1. Copies /usr/ports/.git to a temporary directory
  2. Configures it as a non-bare repository
  3. Checks out HEAD to populate the working tree
  4. No network access or special permissions needed

Missing Dependencies

The upload functionality requires:

  • curl - for HTTP requests
  • tar - for creating the artifact archive
  • gzip - for compression
  • jq - for JSON parsing
  • base64 - for JWT token decoding
  • stat - for file size calculation
  • sha256sum (Linux) or shasum (macOS) - for hash calculation

All of these are typically available in standard runner environments.

Diff Format Compliance

This action follows the FreeBSD Porter's Handbook submission format exactly as specified in Section 3.6: Submitting the New Port.

For New Ports

The diff is generated using:

git add <category>/<port>
git diff --cached <category>/<port>

This produces a staged diff identical to what the Porter's Handbook recommends with git add . && git diff --staged.

For Existing Ports

The diff is generated against HEAD:

git diff HEAD <category>/<port>

This shows all changes from the current upstream state.

Diff Format

The generated diff:

  • Uses standard unified diff format
  • Includes proper --- /dev/null headers for new files
  • Is suitable for patch -p1 or git am application
  • Can be attached to a FreeBSD bug report under product Ports & Packages, component Individual Port(s)