- Shell 100%
| action.yml | ||
| diff.sh | ||
| README.md | ||
| upload.sh | ||
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
.gitdirectory 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)curltargzipjq(JSON parsing)base64statsha256sum(orshasumon macOS)
All of these are typically available in standard Forgejo runner environments.
How It Works
The upload script implements the v4 artifact protocol:
-
CreateArtifact: POST to
/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact- Requests a signed upload URL
- Uses
ACTIONS_RUNTIME_TOKENfor authentication (automatically provided by the runner) - Extracts workflow run and job IDs from the JWT token payload
-
Upload: PUT to the signed upload URL
- Uploads the tar.gz artifact file
- Forgejo requires
&comp=blockappended to the URL
-
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
Git-Related Errors
The action avoids common git issues by copying the .git directory and creating a fresh working tree:
How it works:
- Copies
/usr/ports/.gitto a temporary directory - Configures it as a non-bare repository
- Checks out HEAD to populate the working tree
- No network access or special permissions needed
Missing Dependencies
The upload functionality requires:
curl- for HTTP requeststar- for creating the artifact archivegzip- for compressionjq- for JSON parsingbase64- for JWT token decodingstat- for file size calculationsha256sum(Linux) orshasum(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/nullheaders for new files - Is suitable for
patch -p1orgit amapplication - Can be attached to a FreeBSD bug report under product Ports & Packages, component Individual Port(s)