diff --git a/.gitea/workflows/build-deno-release.yml b/.gitea/workflows/build-deno-release.yml new file mode 100644 index 0000000..bbd656c --- /dev/null +++ b/.gitea/workflows/build-deno-release.yml @@ -0,0 +1,28 @@ +name: Build and Push Deno Release Action + +on: + push: + paths: + - deno-release/** + - .gitea/workflows/build-deno-release.yml + +jobs: + build-and-publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: | + docker build -t git.cyborggrizzly.com/bearmetal/ci-actions/deno-release:latest ./deno-release + + - name: Login to Gitea Registry + env: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + echo "$REGISTRY_TOKEN" | docker login git.cyborggrizzly.com -u "$REGISTRY_USER" --password-stdin + + - name: Push image to Gitea Registry + run: | + docker push git.cyborggrizzly.com/bearmetal/ci-actions/deno-release:latest diff --git a/deno-release/Dockerfile b/deno-release/Dockerfile new file mode 100644 index 0000000..19583e6 --- /dev/null +++ b/deno-release/Dockerfile @@ -0,0 +1,8 @@ +FROM denoland/deno:2.3.1 + +RUN apk add --no-cache zip curl bash git + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/deno-release/action.yml b/deno-release/action.yml new file mode 100644 index 0000000..cece4f0 --- /dev/null +++ b/deno-release/action.yml @@ -0,0 +1,15 @@ +name: Deno Multi-Platform Release +description: Compile a Deno CLI tool for multiple platforms and attach to a Gitea release +inputs: + entrypoint: + description: Path to the Deno entrypoint file (e.g., `src/main.ts`) + required: true + compile-flags: + description: Optional space-separated flags to pass to `deno compile` + required: false +runs: + using: "docker" + image: gitea.example.com/org/ci-actions/deno-release:latest + args: + - ${{ inputs.entrypoint }} + - ${{ inputs.compile-flags }} diff --git a/deno-release/entrypoint.sh b/deno-release/entrypoint.sh new file mode 100644 index 0000000..3f47167 --- /dev/null +++ b/deno-release/entrypoint.sh @@ -0,0 +1,136 @@ +#!/bin/bash +set -euo pipefail + +ENTRYPOINT="$1" +FLAGS_STRING="${2:-}" +IFS=' ' read -r -a DENOCOMPILE_FLAGS <<< "$FLAGS_STRING" + +TAG_NAME=$(git describe --tags --abbrev=0) +REPO_NAME=$(basename -s .git "$(git config --get remote.origin.url)") +OWNER_NAME=$(basename "$(dirname "$(git config --get remote.origin.url)")") +TMPDIR=$(mktemp -d) + +echo "Building for tag: $TAG_NAME" +echo "Using entrypoint: $ENTRYPOINT" +echo "With flags: ${DENOCOMPILE_FLAGS[*]}" + +platforms=( + "x86_64-unknown-linux-gnu" + "x86_64-pc-windows-msvc" + "x86_64-apple-darwin" +) + +for target in "${platforms[@]}"; do + echo "Compiling for $target" + outfile="${TMPDIR}/${REPO_NAME}-${target}" + [[ "$target" == *"windows"* ]] && outfile="${outfile}.exe" + + deno compile \ + --target="$target" \ + --output="$outfile" \ + "${DENOCOMPILE_FLAGS[@]}" \ + "$ENTRYPOINT" +done + +API_URL="${CI_SERVER_URL:-https://gitea.example.com}/api/v1" +RELEASE_ENDPOINT="$API_URL/repos/$OWNER_NAME/$REPO_NAME/releases" + +# Get commits since the last tag +PREV_TAG=$(git describe --tags --abbrev=0 "$TAG_NAME"^ 2>/dev/null || echo "") +if [[ -n "$PREV_TAG" ]]; then + echo "Generating changelog from $PREV_TAG to $TAG_NAME" + COMMITS=$(git log "$PREV_TAG..$TAG_NAME" --pretty=format:"%s (%an)" --no-merges) +else + echo "No previous tag found, generating changelog from initial commit" + COMMITS=$(git log --pretty=format:"%s (%an)" --no-merges) +fi + +# Group commits by type +CHANGELOG="" +append_section() { + local TYPE="$1" + local TITLE="$2" + local EMOJI="$3" + local MATCHED=$(echo "$COMMITS" | grep -E "^${TYPE}: " || true) + if [[ -n "$MATCHED" ]]; then + CHANGELOG+="## $EMOJI $TITLE\\n" + while IFS= read -r line; do + # Remove prefix (e.g., "feat: ") + local CLEANED=$(echo "$line" | sed -E "s/^${TYPE}: //") + CHANGELOG+="- $CLEANED\\n" + done <<< "$MATCHED" + CHANGELOG+="\\n" + fi +} + +append_section "feat" "Features" "โœจ" +append_section "fix" "Fixes" "๐Ÿ›" +append_section "chore" "Chores" "๐Ÿงน" +append_section "refactor" "Refactors" "๐Ÿ”ง" +append_section "docs" "Documentation" "๐Ÿ“" +append_section "test" "Tests" "๐Ÿงช" +append_section "style" "Style" "๐ŸŽจ" +append_section "ci" "CI/CD" "โš™๏ธ" + +# Escape quotes for JSON +CHANGELOG_ESCAPED=$(printf "%s" "$CHANGELOG" | sed 's/"/\\"/g') + +RELEASE_BODY="" + +if [[ -f "CHANGELOG.md" ]]; then + echo "Looking for manual changelog entry for $TAG_NAME..." + MANUAL_SECTION=$(awk "/^## \\[?$TAG_NAME\\]? /{flag=1; next} /^## /{flag=0} flag" CHANGELOG.md) + + if [[ -n "$MANUAL_SECTION" ]]; then + echo "Manual entry found for $TAG_NAME" + + if grep -q '' <<< "$MANUAL_SECTION"; then + echo "Injecting auto-changelog into manual entry" + FINAL_SECTION=$(sed "s||$CHANGELOG|" <<< "$MANUAL_SECTION") + else + FINAL_SECTION="$MANUAL_SECTION" + fi + + # Escape quotes and newlines + RELEASE_BODY=$(printf "%s" "$FINAL_SECTION" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g') + fi +fi + +# Fallback to full auto-changelog +if [[ -z "$RELEASE_BODY" ]]; then + echo "Using full auto-generated changelog" + RELEASE_BODY="$CHANGELOG_ESCAPED" +fi + + +IS_PRERELEASE="false" +if [[ "$TAG_NAME" =~ -[0-9A-Za-z] ]]; then + IS_PRERELEASE="true" +fi + +echo "Creating release $TAG_NAME (prerelease: $IS_PRERELEASE)..." + +RELEASE_JSON=$(curl -sS -X POST "$RELEASE_ENDPOINT" \ + -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d @- <