Skip to content

Merge pull request #119 from tylerobara/fix/helm_liveness_readiness #154

Merge pull request #119 from tylerobara/fix/helm_liveness_readiness

Merge pull request #119 from tylerobara/fix/helm_liveness_readiness #154

Workflow file for this run

name: CI and Release
on:
push:
branches: ["**"]
pull_request:
branches: ["**"]
workflow_dispatch:
jobs:
lint-backend:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23.3"
- name: Cache Go modules
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install golangci-lint
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.3
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- name: Install swag for swagger generation
run: go install github.com/swaggo/swag/cmd/[email protected]
- name: Generate swagger docs
run: |
cd backend
swag init -d . -g cmd/main.go -o swagger
- name: Run golangci-lint
run: |
cd backend
golangci-lint run
- name: Verify go mod tidy
run: |
cd backend
go mod tidy
git diff --exit-code go.mod go.sum || (echo "go mod tidy made changes, please run 'go mod tidy' and commit the changes" && exit 1)
lint-frontend:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: |
cd frontend
npm ci
- name: Check if prettier was run
run: |
cd frontend
npm run format
git diff --exit-code || (echo "Prettier made changes, please run 'npm run format' and commit the changes" && exit 1)
- name: Check if linter was run
run: |
cd frontend
npm run lint
test-backend:
runs-on: ubuntu-latest
needs: [lint-backend]
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23.3"
- name: Cache Go modules
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('backend/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Create .env file for testing
run: |
cd backend
cat > .env << EOF
# docker-compose.yml
DEV_DB_NAME=postgresus
DEV_DB_USERNAME=postgres
DEV_DB_PASSWORD=Q1234567
#app
ENV_MODE=development
# db
DATABASE_DSN=host=localhost user=postgres password=Q1234567 dbname=postgresus port=5437 sslmode=disable
DATABASE_URL=postgres://postgres:Q1234567@localhost:5437/postgresus?sslmode=disable
# migrations
GOOSE_DRIVER=postgres
GOOSE_DBSTRING=postgres://postgres:Q1234567@localhost:5437/postgresus?sslmode=disable
GOOSE_MIGRATION_DIR=./migrations
# testing
# to get Google Drive env variables: add storage in UI and copy data from added storage here
TEST_GOOGLE_DRIVE_CLIENT_ID=${{ secrets.TEST_GOOGLE_DRIVE_CLIENT_ID }}
TEST_GOOGLE_DRIVE_CLIENT_SECRET=${{ secrets.TEST_GOOGLE_DRIVE_CLIENT_SECRET }}
TEST_GOOGLE_DRIVE_TOKEN_JSON=${{ secrets.TEST_GOOGLE_DRIVE_TOKEN_JSON }}
# testing DBs
TEST_POSTGRES_12_PORT=5000
TEST_POSTGRES_13_PORT=5001
TEST_POSTGRES_14_PORT=5002
TEST_POSTGRES_15_PORT=5003
TEST_POSTGRES_16_PORT=5004
TEST_POSTGRES_17_PORT=5005
TEST_POSTGRES_18_PORT=5006
# testing S3
TEST_MINIO_PORT=9000
TEST_MINIO_CONSOLE_PORT=9001
# testing Azure Blob
TEST_AZURITE_BLOB_PORT=10000
# testing NAS
TEST_NAS_PORT=7006
# testing Telegram
TEST_TELEGRAM_BOT_TOKEN=${{ secrets.TEST_TELEGRAM_BOT_TOKEN }}
TEST_TELEGRAM_CHAT_ID=${{ secrets.TEST_TELEGRAM_CHAT_ID }}
EOF
- name: Start test containers
run: |
cd backend
docker compose -f docker-compose.yml.example up -d
- name: Wait for containers to be ready
run: |
# Wait for main dev database
timeout 60 bash -c 'until docker exec dev-db pg_isready -h localhost -p 5437 -U postgres; do sleep 2; done'
# Wait for test databases
timeout 60 bash -c 'until nc -z localhost 5000; do sleep 2; done'
timeout 60 bash -c 'until nc -z localhost 5001; do sleep 2; done'
timeout 60 bash -c 'until nc -z localhost 5002; do sleep 2; done'
timeout 60 bash -c 'until nc -z localhost 5003; do sleep 2; done'
timeout 60 bash -c 'until nc -z localhost 5004; do sleep 2; done'
timeout 60 bash -c 'until nc -z localhost 5005; do sleep 2; done'
# Wait for MinIO
timeout 60 bash -c 'until nc -z localhost 9000; do sleep 2; done'
# Wait for Azurite
timeout 60 bash -c 'until nc -z localhost 10000; do sleep 2; done'
- name: Create data and temp directories
run: |
# Create directories that are used for backups and restore
# These paths match what's configured in config.go
mkdir -p postgresus-data/backups
mkdir -p postgresus-data/temp
- name: Install PostgreSQL client tools
run: |
chmod +x backend/tools/download_linux.sh
cd backend/tools
./download_linux.sh
- name: Run database migrations
run: |
cd backend
go install github.com/pressly/goose/v3/cmd/goose@latest
goose up
- name: Run Go tests
run: |
cd backend
go test -p=1 -count=1 -failfast ./internal/...
- name: Stop test containers
if: always()
run: |
cd backend
docker compose -f docker-compose.yml.example down -v
determine-version:
runs-on: ubuntu-latest
needs: [test-backend, lint-frontend]
if: ${{ github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip-release]') }}
outputs:
should_release: ${{ steps.version_bump.outputs.should_release }}
new_version: ${{ steps.version_bump.outputs.new_version }}
bump_type: ${{ steps.version_bump.outputs.bump_type }}
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install semver
run: npm install -g semver
- name: Get current version
id: current_version
run: |
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "current_version=${LATEST_TAG#v}" >> $GITHUB_OUTPUT
echo "Current version: ${LATEST_TAG#v}"
- name: Analyze commits and determine version bump
id: version_bump
run: |
CURRENT_VERSION="${{ steps.current_version.outputs.current_version }}"
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
# Get commits since last tag
if [ "$LATEST_TAG" = "v0.0.0" ]; then
COMMITS=$(git log --pretty=format:"%s" --no-merges)
else
COMMITS=$(git log ${LATEST_TAG}..HEAD --pretty=format:"%s" --no-merges)
fi
echo "Analyzing commits:"
echo "$COMMITS"
# Initialize flags
HAS_FEATURE=false
HAS_FIX=false
HAS_BREAKING=false
# Analyze each commit
while IFS= read -r commit; do
if [[ "$commit" =~ ^FEATURE ]]; then
HAS_FEATURE=true
echo "Found FEATURE commit: $commit"
elif [[ "$commit" =~ ^FIX ]]; then
HAS_FIX=true
echo "Found FIX commit: $commit"
elif [[ "$commit" =~ ^REFACTOR ]]; then
HAS_FIX=true # Treat refactor as patch
echo "Found REFACTOR commit: $commit"
fi
# Check for breaking changes
if [[ "$commit" =~ BREAKING[[:space:]]CHANGE ]] || [[ "$commit" =~ "!" ]]; then
HAS_BREAKING=true
echo "Found BREAKING CHANGE: $commit"
fi
done <<< "$COMMITS"
# Determine version bump
if [ "$HAS_BREAKING" = true ]; then
BUMP_TYPE="major"
elif [ "$HAS_FEATURE" = true ]; then
BUMP_TYPE="minor"
elif [ "$HAS_FIX" = true ]; then
BUMP_TYPE="patch"
else
BUMP_TYPE="none"
fi
echo "bump_type=$BUMP_TYPE" >> $GITHUB_OUTPUT
if [ "$BUMP_TYPE" != "none" ]; then
NEW_VERSION=$(npx semver -i $BUMP_TYPE $CURRENT_VERSION)
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "should_release=true" >> $GITHUB_OUTPUT
echo "New version will be: $NEW_VERSION"
else
echo "should_release=false" >> $GITHUB_OUTPUT
echo "No version bump needed"
fi
build-only:
runs-on: ubuntu-latest
needs: [test-backend, lint-frontend]
if: ${{ github.ref == 'refs/heads/main' && contains(github.event.head_commit.message, '[skip-release]') }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up QEMU (enables multi-arch emulation)
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push SHA-only tags
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
build-args: |
APP_VERSION=dev-${{ github.sha }}
tags: |
rostislavdugin/postgresus:latest
rostislavdugin/postgresus:${{ github.sha }}
build-and-push:
runs-on: ubuntu-latest
needs: [determine-version]
if: ${{ needs.determine-version.outputs.should_release == 'true' }}
permissions:
contents: write
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up QEMU (enables multi-arch emulation)
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push with version tags
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
build-args: |
APP_VERSION=${{ needs.determine-version.outputs.new_version }}
tags: |
rostislavdugin/postgresus:latest
rostislavdugin/postgresus:v${{ needs.determine-version.outputs.new_version }}
rostislavdugin/postgresus:${{ github.sha }}
release:
runs-on: ubuntu-latest
needs: [determine-version, build-and-push]
if: ${{ needs.determine-version.outputs.should_release == 'true' }}
permissions:
contents: write
pull-requests: write
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Generate changelog
id: changelog
run: |
NEW_VERSION="${{ needs.determine-version.outputs.new_version }}"
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
# Get commits since last tag
if [ "$LATEST_TAG" = "v0.0.0" ]; then
COMMITS=$(git log --pretty=format:"%s|%H|%an|%ad" --date=short --no-merges)
else
COMMITS=$(git log ${LATEST_TAG}..HEAD --pretty=format:"%s|%H|%an|%ad" --date=short --no-merges)
fi
# Create changelog
CHANGELOG="# Changelog\n\n## [${NEW_VERSION}] - $(date +%Y-%m-%d)\n\n"
# Group commits by type and area
FEATURES=""
FIXES=""
REFACTORS=""
while IFS= read -r line; do
if [ -n "$line" ]; then
COMMIT_MSG=$(echo "$line" | cut -d'|' -f1)
COMMIT_HASH=$(echo "$line" | cut -d'|' -f2)
SHORT_HASH=${COMMIT_HASH:0:7}
# Parse commit message format: TYPE (area): description
if [[ "$COMMIT_MSG" == FEATURE* ]]; then
TEMP="${COMMIT_MSG#FEATURE}"
TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
if [[ "$TEMP" == \(* ]]; then
AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
FEATURES="${FEATURES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
fi
elif [[ "$COMMIT_MSG" == FIX* ]]; then
TEMP="${COMMIT_MSG#FIX}"
TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
if [[ "$TEMP" == \(* ]]; then
AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
FIXES="${FIXES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
fi
elif [[ "$COMMIT_MSG" == REFACTOR* ]]; then
TEMP="${COMMIT_MSG#REFACTOR}"
TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
if [[ "$TEMP" == \(* ]]; then
AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
REFACTORS="${REFACTORS}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
fi
fi
fi
done <<< "$COMMITS"
# Build changelog sections
if [ -n "$FEATURES" ]; then
CHANGELOG="${CHANGELOG}### ✨ Features\n${FEATURES}\n"
fi
if [ -n "$FIXES" ]; then
CHANGELOG="${CHANGELOG}### 🐛 Bug Fixes\n${FIXES}\n"
fi
if [ -n "$REFACTORS" ]; then
CHANGELOG="${CHANGELOG}### 🔨 Refactoring\n${REFACTORS}\n"
fi
# Add Docker image info
CHANGELOG="${CHANGELOG}### 🐳 Docker\n"
CHANGELOG="${CHANGELOG}- **Image**: \`rostislavdugin/postgresus:v${NEW_VERSION}\`\n"
CHANGELOG="${CHANGELOG}- **Platforms**: linux/amd64, linux/arm64\n\n"
# Set output for GitHub release
{
echo 'changelog<<EOF'
echo -e "$CHANGELOG"
echo EOF
} >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ needs.determine-version.outputs.new_version }}
release_name: Release v${{ needs.determine-version.outputs.new_version }}
body: ${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false