1- name : Automated Release
1+ name : CI and Release
22
33on :
44 push :
55 branches : [main]
66 workflow_dispatch :
77
88jobs :
9- release :
9+ lint-backend :
1010 runs-on : ubuntu-latest
11- if : ${{ !contains(github.event.head_commit.message, '[skip-release]') }}
12- permissions :
13- contents : write
14- pull-requests : write
15-
1611 steps :
1712 - name : Check out code
1813 uses : actions/checkout@v4
14+
15+ - name : Set up Go
16+ uses : actions/setup-go@v5
1917 with :
20- fetch-depth : 0
21- token : ${{ secrets.GITHUB_TOKEN }}
18+ go-version : " 1.23.3"
19+
20+ - name : Cache Go modules
21+ uses : actions/cache@v4
22+ with :
23+ path : |
24+ ~/go/pkg/mod
25+ ~/.cache/go-build
26+ key : ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
27+ restore-keys : |
28+ ${{ runner.os }}-go-
29+
30+ - name : Install golangci-lint
31+ run : |
32+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.3
33+ echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
34+
35+ - name : Install swag for swagger generation
36+ run :
go install github.com/swaggo/swag/cmd/[email protected] 37+
38+ - name : Generate swagger docs
39+ run : |
40+ cd backend
41+ swag init -d . -g cmd/main.go -o swagger
42+
43+ - name : Run golangci-lint
44+ run : |
45+ cd backend
46+ golangci-lint run
47+
48+ - name : Verify go mod tidy
49+ run : |
50+ cd backend
51+ go mod tidy
52+ 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)
53+
54+ lint-frontend :
55+ runs-on : ubuntu-latest
56+ steps :
57+ - name : Check out code
58+ uses : actions/checkout@v4
2259
2360 - name : Set up Node.js
2461 uses : actions/setup-node@v4
2562 with :
2663 node-version : " 20"
64+ cache : " npm"
65+ cache-dependency-path : frontend/package-lock.json
2766
2867 - name : Install dependencies
2968 run : |
30- npm install -g conventional-changelog-cli
31- npm install -g semver
69+ cd frontend
70+ npm ci
71+
72+ - name : Check if prettier was run
73+ run : |
74+ cd frontend
75+ npm run format
76+ git diff --exit-code || (echo "Prettier made changes, please run 'npm run format' and commit the changes" && exit 1)
77+
78+ - name : Check if linter was run
79+ run : |
80+ cd frontend
81+ npm run lint
82+
83+ determine-version :
84+ runs-on : ubuntu-latest
85+ needs : [lint-backend, lint-frontend]
86+ if : ${{ !contains(github.event.head_commit.message, '[skip-release]') }}
87+ outputs :
88+ should_release : ${{ steps.version_bump.outputs.should_release }}
89+ new_version : ${{ steps.version_bump.outputs.new_version }}
90+ bump_type : ${{ steps.version_bump.outputs.bump_type }}
91+ steps :
92+ - name : Check out code
93+ uses : actions/checkout@v4
94+ with :
95+ fetch-depth : 0
96+
97+ - name : Set up Node.js
98+ uses : actions/setup-node@v4
99+ with :
100+ node-version : " 20"
101+
102+ - name : Install semver
103+ run : npm install -g semver
32104
33105 - name : Get current version
34106 id : current_version
35107 run : |
36- # Get the latest tag, default to 0.0.0 if no tags exist
37108 LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
38109 echo "current_version=${LATEST_TAG#v}" >> $GITHUB_OUTPUT
39110 echo "Current version: ${LATEST_TAG#v}"
@@ -102,12 +173,97 @@ jobs:
102173 echo "No version bump needed"
103174 fi
104175
176+ build-only :
177+ runs-on : ubuntu-latest
178+ needs : [lint-backend, lint-frontend]
179+ if : ${{ contains(github.event.head_commit.message, '[skip-release]') }}
180+ steps :
181+ - name : Check out code
182+ uses : actions/checkout@v4
183+
184+ - name : Set up QEMU (enables multi-arch emulation)
185+ uses : docker/setup-qemu-action@v3
186+
187+ - name : Set up Docker Buildx
188+ uses : docker/setup-buildx-action@v3
189+
190+ - name : Log in to Docker Hub
191+ uses : docker/login-action@v3
192+ with :
193+ username : ${{ secrets.DOCKERHUB_USERNAME }}
194+ password : ${{ secrets.DOCKERHUB_TOKEN }}
195+
196+ - name : Build and push SHA-only tags
197+ uses : docker/build-push-action@v5
198+ with :
199+ context : .
200+ push : true
201+ platforms : linux/amd64,linux/arm64
202+ tags : |
203+ rostislavdugin/postgresus:latest
204+ rostislavdugin/postgresus:${{ github.sha }}
205+
206+ build-and-push :
207+ runs-on : ubuntu-latest
208+ needs : [determine-version]
209+ if : ${{ needs.determine-version.outputs.should_release == 'true' }}
210+ permissions :
211+ contents : write
212+ steps :
213+ - name : Check out code
214+ uses : actions/checkout@v4
215+
216+ - name : Set up QEMU (enables multi-arch emulation)
217+ uses : docker/setup-qemu-action@v3
218+
219+ - name : Set up Docker Buildx
220+ uses : docker/setup-buildx-action@v3
221+
222+ - name : Log in to Docker Hub
223+ uses : docker/login-action@v3
224+ with :
225+ username : ${{ secrets.DOCKERHUB_USERNAME }}
226+ password : ${{ secrets.DOCKERHUB_TOKEN }}
227+
228+ - name : Build and push with version tags
229+ uses : docker/build-push-action@v5
230+ with :
231+ context : .
232+ push : true
233+ platforms : linux/amd64,linux/arm64
234+ tags : |
235+ rostislavdugin/postgresus:latest
236+ rostislavdugin/postgresus:v${{ needs.determine-version.outputs.new_version }}
237+ rostislavdugin/postgresus:${{ github.sha }}
238+
239+ - name : Update Docker Hub description
240+ uses : peter-evans/dockerhub-description@v4
241+ continue-on-error : true
242+ with :
243+ username : ${{ secrets.DOCKERHUB_USERNAME }}
244+ password : ${{ secrets.DOCKERHUB_PASSWORD }}
245+ repository : rostislavdugin/postgresus
246+ short-description : " Free PostgreSQL monitoring & backup solution with multi-storage support"
247+ readme-filepath : ./README.md
248+
249+ release :
250+ runs-on : ubuntu-latest
251+ needs : [determine-version, build-and-push]
252+ if : ${{ needs.determine-version.outputs.should_release == 'true' }}
253+ permissions :
254+ contents : write
255+ pull-requests : write
256+ steps :
257+ - name : Check out code
258+ uses : actions/checkout@v4
259+ with :
260+ fetch-depth : 0
261+ token : ${{ secrets.GITHUB_TOKEN }}
262+
105263 - name : Generate changelog
106264 id : changelog
107- if : steps.version_bump.outputs.should_release == 'true'
108265 run : |
109- CURRENT_VERSION="${{ steps.current_version.outputs.current_version }}"
110- NEW_VERSION="${{ steps.version_bump.outputs.new_version }}"
266+ NEW_VERSION="${{ needs.determine-version.outputs.new_version }}"
111267 LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
112268
113269 # Get commits since last tag
@@ -129,33 +285,28 @@ jobs:
129285 if [ -n "$line" ]; then
130286 COMMIT_MSG=$(echo "$line" | cut -d'|' -f1)
131287 COMMIT_HASH=$(echo "$line" | cut -d'|' -f2)
132- COMMIT_AUTHOR=$(echo "$line" | cut -d'|' -f3)
133- COMMIT_DATE=$(echo "$line" | cut -d'|' -f4)
134288 SHORT_HASH=${COMMIT_HASH:0:7}
135289
136290 # Parse commit message format: TYPE (area): description
137291 if [[ "$COMMIT_MSG" == FEATURE* ]]; then
138- # Extract area and description
139292 TEMP="${COMMIT_MSG#FEATURE}"
140- TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}" # trim leading spaces
293+ TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
141294 if [[ "$TEMP" == \(* ]]; then
142295 AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
143296 DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
144297 FEATURES="${FEATURES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
145298 fi
146299 elif [[ "$COMMIT_MSG" == FIX* ]]; then
147- # Extract area and description
148300 TEMP="${COMMIT_MSG#FIX}"
149- TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}" # trim leading spaces
301+ TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
150302 if [[ "$TEMP" == \(* ]]; then
151303 AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
152304 DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
153305 FIXES="${FIXES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
154306 fi
155307 elif [[ "$COMMIT_MSG" == REFACTOR* ]]; then
156- # Extract area and description
157308 TEMP="${COMMIT_MSG#REFACTOR}"
158- TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}" # trim leading spaces
309+ TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
159310 if [[ "$TEMP" == \(* ]]; then
160311 AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
161312 DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
@@ -178,58 +329,25 @@ jobs:
178329 CHANGELOG="${CHANGELOG}### 🔨 Refactoring\n${REFACTORS}\n"
179330 fi
180331
181- # Save changelog to file
182- echo -e "$CHANGELOG" > RELEASE_CHANGELOG.md
183-
184- # Update main CHANGELOG.md - preserve all version history
185- if [ -f "CHANGELOG.md" ]; then
186- # Get the header until [Unreleased] section
187- sed -n '1,/## \[Unreleased\]/p' CHANGELOG.md > NEW_CHANGELOG.md
188- echo "" >> NEW_CHANGELOG.md
189- # Add the new release (without the "# Changelog" header)
190- echo "## [${NEW_VERSION}] - $(date +%Y-%m-%d)" >> NEW_CHANGELOG.md
191- echo "" >> NEW_CHANGELOG.md
192-
193- # Add the new release sections
194- if [ -n "$FEATURES" ]; then
195- echo "### ✨ Features" >> NEW_CHANGELOG.md
196- echo -e "$FEATURES" >> NEW_CHANGELOG.md
197- fi
198-
199- if [ -n "$FIXES" ]; then
200- echo "### 🐛 Bug Fixes" >> NEW_CHANGELOG.md
201- echo -e "$FIXES" >> NEW_CHANGELOG.md
202- fi
203-
204- if [ -n "$REFACTORS" ]; then
205- echo "### 🔨 Refactoring" >> NEW_CHANGELOG.md
206- echo -e "$REFACTORS" >> NEW_CHANGELOG.md
207- fi
208-
209- # Get existing releases (everything after first ## [version] pattern)
210- sed -n '/## \[[0-9]/,$p' CHANGELOG.md >> NEW_CHANGELOG.md
211-
212- # Replace the original file
213- mv NEW_CHANGELOG.md CHANGELOG.md
214- else
215- echo -e "$CHANGELOG" > CHANGELOG.md
216- fi
332+ # Add Docker image info
333+ CHANGELOG="${CHANGELOG}### 🐳 Docker\n"
334+ CHANGELOG="${CHANGELOG}- **Image**: \`rostislavdugin/postgresus:v${NEW_VERSION}\`\n"
335+ CHANGELOG="${CHANGELOG}- **Platforms**: linux/amd64, linux/arm64\n\n"
217336
218- # Set output for GitHub release (escape newlines)
337+ # Set output for GitHub release
219338 {
220339 echo 'changelog<<EOF'
221340 echo -e "$CHANGELOG"
222341 echo EOF
223342 } >> $GITHUB_OUTPUT
224343
225344 - name : Create GitHub Release
226- if : steps.version_bump.outputs.should_release == 'true'
227345 uses : actions/create-release@v1
228346 env :
229347 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
230348 with :
231- tag_name : v${{ steps.version_bump .outputs.new_version }}
232- release_name : Release v${{ steps.version_bump .outputs.new_version }}
349+ tag_name : v${{ needs.determine-version .outputs.new_version }}
350+ release_name : Release v${{ needs.determine-version .outputs.new_version }}
233351 body : ${{ steps.changelog.outputs.changelog }}
234352 draft : false
235353 prerelease : false
0 commit comments