initial release #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }} |