Add reusable Forgejo Actions
Composite actions for CI/CD workflows: - checkout: Clone repo with configurable depth - docker-build: Build Docker images with multiple tags - docker-push: Push to Forgejo Packages registry - create-tag: Auto-increment semantic version tags - create-issue: Create issues via Forgejo API - create-pr: Create pull requests via Forgejo API - comment-pr: Add comments to PRs via Forgejo API All actions use shell scripts (no Node.js required). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
28
checkout/action.yaml
Normal file
28
checkout/action.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: Checkout
|
||||||
|
description: Clone repository with configurable depth
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
repository:
|
||||||
|
description: Repository to clone (owner/repo)
|
||||||
|
default: ${{ github.repository }}
|
||||||
|
ref:
|
||||||
|
description: Branch, tag, or SHA to checkout
|
||||||
|
default: ${{ github.ref_name }}
|
||||||
|
depth:
|
||||||
|
description: Clone depth (0 for full history)
|
||||||
|
default: '1'
|
||||||
|
token:
|
||||||
|
description: Token for private repositories
|
||||||
|
default: ${{ github.token }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- shell: bash
|
||||||
|
run: |
|
||||||
|
if [ "${{ inputs.depth }}" = "0" ]; then
|
||||||
|
git clone "https://oauth2:${{ inputs.token }}@code.flowmade.one/${{ inputs.repository }}.git" .
|
||||||
|
else
|
||||||
|
git clone --depth "${{ inputs.depth }}" --branch "${{ inputs.ref }}" \
|
||||||
|
"https://oauth2:${{ inputs.token }}@code.flowmade.one/${{ inputs.repository }}.git" .
|
||||||
|
fi
|
||||||
43
comment-pr/action.yaml
Normal file
43
comment-pr/action.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Comment on PR
|
||||||
|
description: Add a comment to a pull request via Forgejo API
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
token:
|
||||||
|
description: Forgejo API token
|
||||||
|
required: true
|
||||||
|
repository:
|
||||||
|
description: Repository (owner/repo)
|
||||||
|
default: ${{ github.repository }}
|
||||||
|
pr-number:
|
||||||
|
description: Pull request number
|
||||||
|
required: true
|
||||||
|
body:
|
||||||
|
description: Comment body
|
||||||
|
required: true
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
id:
|
||||||
|
description: Created comment ID
|
||||||
|
value: ${{ steps.comment.outputs.id }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- id: comment
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
TOKEN="${{ inputs.token }}"
|
||||||
|
REPO="${{ inputs.repository }}"
|
||||||
|
PR_NUMBER="${{ inputs.pr-number }}"
|
||||||
|
BODY="${{ inputs.body }}"
|
||||||
|
|
||||||
|
JSON=$(jq -n --arg body "$BODY" '{body: $body}')
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X POST \
|
||||||
|
"https://code.flowmade.one/api/v1/repos/$REPO/issues/$PR_NUMBER/comments" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$JSON")
|
||||||
|
|
||||||
|
ID=$(echo "$RESPONSE" | jq -r '.id')
|
||||||
|
echo "id=$ID" >> $GITHUB_OUTPUT
|
||||||
73
create-issue/action.yaml
Normal file
73
create-issue/action.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
name: Create Issue
|
||||||
|
description: Create an issue via Forgejo API
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
token:
|
||||||
|
description: Forgejo API token
|
||||||
|
required: true
|
||||||
|
repository:
|
||||||
|
description: Repository (owner/repo)
|
||||||
|
default: ${{ github.repository }}
|
||||||
|
title:
|
||||||
|
description: Issue title
|
||||||
|
required: true
|
||||||
|
body:
|
||||||
|
description: Issue body
|
||||||
|
default: ''
|
||||||
|
labels:
|
||||||
|
description: Comma-separated label names
|
||||||
|
default: ''
|
||||||
|
assignees:
|
||||||
|
description: Comma-separated usernames to assign
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
number:
|
||||||
|
description: Created issue number
|
||||||
|
value: ${{ steps.create.outputs.number }}
|
||||||
|
url:
|
||||||
|
description: Issue URL
|
||||||
|
value: ${{ steps.create.outputs.url }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- id: create
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
TOKEN="${{ inputs.token }}"
|
||||||
|
REPO="${{ inputs.repository }}"
|
||||||
|
TITLE="${{ inputs.title }}"
|
||||||
|
BODY="${{ inputs.body }}"
|
||||||
|
LABELS="${{ inputs.labels }}"
|
||||||
|
ASSIGNEES="${{ inputs.assignees }}"
|
||||||
|
|
||||||
|
# Build JSON payload
|
||||||
|
JSON=$(jq -n \
|
||||||
|
--arg title "$TITLE" \
|
||||||
|
--arg body "$BODY" \
|
||||||
|
'{title: $title, body: $body}')
|
||||||
|
|
||||||
|
# Add labels if provided
|
||||||
|
if [ -n "$LABELS" ]; then
|
||||||
|
LABELS_JSON=$(echo "$LABELS" | tr ',' '\n' | jq -R . | jq -s .)
|
||||||
|
JSON=$(echo "$JSON" | jq --argjson labels "$LABELS_JSON" '. + {labels: $labels}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add assignees if provided
|
||||||
|
if [ -n "$ASSIGNEES" ]; then
|
||||||
|
ASSIGNEES_JSON=$(echo "$ASSIGNEES" | tr ',' '\n' | jq -R . | jq -s .)
|
||||||
|
JSON=$(echo "$JSON" | jq --argjson assignees "$ASSIGNEES_JSON" '. + {assignees: $assignees}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X POST \
|
||||||
|
"https://code.flowmade.one/api/v1/repos/$REPO/issues" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$JSON")
|
||||||
|
|
||||||
|
NUMBER=$(echo "$RESPONSE" | jq -r '.number')
|
||||||
|
URL=$(echo "$RESPONSE" | jq -r '.html_url')
|
||||||
|
|
||||||
|
echo "number=$NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
echo "url=$URL" >> $GITHUB_OUTPUT
|
||||||
83
create-pr/action.yaml
Normal file
83
create-pr/action.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
name: Create Pull Request
|
||||||
|
description: Create a pull request via Forgejo API
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
token:
|
||||||
|
description: Forgejo API token
|
||||||
|
required: true
|
||||||
|
repository:
|
||||||
|
description: Repository (owner/repo)
|
||||||
|
default: ${{ github.repository }}
|
||||||
|
title:
|
||||||
|
description: Pull request title
|
||||||
|
required: true
|
||||||
|
body:
|
||||||
|
description: Pull request body
|
||||||
|
default: ''
|
||||||
|
head:
|
||||||
|
description: Source branch
|
||||||
|
required: true
|
||||||
|
base:
|
||||||
|
description: Target branch
|
||||||
|
default: 'main'
|
||||||
|
labels:
|
||||||
|
description: Comma-separated label names
|
||||||
|
default: ''
|
||||||
|
assignees:
|
||||||
|
description: Comma-separated usernames to assign
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
number:
|
||||||
|
description: Created PR number
|
||||||
|
value: ${{ steps.create.outputs.number }}
|
||||||
|
url:
|
||||||
|
description: PR URL
|
||||||
|
value: ${{ steps.create.outputs.url }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- id: create
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
TOKEN="${{ inputs.token }}"
|
||||||
|
REPO="${{ inputs.repository }}"
|
||||||
|
TITLE="${{ inputs.title }}"
|
||||||
|
BODY="${{ inputs.body }}"
|
||||||
|
HEAD="${{ inputs.head }}"
|
||||||
|
BASE="${{ inputs.base }}"
|
||||||
|
LABELS="${{ inputs.labels }}"
|
||||||
|
ASSIGNEES="${{ inputs.assignees }}"
|
||||||
|
|
||||||
|
# Build JSON payload
|
||||||
|
JSON=$(jq -n \
|
||||||
|
--arg title "$TITLE" \
|
||||||
|
--arg body "$BODY" \
|
||||||
|
--arg head "$HEAD" \
|
||||||
|
--arg base "$BASE" \
|
||||||
|
'{title: $title, body: $body, head: $head, base: $base}')
|
||||||
|
|
||||||
|
# Add labels if provided
|
||||||
|
if [ -n "$LABELS" ]; then
|
||||||
|
LABELS_JSON=$(echo "$LABELS" | tr ',' '\n' | jq -R . | jq -s .)
|
||||||
|
JSON=$(echo "$JSON" | jq --argjson labels "$LABELS_JSON" '. + {labels: $labels}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add assignees if provided
|
||||||
|
if [ -n "$ASSIGNEES" ]; then
|
||||||
|
ASSIGNEES_JSON=$(echo "$ASSIGNEES" | tr ',' '\n' | jq -R . | jq -s .)
|
||||||
|
JSON=$(echo "$JSON" | jq --argjson assignees "$ASSIGNEES_JSON" '. + {assignees: $assignees}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -X POST \
|
||||||
|
"https://code.flowmade.one/api/v1/repos/$REPO/pulls" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$JSON")
|
||||||
|
|
||||||
|
NUMBER=$(echo "$RESPONSE" | jq -r '.number')
|
||||||
|
URL=$(echo "$RESPONSE" | jq -r '.html_url')
|
||||||
|
|
||||||
|
echo "number=$NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
echo "url=$URL" >> $GITHUB_OUTPUT
|
||||||
49
create-tag/action.yaml
Normal file
49
create-tag/action.yaml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: Create Tag
|
||||||
|
description: Auto-increment and create a version tag
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
prefix:
|
||||||
|
description: Tag prefix (e.g., 'v', 'myapp-v')
|
||||||
|
default: 'v'
|
||||||
|
token:
|
||||||
|
description: Token for pushing tags
|
||||||
|
default: ${{ github.token }}
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
tag:
|
||||||
|
description: The created tag name
|
||||||
|
value: ${{ steps.version.outputs.tag }}
|
||||||
|
version:
|
||||||
|
description: The version number without prefix
|
||||||
|
value: ${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- id: version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
PREFIX="${{ inputs.prefix }}"
|
||||||
|
|
||||||
|
# Find latest tag with this prefix
|
||||||
|
LATEST_TAG=$(git tag -l "${PREFIX}*" | sort -V | tail -1)
|
||||||
|
|
||||||
|
if [ -z "$LATEST_TAG" ]; then
|
||||||
|
NEXT_VERSION="${PREFIX}1.0.0"
|
||||||
|
else
|
||||||
|
# Extract version and increment patch
|
||||||
|
CURRENT_VERSION=${LATEST_TAG#$PREFIX}
|
||||||
|
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
|
||||||
|
NEXT_VERSION="${PREFIX}${MAJOR}.${MINOR}.$((PATCH + 1))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "tag=$NEXT_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=${NEXT_VERSION#$PREFIX}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Configure git and create tag
|
||||||
|
git config user.name forgejo-actions
|
||||||
|
git config user.email forgejo-actions@code.flowmade.one
|
||||||
|
git tag "$NEXT_VERSION"
|
||||||
|
|
||||||
|
# Push tag using token
|
||||||
|
git push "https://oauth2:${{ inputs.token }}@code.flowmade.one/${{ github.repository }}.git" "$NEXT_VERSION"
|
||||||
62
docker-build/action.yaml
Normal file
62
docker-build/action.yaml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
name: Docker Build
|
||||||
|
description: Build a Docker image with tags
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
image:
|
||||||
|
description: Full image name (registry/org/name)
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
description: Comma-separated list of tags
|
||||||
|
default: 'latest'
|
||||||
|
context:
|
||||||
|
description: Build context path
|
||||||
|
default: '.'
|
||||||
|
dockerfile:
|
||||||
|
description: Path to Dockerfile
|
||||||
|
default: 'Dockerfile'
|
||||||
|
build-args:
|
||||||
|
description: Build arguments (KEY=value, newline-separated)
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
images:
|
||||||
|
description: Built image references
|
||||||
|
value: ${{ steps.build.outputs.images }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- id: build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
IMAGE="${{ inputs.image }}"
|
||||||
|
TAGS="${{ inputs.tags }}"
|
||||||
|
CONTEXT="${{ inputs.context }}"
|
||||||
|
DOCKERFILE="${{ inputs.dockerfile }}"
|
||||||
|
BUILD_ARGS="${{ inputs.build-args }}"
|
||||||
|
|
||||||
|
# Build tag arguments
|
||||||
|
TAG_ARGS=""
|
||||||
|
IMAGES=""
|
||||||
|
IFS=',' read -ra TAG_ARRAY <<< "$TAGS"
|
||||||
|
for tag in "${TAG_ARRAY[@]}"; do
|
||||||
|
tag=$(echo "$tag" | xargs) # trim whitespace
|
||||||
|
TAG_ARGS="$TAG_ARGS -t $IMAGE:$tag"
|
||||||
|
IMAGES="$IMAGES$IMAGE:$tag,"
|
||||||
|
done
|
||||||
|
IMAGES="${IMAGES%,}" # remove trailing comma
|
||||||
|
|
||||||
|
# Build build-arg arguments
|
||||||
|
BUILD_ARG_ARGS=""
|
||||||
|
if [ -n "$BUILD_ARGS" ]; then
|
||||||
|
while IFS= read -r arg; do
|
||||||
|
if [ -n "$arg" ]; then
|
||||||
|
BUILD_ARG_ARGS="$BUILD_ARG_ARGS --build-arg $arg"
|
||||||
|
fi
|
||||||
|
done <<< "$BUILD_ARGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the image
|
||||||
|
docker build $TAG_ARGS $BUILD_ARG_ARGS -f "$DOCKERFILE" "$CONTEXT"
|
||||||
|
|
||||||
|
echo "images=$IMAGES" >> $GITHUB_OUTPUT
|
||||||
41
docker-push/action.yaml
Normal file
41
docker-push/action.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
name: Docker Push
|
||||||
|
description: Push Docker image to Forgejo Packages registry
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
image:
|
||||||
|
description: Full image name (registry/org/name)
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
description: Comma-separated list of tags to push
|
||||||
|
default: 'latest'
|
||||||
|
registry:
|
||||||
|
description: Registry URL
|
||||||
|
default: 'code.flowmade.one'
|
||||||
|
username:
|
||||||
|
description: Registry username
|
||||||
|
default: ${{ github.repository_owner }}
|
||||||
|
password:
|
||||||
|
description: Registry password/token
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- shell: bash
|
||||||
|
run: |
|
||||||
|
IMAGE="${{ inputs.image }}"
|
||||||
|
TAGS="${{ inputs.tags }}"
|
||||||
|
REGISTRY="${{ inputs.registry }}"
|
||||||
|
USERNAME="${{ inputs.username }}"
|
||||||
|
PASSWORD="${{ inputs.password }}"
|
||||||
|
|
||||||
|
# Login to registry
|
||||||
|
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
|
||||||
|
|
||||||
|
# Push each tag
|
||||||
|
IFS=',' read -ra TAG_ARRAY <<< "$TAGS"
|
||||||
|
for tag in "${TAG_ARRAY[@]}"; do
|
||||||
|
tag=$(echo "$tag" | xargs) # trim whitespace
|
||||||
|
echo "Pushing $IMAGE:$tag"
|
||||||
|
docker push "$IMAGE:$tag"
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user