feat: add application versioning to UI and implement automated release workflow via Gitea Actions
Release / release (pull_request) Successful in 1m13s

This commit is contained in:
2026-06-12 14:38:57 +01:00
parent d5b4df9d56
commit e6d34c730a
5 changed files with 87 additions and 48 deletions
-44
View File
@@ -1,44 +0,0 @@
name: Build
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build-and-push:
name: Build and Push Docker Image
runs-on: build-htz-01
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and push Docker image
run: |
docker build -t cr.jdbnet.co.uk/public/goencode:latest .
docker push cr.jdbnet.co.uk/public/goencode:latest
build-binary:
name: Build and Upload Binary
runs-on: build-htz-01
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build
run: |
go mod tidy
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o goencode ./cmd/goencode
- name: Upload to Cloudflare R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT_URL }}
run: |
aws s3 cp goencode s3://apps/goencode --endpoint-url "$R2_ENDPOINT"
+68
View File
@@ -0,0 +1,68 @@
name: Release
on:
pull_request:
branches:
- main
types: [closed]
jobs:
release:
if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'v')
runs-on: build-htz-01
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract Version
id: get_version
run: |
RAW_VERSION=${{ github.head_ref }}
CLEAN_VERSION=${RAW_VERSION#v}
echo "VERSION=${RAW_VERSION}" >> $GITHUB_OUTPUT
echo "CLEAN_VERSION=${CLEAN_VERSION}" >> $GITHUB_OUTPUT
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build Binary
run: |
go mod tidy
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.Version=${{ steps.get_version.outputs.VERSION }}" -o goencode ./cmd/goencode
- name: Build and push Docker image
run: |
docker build -t cr.jdbnet.co.uk/public/goencode:${{ steps.get_version.outputs.CLEAN_VERSION }} .
docker push cr.jdbnet.co.uk/public/goencode:${{ steps.get_version.outputs.CLEAN_VERSION }}
docker tag cr.jdbnet.co.uk/public/goencode:${{ steps.get_version.outputs.CLEAN_VERSION }} cr.jdbnet.co.uk/public/goencode:latest
docker push cr.jdbnet.co.uk/public/goencode:latest
# - name: Generate Changelog
# id: changelog
# uses: https://github.com/metcalfc/changelog-generator@v4.6.2
# with:
# myToken: ${{ secrets.GITHUB_TOKEN }}
- name: Create Gitea Release
uses: https://gitea.com/actions/gitea-release-action@v1
with:
tag_name: ${{ steps.get_version.outputs.VERSION }}
name: ${{ steps.get_version.outputs.VERSION }}
body: ${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false
files: |
goencode
- name: Upload to Cloudflare R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT_URL }}
run: |
aws s3 cp goencode s3://apps/goencode --endpoint-url "$R2_ENDPOINT"
+4 -2
View File
@@ -15,6 +15,8 @@ import (
"goencode/internal/web"
)
var Version string = "dev"
func main() {
configPath := flag.String("config", "goencode.yaml", "Path to configuration file")
flag.Parse()
@@ -44,10 +46,10 @@ func main() {
wm.Start()
defer wm.Stop()
server := web.NewServer(cfg, qm, wm, sseServer)
server := web.NewServer(cfg, qm, wm, sseServer, Version)
go func() {
log.Printf("Starting GoEncode Web UI on %s:%d", cfg.Server.ListenAddr, cfg.Server.Port)
log.Printf("Starting GoEncode Web UI (v%s) on %s:%d", Version, cfg.Server.ListenAddr, cfg.Server.Port)
if err := server.Start(); err != nil {
log.Fatalf("Server failed: %v", err)
}
+14 -2
View File
@@ -26,9 +26,10 @@ type Server struct {
sse *SSEServer
mux *http.ServeMux
sessionToken string
version string
}
func NewServer(cfg *config.Config, qm *queue.Manager, wm *watcher.Manager, sse *SSEServer) *Server {
func NewServer(cfg *config.Config, qm *queue.Manager, wm *watcher.Manager, sse *SSEServer, version string) *Server {
b := make([]byte, 32)
rand.Read(b)
token := hex.EncodeToString(b)
@@ -40,6 +41,7 @@ func NewServer(cfg *config.Config, qm *queue.Manager, wm *watcher.Manager, sse *
sse: sse,
mux: http.NewServeMux(),
sessionToken: token,
version: version,
}
s.routes()
return s
@@ -246,11 +248,13 @@ func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) {
FilesEncoded int
QueueLength int
SavedSpace string
Version string
}{
AuthEnabled: s.cfg.Auth.Username != "",
FilesEncoded: stats.FilesEncoded,
QueueLength: stats.QueueLength,
SavedSpace: formatBytes(stats.TotalSavedSpace),
Version: s.version,
}
tmpl, err := template.New("layout").Funcs(template.FuncMap{
@@ -270,7 +274,13 @@ func (s *Server) handlePage(tmplName string) http.HandlerFunc {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
data := struct{ AuthEnabled bool }{AuthEnabled: s.cfg.Auth.Username != ""}
data := struct {
AuthEnabled bool
Version string
}{
AuthEnabled: s.cfg.Auth.Username != "",
Version: s.version,
}
if err := tmpl.ExecuteTemplate(w, "layout", data); err != nil {
log.Printf("Template execution error: %v", err)
}
@@ -334,6 +344,7 @@ func (s *Server) handleHistory(w http.ResponseWriter, r *http.Request) {
FilterFolder int
Folders []db.WatchFolder
Limit int
Version string
}{
AuthEnabled: s.cfg.Auth.Username != "",
Reports: reports,
@@ -348,6 +359,7 @@ func (s *Server) handleHistory(w http.ResponseWriter, r *http.Request) {
FilterFolder: folderFilterID,
Folders: folders,
Limit: limit,
Version: s.version,
}
tmpl, err := template.New("layout").Funcs(template.FuncMap{
+1
View File
@@ -24,6 +24,7 @@
<div class="navbar-brand" style="display: flex; align-items: center;">
<img src="/static/icon.png" alt="" style="height: 1.5rem; margin-right: 0.5rem; border-radius: 4px;">
Go<span>Encode</span>
<span style="font-size: 0.75rem; font-weight: normal; margin-left: 0.5rem; color: #888; background: #2a2a2a; padding: 2px 6px; border-radius: 4px;">{{if .Version}}v{{.Version}}{{else}}vdev{{end}}</span>
</div>
<div class="nav-links">
<a href="/" id="nav-dashboard">