Skip to content

initial release

initial release #1

Workflow file for this run

name: Build and Release
on:
push:
tags:
- "v*" # Trigger on version tags like v2025-04-29.1
- "latest" # Trigger on version tag latest
permissions:
contents: write # Needed for release creation
jobs:
create-release:
name: Create Release
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
release_id: ${{ steps.create_release.outputs.id }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Get full history for release notes generation
- name: Delete existing release if it exists
id: delete_release
uses: actions/github-script@v7
with:
script: |
try {
const tagName = context.ref.replace('refs/tags/', '');
console.log(`Checking for existing release with tag: ${tagName}`);
const release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: tagName
});
console.log(`Release found with ID: ${release.data.id}, deleting...`);
await github.rest.repos.deleteRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id
});
console.log('Existing release deleted successfully');
return 'deleted';
} catch (error) {
if (error.status === 404) {
console.log('No existing release found, will create new one');
return 'not_found';
}
console.error('Error checking/deleting release:', error);
throw error;
}
- name: Get version from tag
id: get_version
run: |
TAG=${GITHUB_REF#refs/tags/}
echo "tag=$TAG" >> $GITHUB_OUTPUT
# Strip 'v' prefix if present
if [[ $TAG == v* ]]; then
VERSION=${TAG:1}
else
VERSION=$TAG
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Generate release notes
id: release_notes
run: |
# Determine previous tag for comparison
PREVIOUS_TAG=$(git describe --tags --abbrev=0 ${{ steps.get_version.outputs.tag }}^ 2>/dev/null || echo "")
if [ -z "$PREVIOUS_TAG" ]; then
echo "This is the first release, showing all commits"
COMPARE_BASE=$(git rev-list --max-parents=0 HEAD)
else
echo "Comparing with previous tag: $PREVIOUS_TAG"
COMPARE_BASE=$PREVIOUS_TAG
fi
# Get repository information for commit links
REPO_URL="https://github.com/${GITHUB_REPOSITORY}"
# Create a file for release notes
cat > release_notes.md << EOL
# Release ${{ steps.get_version.outputs.tag }}
## What's Changed
$(git log --pretty=format:"* %s ([%h]($REPO_URL/commit/%H)) - %an" $COMPARE_BASE..${{ steps.get_version.outputs.tag }} | grep -v "Merge branch")
## Install
Download the appropriate version for your platform:
- Windows: app-pemburu-komen-judol-windows-[amd64|arm64]-${{ steps.get_version.outputs.tag }}.exe
- macOS: app-pemburu-komen-judol-darwin-[amd64|arm64]-${{ steps.get_version.outputs.tag }}
- Linux: app-pemburu-komen-judol-linux-[amd64|arm64]-${{ steps.get_version.outputs.tag }}
## Configuration
1. Download .env.example and save in same folder with executable file
2. Rename .env.example to .env
3. Configure your environment variables in the .env file
4. Run the executable file
- Windows: app-pemburu-komen-judol-windows-[amd64|arm64]-${{ steps.get_version.outputs.tag }}.exe
- macOS: app-pemburu-komen-judol-darwin-[amd64|arm64]-${{ steps.get_version.outputs.tag }}
- Linux: app-pemburu-komen-judol-linux-[amd64|arm64]-${{ steps.get_version.outputs.tag }}
## System Requirements
- Google OAuth2 (Required)
- PostgreSQL database (Required)
EOL
# Output the path for the release notes file
echo "notes_file=release_notes.md" >> $GITHUB_OUTPUT
# For debugging: show the generated notes
cat release_notes.md
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2
with:
draft: false
prerelease: false
name: Release ${{ steps.get_version.outputs.tag }}
tag_name: ${{ steps.get_version.outputs.tag }}
body_path: ${{ steps.release_notes.outputs.notes_file }} # Use our custom release notes
generate_release_notes: true # Let GitHub generate release notes automatically
build-client:
name: Build Client
runs-on: ubuntu-latest
needs: create-release
env:
NODE_VERSION: "22"
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: "client/package-lock.json"
- name: Build React client
working-directory: client
run: |
npm ci
npm run build
- name: Upload client build as artifact
uses: actions/upload-artifact@v4
with:
name: client-build
path: client/dist/
retention-days: 1
prepare-env-example:
name: Prepare Environment Example
runs-on: ubuntu-latest
needs: create-release
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Copy .env.example from repository
run: |
# Create directory for artifact
mkdir -p artifact-files
# Check if server/.env.example exists and copy it
if [ -f "server/.env.example" ]; then
cp server/.env.example artifact-files/.env.example
echo "Copied .env.example from server directory"
else
echo "Warning: server/.env.example not found!"
echo "Checking alternative locations..."
# Try alternative locations
if [ -f ".env.example" ]; then
cp .env.example artifact-files/.env.example
echo "Copied .env.example from root directory"
elif [ -f "server/example.env" ]; then
cp server/example.env artifact-files/.env.example
echo "Copied example.env from server directory"
else
echo "Error: Could not find .env.example file in repository!"
exit 1
fi
fi
# Verify the file was copied
ls -la artifact-files/
echo "Content of .env.example:"
cat artifact-files/.env.example
- name: Upload .env.example as artifact
uses: actions/upload-artifact@v4
with:
name: env-example
path: artifact-files/.env.example
retention-days: 1
if-no-files-found: error
include-hidden-files: true
build:
name: Build Go Binaries
needs: [create-release, build-client]
runs-on: ubuntu-latest
env:
GO_VERSION: "1.24"
strategy:
fail-fast: false
matrix:
goos: [linux, windows, darwin]
goarch: [amd64, arm64]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: ./server/go.sum
# Debug Go environment
- name: Debug Go environment
run: |
go version
go env
# Download client build
- name: Download client build
uses: actions/download-artifact@v4
with:
name: client-build
path: client-build
# Create public directories and copy client build files
- name: Prepare public directories with client build files
run: |
# Create public directories
mkdir -p server/internal/app/public
# Copy client build files to the public directories
cp -r client-build/* server/internal/app/public/
# Check Go module structure
- name: Check Go module structure
run: |
cd server
go mod tidy
go mod verify
ls -la
if [ -f "go.mod" ]; then
echo "go.mod contents:"
cat go.mod
else
echo "go.mod not found!"
fi
# Build with populated public directories
- name: Build Go binaries
run: |
OUTPUT_DIR=output
VERSION=${{ github.ref_name }}
# Set OS-specific extension
EXT=""
if [ "${{ matrix.goos }}" = "windows" ]; then
EXT=".exe"
fi
mkdir -p $OUTPUT_DIR
cd server
# Get build metadata
COMMIT_HASH=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
GO_VERSION=$(go version | cut -d ' ' -f 3)
REPO_URL="https://github.com/${GITHUB_REPOSITORY}"
# Define ldflags properly with quoted strings
VERSION_FLAGS="-X 'github.com/rusman-plat-d/pemburu-komen-judol/server.Version=${VERSION}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.CommitHash=${COMMIT_HASH}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.BuildTime=${BUILD_TIME}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.GoVersion=${GO_VERSION}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.OS=${{ matrix.goos }}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.Arch=${{ matrix.goarch }}'"
# Add application metadata with proper quoting
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppName=Pemburu Komen Judol'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppDescription=Platform ini membantu para kreator konten mengelola kehadiran YouTube mereka, menganalisis metrik kinerja, dan memoderasi komentar secara efisien dengan kemampuan deteksi spam tingkat lanjut.'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppIcon=/public/vite.svg'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppAuthor=${GITHUB_REPOSITORY_OWNER}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppWebsite=${REPO_URL}'"
VERSION_FLAGS="${VERSION_FLAGS} -X 'github.com/rusman-plat-d/pemburu-komen-judol/server.AppRepository=${REPO_URL}'"
echo "Building app with ldflags: ${VERSION_FLAGS}"
# Build app
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 go build -v -ldflags="${VERSION_FLAGS}" -o ../$OUTPUT_DIR/app-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} cmd/app/main.go
# Build server
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 go build -v -ldflags="${VERSION_FLAGS}" -o ../$OUTPUT_DIR/server-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} cmd/server/main.go
# Build static
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 go build -v -ldflags="${VERSION_FLAGS}" -o ../$OUTPUT_DIR/static-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} cmd/static/main.go
# Upload binaries as artifacts
- name: Upload Go binaries as artifacts
uses: actions/upload-artifact@v4
with:
name: go-binaries-${{ matrix.goos }}-${{ matrix.goarch }}
path: output/
retention-days: 1
combine-and-release:
name: Combine and Release Artifacts
needs: [build, prepare-env-example]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goos: [linux, windows, darwin]
goarch: [amd64, arm64]
steps:
- name: Download client build
uses: actions/download-artifact@v4
with:
name: client-build
path: client/dist/
- name: Download Go binaries
uses: actions/download-artifact@v4
with:
name: go-binaries-${{ matrix.goos }}-${{ matrix.goarch }}
path: output/
- name: Download .env.example
uses: actions/download-artifact@v4
with:
name: env-example
path: ./artifact-files/
- name: Debug artifacts
run: |
echo "Current directory contents:"
ls -la
echo "Artifact files directory contents:"
ls -la ./artifact-files/ || echo "artifact-files directory not found"
echo "Output directory contents (if exists):"
ls -la output/ || echo "Output directory not found"
- name: Prepare unique asset filenames
id: prepare_filenames
run: |
# Create a unique suffix based on run ID
UNIQUE_SUFFIX="-run-${{ github.run_id }}"
# Set OS-specific extension
EXT=""
if [ "${{ matrix.goos }}" = "windows" ]; then
EXT=".exe"
fi
# Set output values that will be used later
echo "unique_suffix=${UNIQUE_SUFFIX}" >> $GITHUB_OUTPUT
echo "bin_ext=${EXT}" >> $GITHUB_OUTPUT
- name: Zip React build
run: |
cd client/dist
zip -r ../../output/client-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}.zip . || true
- name: Create Bundle.zip
run: |
# Use the extension from previous step
EXT="${{ steps.prepare_filenames.outputs.bin_ext }}"
UNIQUE_SUFFIX="${{ steps.prepare_filenames.outputs.unique_suffix }}"
# Copy .env.example to output directory
mkdir -p output
cp ./artifact-files/.env.example output/.env.example
cd output
# List directory contents for debugging
echo "Output directory contents before creating bundle:"
ls -la
# Create bundle zip with .env.example and unique suffix
zip -j bundle-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${UNIQUE_SUFFIX}.zip \
.env.example \
client-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${UNIQUE_SUFFIX}.zip \
app-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} \
server-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} \
static-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} || echo "Warning: Error creating bundle zip"
- name: Rename binaries with unique suffix
run: |
cd output
EXT="${{ steps.prepare_filenames.outputs.bin_ext }}"
UNIQUE_SUFFIX="${{ steps.prepare_filenames.outputs.unique_suffix }}"
# Rename each binary to include the unique suffix
mv app-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} \
app-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${UNIQUE_SUFFIX}${EXT} || true
mv server-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} \
server-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${UNIQUE_SUFFIX}${EXT} || true
mv static-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${EXT} \
static-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${UNIQUE_SUFFIX}${EXT} || true
ls -la
- name: Upload Release Assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
fail_on_unmatched_files: false
files: |
output/app-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}${{ steps.prepare_filenames.outputs.bin_ext }}
output/server-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}${{ steps.prepare_filenames.outputs.bin_ext }}
output/static-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}${{ steps.prepare_filenames.outputs.bin_ext }}
output/client-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}.zip
output/bundle-pemburu-komen-judol-${{ matrix.goos }}-${{ matrix.goarch }}-${{ github.ref_name }}${{ steps.prepare_filenames.outputs.unique_suffix }}.zip
# Simplified env example upload
upload-env:
name: Upload Environment Example
needs: [create-release, prepare-env-example]
runs-on: ubuntu-latest
steps:
- name: Download .env.example artifact
uses: actions/download-artifact@v4
with:
name: env-example
path: ./
- name: Create unique filename for env example
run: |
# Create a uniquely named copy
cp .env.example .env.example.${{ github.run_id }}
- name: Upload .env.example to release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
fail_on_unmatched_files: false
files: |
.env.example.${{ github.run_id }}