mirror of
https://github.com/tgdrive/teldrive.git
synced 2025-09-27 17:04:50 +08:00
ci: migrate build process to Taskfile
This commit is contained in:
parent
4c5d5035f7
commit
9b25f3f676
9 changed files with 317 additions and 163 deletions
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
@ -27,6 +27,12 @@ jobs:
|
|||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
|
|
|
@ -5,8 +5,8 @@ env:
|
|||
|
||||
before:
|
||||
hooks:
|
||||
- make frontend
|
||||
- make gen
|
||||
- task ui
|
||||
- task gen
|
||||
|
||||
builds:
|
||||
- env:
|
||||
|
@ -86,6 +86,8 @@ changelog:
|
|||
exclude:
|
||||
- '^README'
|
||||
- '^Update'
|
||||
- '^Version'
|
||||
- '^ci:'
|
||||
- Merge pull request
|
||||
- Merge branch
|
||||
|
||||
|
|
24
Dockerfile
24
Dockerfile
|
@ -1,24 +0,0 @@
|
|||
|
||||
FROM golang:alpine AS builder
|
||||
|
||||
RUN apk add --no-cache git unzip curl make bash
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN make build
|
||||
|
||||
FROM scratch
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY --from=builder /app/bin/teldrive /teldrive
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/teldrive","run","--tg-session-file","/session.db"]
|
137
Makefile
137
Makefile
|
@ -1,137 +0,0 @@
|
|||
ifdef ComSpec
|
||||
SHELL := powershell.exe
|
||||
IS_WINDOWS := true
|
||||
else
|
||||
SHELL := /bin/bash
|
||||
IS_WINDOWS := false
|
||||
endif
|
||||
|
||||
APP_NAME := teldrive
|
||||
BUILD_DIR := bin
|
||||
FRONTEND_DIR := ui/dist
|
||||
FRONTEND_ASSET := https://github.com/tgdrive/teldrive-ui/releases/download/latest/teldrive-ui.zip
|
||||
GIT_COMMIT := $(shell git rev-parse --short HEAD)
|
||||
GIT_LINK := $(shell git remote get-url origin)
|
||||
MODULE_PATH := $(shell go list -m)
|
||||
GOOS ?= $(shell go env GOOS)
|
||||
GOARCH ?= $(shell go env GOARCH)
|
||||
GIT_COMMIT := $(shell git rev-parse --short HEAD)
|
||||
VERSION_PACKAGE := $(MODULE_PATH)/internal/version
|
||||
BINARY_EXTENSION :=
|
||||
|
||||
ifeq ($(IS_WINDOWS),true)
|
||||
TAG_FILTER:=Sort-Object -Descending | Select-Object -First 1
|
||||
else
|
||||
TAG_FILTER:=head -n 1
|
||||
endif
|
||||
|
||||
GIT_TAG := $(shell git tag -l '[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | $(TAG_FILTER))
|
||||
|
||||
ifeq ($(IS_WINDOWS),true)
|
||||
BINARY_EXTENSION := .exe
|
||||
RM := powershell -Command "Remove-Item"
|
||||
RMDIR := powershell -Command "Remove-Item -Recurse -Force"
|
||||
MKDIR := powershell -Command "New-Item -ItemType Directory -Force"
|
||||
DOWNLOAD := powershell -Command "Invoke-WebRequest -Uri"
|
||||
UNZIP := powershell -Command "Expand-Archive"
|
||||
else
|
||||
RM := rm -f
|
||||
RMDIR := rm -rf
|
||||
MKDIR := mkdir -p
|
||||
DOWNLOAD := curl -sLO
|
||||
UNZIP := unzip -q -d
|
||||
endif
|
||||
|
||||
.PHONY: all build run clean frontend backend run sync-ui retag patch-version minor-version major-version gen check-semver install-semver
|
||||
|
||||
all: build
|
||||
|
||||
check-semver:
|
||||
ifeq ($(IS_WINDOWS),true)
|
||||
@powershell -Command "if (-not (Get-Command semver -ErrorAction SilentlyContinue)) { Write-Host 'Installing semver...'; npm install -g semver }"
|
||||
else
|
||||
@which semver > /dev/null || (echo "Installing semver..." && npm install -g semver)
|
||||
endif
|
||||
|
||||
frontend:
|
||||
@echo "Extract UI"
|
||||
$(RMDIR) $(FRONTEND_DIR)
|
||||
ifeq ($(IS_WINDOWS),true)
|
||||
$(DOWNLOAD) $(FRONTEND_ASSET) -OutFile teldrive-ui.zip
|
||||
$(MKDIR) $(subst /,\\,$(FRONTEND_DIR))
|
||||
$(UNZIP) -Path teldrive-ui.zip -DestinationPath $(FRONTEND_DIR) -Force
|
||||
$(RM) teldrive-ui.zip
|
||||
else
|
||||
$(DOWNLOAD) $(FRONTEND_ASSET)
|
||||
$(MKDIR) $(FRONTEND_DIR)
|
||||
$(UNZIP) $(FRONTEND_DIR) teldrive-ui.zip
|
||||
$(RM) teldrive-ui.zip
|
||||
endif
|
||||
|
||||
gen:
|
||||
go generate ./...
|
||||
|
||||
backend: gen
|
||||
@echo "Building backend for $(GOOS)/$(GOARCH)..."
|
||||
go build -trimpath -ldflags "-s -w -X '$(VERSION_PACKAGE).Version=$(GIT_TAG)' -X '$(VERSION_PACKAGE).CommitSHA=$(GIT_COMMIT)' -extldflags=-static" -o $(BUILD_DIR)/$(APP_NAME)$(BINARY_EXTENSION)
|
||||
|
||||
|
||||
build: frontend backend
|
||||
@echo "Building complete."
|
||||
|
||||
run:
|
||||
@echo "Running $(APP_NAME)..."
|
||||
$(BUILD_DIR)/$(APP_NAME) run
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up..."
|
||||
$(RMDIR) $(BUILD_DIR)
|
||||
ifeq ($(IS_WINDOWS),true)
|
||||
if exist "$(FRONTEND_DIR)" $(RMDIR) "$(FRONTEND_DIR)"
|
||||
else
|
||||
$(RMDIR) $(FRONTEND_DIR)
|
||||
endif
|
||||
|
||||
deps:
|
||||
@echo "Installing Go dependencies..."
|
||||
go mod download
|
||||
|
||||
retag:
|
||||
@echo "Retagging $(GIT_TAG)..."
|
||||
-git tag -d $(GIT_TAG)
|
||||
-git push --delete origin $(GIT_TAG)
|
||||
git tag -a $(GIT_TAG) -m "Recreated tag $(GIT_TAG)"
|
||||
git push origin $(GIT_TAG)
|
||||
|
||||
patch-version: check-semver
|
||||
@echo "Current version: $(GIT_TAG)"
|
||||
ifeq ($(GIT_TAG),)
|
||||
$(eval NEW_VERSION := 1.0.0)
|
||||
else
|
||||
$(eval NEW_VERSION := $(shell semver -i patch $(GIT_TAG)))
|
||||
endif
|
||||
@echo "Creating new patch version: $(NEW_VERSION)"
|
||||
git tag -a $(NEW_VERSION) -m "Release $(NEW_VERSION)"
|
||||
git push origin $(NEW_VERSION)
|
||||
|
||||
minor-version: check-semver
|
||||
@echo "Current version: $(GIT_TAG)"
|
||||
ifeq ($(GIT_TAG),)
|
||||
$(eval NEW_VERSION := 1.0.0)
|
||||
else
|
||||
$(eval NEW_VERSION := $(shell semver -i minor $(GIT_TAG)))
|
||||
endif
|
||||
@echo "Creating new minor version: $(NEW_VERSION)"
|
||||
git tag -a $(NEW_VERSION) -m "Release $(NEW_VERSION)"
|
||||
git push origin $(NEW_VERSION)
|
||||
|
||||
major-version: check-semver
|
||||
@echo "Current version: $(GIT_TAG)"
|
||||
ifeq ($(GIT_TAG),)
|
||||
$(eval NEW_VERSION := 1.0.0)
|
||||
else
|
||||
$(eval NEW_VERSION := $(shell semver -i major $(GIT_TAG)))
|
||||
endif
|
||||
@echo "Creating new major version: $(NEW_VERSION)"
|
||||
git tag -a $(NEW_VERSION) -m "Release $(NEW_VERSION)"
|
||||
git push origin $(NEW_VERSION)
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/tgdrive/teldrive
|
|||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.3.1
|
||||
github.com/WinterYukky/gorm-extra-clause-plugin v0.3.0
|
||||
github.com/coocood/freecache v1.2.4
|
||||
github.com/go-chi/chi/v5 v5.2.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -4,6 +4,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
|
|||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
|
||||
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/WinterYukky/gorm-extra-clause-plugin v0.3.0 h1:fQfTkxoRso6mlm7eOfBIk94aqamJeqxCEfU+MyLWhgo=
|
||||
github.com/WinterYukky/gorm-extra-clause-plugin v0.3.0/go.mod h1:GFT8TzxeeGKYXNU/65PsiN2+zNHigm9HjybnbL1T7eg=
|
||||
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
|
||||
|
|
104
scripts/extract.go
Normal file
104
scripts/extract.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
urlFlag := flag.String("url", "", "URL to download from")
|
||||
outputFlag := flag.String("output", "", "Output directory")
|
||||
flag.Parse()
|
||||
|
||||
if *urlFlag == "" || *outputFlag == "" {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(*outputFlag); err != nil {
|
||||
fmt.Printf("Error removing directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(*outputFlag, 0755); err != nil {
|
||||
fmt.Printf("Error creating directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
resp, err := http.Get(*urlFlag)
|
||||
if err != nil {
|
||||
fmt.Printf("Error downloading: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Printf("Bad status: %s\n", resp.Status)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "download-*.zip")
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating temp file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
defer tmpFile.Close()
|
||||
|
||||
_, err = io.Copy(tmpFile, resp.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("Error saving download: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
reader, err := zip.OpenReader(tmpFile.Name())
|
||||
if err != nil {
|
||||
fmt.Printf("Error opening zip: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
for _, file := range reader.File {
|
||||
path := filepath.Join(*outputFlag, file.Name)
|
||||
|
||||
if file.FileInfo().IsDir() {
|
||||
os.MkdirAll(path, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
|
||||
fmt.Printf("Error creating directory for file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dstFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
srcFile, err := file.Open()
|
||||
if err != nil {
|
||||
dstFile.Close()
|
||||
fmt.Printf("Error opening zip entry: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, err = io.Copy(dstFile, srcFile)
|
||||
dstFile.Close()
|
||||
srcFile.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Error extracting file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("UI Extracted successfully!")
|
||||
}
|
90
scripts/release.go
Normal file
90
scripts/release.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
versionFile = "VERSION"
|
||||
versionFlag bool
|
||||
commitFlag bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
pflag.BoolVarP(&versionFlag, "version", "v", false, "resolved version number")
|
||||
pflag.Parse()
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := release(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func release() error {
|
||||
if len(pflag.Args()) != 1 {
|
||||
return errors.New("error: expected version number")
|
||||
}
|
||||
|
||||
version, err := getVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := bumpVersion(version, pflag.Arg(0)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if versionFlag {
|
||||
fmt.Println(version)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := writeVersionFile(version); err != nil {
|
||||
return fmt.Errorf("failed to write version file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getVersion() (*semver.Version, error) {
|
||||
cmd := exec.Command("git", "tag", "-l", "[0-9]*.[0-9]*.[0-9]*", "--sort=-v:refname")
|
||||
b, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tags := strings.Split(strings.TrimSpace(string(b)), "\n")
|
||||
if len(tags) == 0 || tags[0] == "" {
|
||||
return nil, errors.New("error: no tags found")
|
||||
}
|
||||
|
||||
return semver.NewVersion(tags[0])
|
||||
}
|
||||
|
||||
func bumpVersion(version *semver.Version, verb string) error {
|
||||
switch verb {
|
||||
case "major":
|
||||
*version = version.IncMajor()
|
||||
case "minor":
|
||||
*version = version.IncMinor()
|
||||
case "patch":
|
||||
*version = version.IncPatch()
|
||||
case "current":
|
||||
// do nothing
|
||||
default:
|
||||
*version = *semver.MustParse(verb)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeVersionFile(version *semver.Version) error {
|
||||
return os.WriteFile(versionFile, []byte(version.String()), 0644)
|
||||
}
|
110
taskfile.yml
Normal file
110
taskfile.yml
Normal file
|
@ -0,0 +1,110 @@
|
|||
version: '3'
|
||||
|
||||
vars:
|
||||
APP_NAME: teldrive
|
||||
BUILD_DIR: bin
|
||||
FRONTEND_DIR: ui/dist
|
||||
FRONTEND_ASSET: https://github.com/tgdrive/teldrive-ui/releases/download/latest/teldrive-ui.zip
|
||||
GIT_COMMIT:
|
||||
sh: git rev-parse --short HEAD
|
||||
MODULE_PATH:
|
||||
sh: go list -m
|
||||
GOOS:
|
||||
sh: go env GOOS
|
||||
GOARCH:
|
||||
sh: go env GOARCH
|
||||
BINARY_EXTENSION: '{{if eq OS "windows"}}.exe{{end}}'
|
||||
|
||||
tasks:
|
||||
default:
|
||||
cmds:
|
||||
- task: ui
|
||||
- task: server
|
||||
|
||||
ui:
|
||||
desc: Download UI assets
|
||||
cmds:
|
||||
- go run scripts/extract.go -url {{.FRONTEND_ASSET}} -output {{.FRONTEND_DIR}}
|
||||
|
||||
gen:
|
||||
desc: Generate API code
|
||||
cmds:
|
||||
- go generate ./...
|
||||
|
||||
server:
|
||||
desc: Build Server
|
||||
deps: [gen]
|
||||
vars:
|
||||
VERSION:
|
||||
sh: go run scripts/release.go --version current
|
||||
cmds:
|
||||
- echo "Building backend for {{.GOOS}}/{{.GOARCH}}..."
|
||||
- >
|
||||
go build -trimpath -ldflags "-s -w
|
||||
-X '{{.MODULE_PATH}}/internal/version.Version={{.VERSION}}'
|
||||
-X '{{.MODULE_PATH}}/internal/version.CommitSHA={{.GIT_COMMIT}}'
|
||||
-extldflags=-static
|
||||
" -o {{.BUILD_DIR}}/{{.APP_NAME}}{{.BINARY_EXTENSION}}
|
||||
|
||||
run:
|
||||
desc: Run Server
|
||||
cmds:
|
||||
- ./{{.BUILD_DIR}}/{{.APP_NAME}}{{.BINARY_EXTENSION}} run
|
||||
|
||||
deps:
|
||||
desc: Install dependencies
|
||||
cmds:
|
||||
- go mod download
|
||||
- go mod tidy
|
||||
|
||||
retag:
|
||||
desc: Retag a version
|
||||
vars:
|
||||
VERSION:
|
||||
sh: go run scripts/release.go --version current
|
||||
preconditions:
|
||||
- sh: test $(git rev-parse --abbrev-ref HEAD) = "main"
|
||||
msg: "You must be on the main branch to retag"
|
||||
- sh: "[[ -z $(git diff --shortstat main) ]]"
|
||||
msg: "You must have a clean working tree to retag"
|
||||
prompt: "This will recreate tag {{.VERSION}}. Are you sure?"
|
||||
cmds:
|
||||
- echo "Retagging {{.VERSION}}..."
|
||||
- cmd: git rev-list -n 1 {{.VERSION}} || true
|
||||
silent: true
|
||||
vars:
|
||||
OLD_COMMIT: out
|
||||
- git tag -d {{.VERSION}} || true
|
||||
- git push --delete origin {{.VERSION}} || true
|
||||
- cmd: |
|
||||
if [ ! -z "{{.OLD_COMMIT}}" ]; then
|
||||
if ! git cherry-pick {{.OLD_COMMIT}}; then
|
||||
git cherry-pick --abort
|
||||
echo "Failed to cherry-pick version commit"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
- git tag -a {{.VERSION}} -m "Release {{.VERSION}}"
|
||||
- git push origin {{.VERSION}}
|
||||
- git push origin main
|
||||
|
||||
release:*:
|
||||
desc: Prepare for a new release
|
||||
vars:
|
||||
VERSION:
|
||||
sh: "go run scripts/release.go --version {{index .MATCH 0}}"
|
||||
preconditions:
|
||||
- sh: test $(git rev-parse --abbrev-ref HEAD) = "main"
|
||||
msg: "You must be on the main branch to release"
|
||||
- sh: "[[ -z $(git diff --shortstat main) ]]"
|
||||
msg: "You must have a clean working tree to release"
|
||||
prompt: "Are you sure you want to release version {{.VERSION}}?"
|
||||
cmds:
|
||||
- cmd: echo "Releasing {{.VERSION}}"
|
||||
silent: true
|
||||
- "go run scripts/release.go {{.VERSION}}"
|
||||
- "git add --all"
|
||||
- 'git commit -m "Version {{.VERSION}}"'
|
||||
- "git push"
|
||||
- "git tag {{.VERSION}}"
|
||||
- "git push origin tag {{.VERSION}}"
|
Loading…
Add table
Reference in a new issue