添加功能
This commit is contained in:
parent
44c7487099
commit
e0717af09b
|
@ -0,0 +1,63 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
BINARY_PREFIX: "qinglong-go_"
|
||||||
|
BINARY_SUFFIX: ""
|
||||||
|
COMMIT_ID: "${{ github.sha }}"
|
||||||
|
PR_PROMPT: "::warning:: Build artifact will not be uploaded due to the workflow is trigged by pull request."
|
||||||
|
LD_FLAGS: "-w -s"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build binary CI
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64, darwin/arm64
|
||||||
|
goos: [linux, windows, darwin]
|
||||||
|
goarch: ["386", amd64, arm, arm64]
|
||||||
|
exclude:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: arm
|
||||||
|
- goos: darwin
|
||||||
|
goarch: "386"
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
fail-fast: true
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Fetch all tags
|
||||||
|
run: git fetch --force --tags
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.18
|
||||||
|
|
||||||
|
- name: Build binary file
|
||||||
|
env:
|
||||||
|
GOOS: ${{ matrix.goos }}
|
||||||
|
GOARCH: ${{ matrix.goarch }}
|
||||||
|
IS_PR: ${{ !!github.head_ref }}
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
run: |
|
||||||
|
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
||||||
|
if $IS_PR ; then echo $PR_PROMPT; fi
|
||||||
|
export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX"
|
||||||
|
export LD_FLAGS="-w -s -X github.com/huoxue1/qinglong-go/api/system.VERSION=$COMMIT_ID"
|
||||||
|
go mod tidy
|
||||||
|
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" ./
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: ${{ !github.head_ref }}
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||||
|
path: output/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
name: docker build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Fetch all tags
|
||||||
|
run: git fetch --force --tags
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.18
|
||||||
|
-
|
||||||
|
name: Cache Go modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
id: qemu
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Check snapshot
|
||||||
|
if: "!startsWith(github.ref, 'refs/tags/')"
|
||||||
|
id: snapshot
|
||||||
|
run: echo '::set-output name=ARG::--snapshot'
|
||||||
|
-
|
||||||
|
name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v3
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: build --rm-dist --id docker ${{ steps.snapshot.outputs.ARG }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: huoxue1/qinglong-go
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest
|
||||||
|
type=ref,event=tag
|
||||||
|
-
|
||||||
|
name: Docker Login
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/386,linux/arm
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
shm-size: 2g
|
||||||
|
ulimit: core=0:0
|
|
@ -0,0 +1,29 @@
|
||||||
|
name: release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2.3.4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '1.18'
|
||||||
|
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
linters-settings:
|
||||||
|
errcheck:
|
||||||
|
ignore: fmt:.*,io/ioutil:^Read.*
|
||||||
|
ignoretests: true
|
||||||
|
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/huoxue1/qinglong-go
|
||||||
|
|
||||||
|
gocritic:
|
||||||
|
disabled-checks:
|
||||||
|
- exitAfterDefer
|
||||||
|
|
||||||
|
forbidigo:
|
||||||
|
# Forbid the following identifiers
|
||||||
|
forbid:
|
||||||
|
- ^fmt\.Errorf$ # consider errors.Errorf in github.com/pkg/errors
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
fast: true
|
||||||
|
enable:
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- depguard
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- exportloopref
|
||||||
|
- exhaustive
|
||||||
|
#- funlen
|
||||||
|
#- goconst
|
||||||
|
- gocritic
|
||||||
|
#- gocyclo
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- goprintffuncname
|
||||||
|
#- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- misspell
|
||||||
|
- nolintlint
|
||||||
|
- rowserrcheck
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
- whitespace
|
||||||
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- asciicheck
|
||||||
|
- forbidigo
|
||||||
|
- makezero
|
||||||
|
- revive
|
||||||
|
#- interfacer
|
||||||
|
|
||||||
|
# don't enable:
|
||||||
|
# - scopelint
|
||||||
|
# - gochecknoglobals
|
||||||
|
# - gocognit
|
||||||
|
# - godot
|
||||||
|
# - godox
|
||||||
|
# - goerr113
|
||||||
|
# - interfacer
|
||||||
|
# - maligned
|
||||||
|
# - nestif
|
||||||
|
# - testpackage
|
||||||
|
# - wsl
|
||||||
|
|
||||||
|
run:
|
||||||
|
# default concurrency is a available CPU number.
|
||||||
|
# concurrency: 4 # explicitly omit this value to fully utilize available resources.
|
||||||
|
deadline: 5m
|
||||||
|
issues-exit-code: 1
|
||||||
|
tests: false
|
||||||
|
|
||||||
|
# output configuration options
|
||||||
|
output:
|
||||||
|
format: "colored-line-number"
|
||||||
|
print-issued-lines: true
|
||||||
|
print-linter-name: true
|
||||||
|
uniq-by-line: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
# Fix found issues (if it's supported by the linter)
|
||||||
|
fix: true
|
||||||
|
exclude-use-default: false
|
||||||
|
exclude:
|
||||||
|
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
|
@ -0,0 +1,108 @@
|
||||||
|
env:
|
||||||
|
- GO111MODULE=on
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
|
||||||
|
- id: nowin
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
- GO111MODULE=on
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- 386
|
||||||
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
goarm:
|
||||||
|
- 7
|
||||||
|
ignore:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: arm
|
||||||
|
- goos: darwin
|
||||||
|
goarch: 386
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X main.VERSION=v{{.Version}}
|
||||||
|
- id: win
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
- GO111MODULE=on
|
||||||
|
goos:
|
||||||
|
- windows
|
||||||
|
goarch:
|
||||||
|
- 386
|
||||||
|
- amd64
|
||||||
|
goarm:
|
||||||
|
- 7
|
||||||
|
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X main.VERSION=v{{.Version}}
|
||||||
|
- id: docker
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
- GO111MODULE=on
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
- 386
|
||||||
|
- arm
|
||||||
|
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X main.VERSION=v{{.Version}}
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: "{{ .ProjectName }}_checksums.txt"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
- fix typo
|
||||||
|
- Merge pull request
|
||||||
|
- Merge branch
|
||||||
|
- Merge remote-tracking
|
||||||
|
- go mod tidy
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- id: binary
|
||||||
|
builds:
|
||||||
|
- win
|
||||||
|
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: binary
|
||||||
|
- id: nowin
|
||||||
|
builds:
|
||||||
|
- nowin
|
||||||
|
- win
|
||||||
|
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
|
||||||
|
nfpms:
|
||||||
|
- license: AGPL 3.0
|
||||||
|
homepage: https://github.com/johlanse/study_xxqg
|
||||||
|
file_name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||||
|
formats:
|
||||||
|
- deb
|
||||||
|
- rpm
|
||||||
|
maintainer: johlanse
|
||||||
|
builds:
|
||||||
|
- nowin
|
||||||
|
- win
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
FROM python:alpine
|
||||||
|
|
||||||
|
LABEL maintainer="${QL_MAINTAINER}"
|
||||||
|
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm/global/5/node_modules \
|
||||||
|
LANG=zh_CN.UTF-8 \
|
||||||
|
SHELL=/bin/bash \
|
||||||
|
PS1="\u@\h:\w \$ " \
|
||||||
|
QL_DIR=/ql \
|
||||||
|
QL_BRANCH=${QL_BRANCH}
|
||||||
|
|
||||||
|
WORKDIR ${QL_DIR}
|
||||||
|
|
||||||
|
RUN set -x \
|
||||||
|
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
|
||||||
|
&& apk update -f \
|
||||||
|
&& apk upgrade \
|
||||||
|
&& apk --no-cache add -f bash \
|
||||||
|
coreutils \
|
||||||
|
moreutils \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
tzdata \
|
||||||
|
perl \
|
||||||
|
openssl \
|
||||||
|
nodejs \
|
||||||
|
jq \
|
||||||
|
openssh \
|
||||||
|
npm \
|
||||||
|
&& rm -rf /var/cache/apk/* \
|
||||||
|
&& apk update \
|
||||||
|
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
|
&& echo "Asia/Shanghai" > /etc/timezone \
|
||||||
|
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
||||||
|
&& git config --global user.name "qinglong" \
|
||||||
|
&& git config --global http.postBuffer 524288000 \
|
||||||
|
&& npm install -g yarn \
|
||||||
|
&& rm -rf /root/.cache \
|
||||||
|
&& rm -rf /root/.npm \
|
||||||
|
|
||||||
|
COPY ./dist/docker_linux_$TARGETARCH*/qinglong-go ${QL_DIR}/qinglong-go
|
||||||
|
|
||||||
|
RUN chmod -R 777 ${QL_DIR}/qinglong-go
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
VOLUME ${QL_DIR}/data
|
||||||
|
|
||||||
|
CMD cd ${QL_DIR} && ./qinglong-go
|
|
@ -8,6 +8,10 @@ import (
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
VERSION = "UNKNOWN"
|
||||||
|
)
|
||||||
|
|
||||||
func Api(group *gin.RouterGroup) {
|
func Api(group *gin.RouterGroup) {
|
||||||
group.GET("", get())
|
group.GET("", get())
|
||||||
}
|
}
|
||||||
|
@ -18,7 +22,7 @@ func get() gin.HandlerFunc {
|
||||||
exist := os.IsNotExist(err)
|
exist := os.IsNotExist(err)
|
||||||
ctx.JSON(200, res.Ok(system.System{
|
ctx.JSON(200, res.Ok(system.System{
|
||||||
IsInitialized: !exist,
|
IsInitialized: !exist,
|
||||||
Version: "2.0.14",
|
Version: VERSION,
|
||||||
LastCommitTime: "",
|
LastCommitTime: "",
|
||||||
LastCommitId: "",
|
LastCommitId: "",
|
||||||
Branch: "master",
|
Branch: "master",
|
||||||
|
|
|
@ -16,6 +16,9 @@ import (
|
||||||
//go:embed config_sample.sh
|
//go:embed config_sample.sh
|
||||||
var sample []byte
|
var sample []byte
|
||||||
|
|
||||||
|
//go:embed package_sample.json
|
||||||
|
var pack []byte
|
||||||
|
|
||||||
func Api(group *gin.RouterGroup) {
|
func Api(group *gin.RouterGroup) {
|
||||||
group.GET("/", get())
|
group.GET("/", get())
|
||||||
group.PUT("/init", appInit())
|
group.PUT("/init", appInit())
|
||||||
|
@ -45,8 +48,11 @@ func appInit() gin.HandlerFunc {
|
||||||
_ = os.MkdirAll(path.Join("data", "log"), 0666)
|
_ = os.MkdirAll(path.Join("data", "log"), 0666)
|
||||||
_ = os.MkdirAll(path.Join("data", "repo"), 0666)
|
_ = os.MkdirAll(path.Join("data", "repo"), 0666)
|
||||||
_ = os.MkdirAll(path.Join("data", "scripts"), 0666)
|
_ = os.MkdirAll(path.Join("data", "scripts"), 0666)
|
||||||
|
_ = os.MkdirAll(path.Join("data", "deps"), 0666)
|
||||||
|
_ = os.MkdirAll(path.Join("data", "raw"), 0666)
|
||||||
_ = os.WriteFile(path.Join("data", "config", "config.sh"), sample, 0666)
|
_ = os.WriteFile(path.Join("data", "config", "config.sh"), sample, 0666)
|
||||||
_ = os.WriteFile(path.Join("data", "config", "config_sample.sh"), sample, 0666)
|
_ = os.WriteFile(path.Join("data", "scripts", "package.json"), pack, 0666)
|
||||||
|
_ = os.WriteFile(path.Join("data", "config", "config.sample.sh"), sample, 0666)
|
||||||
type Req struct {
|
type Req struct {
|
||||||
UserName string `json:"username"`
|
UserName string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
version: "3.5"
|
||||||
|
services:
|
||||||
|
xuexi-auto:
|
||||||
|
image: huoxue1/qinglong-go:latest
|
||||||
|
# 容器名
|
||||||
|
container_name: qinglong-go
|
||||||
|
environment:
|
||||||
|
# 时区
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
# 配置文件路径
|
||||||
|
volumes:
|
||||||
|
- ./data:/ql/data
|
||||||
|
# 映射端口
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
restart: unless-stopped
|
4
main.go
4
main.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
nested "github.com/Lyrics-you/sail-logrus-formatter/sailor"
|
nested "github.com/Lyrics-you/sail-logrus-formatter/sailor"
|
||||||
"github.com/huoxue1/qinglong-go/controller"
|
"github.com/huoxue1/qinglong-go/controller"
|
||||||
|
"github.com/huoxue1/qinglong-go/service"
|
||||||
rotates "github.com/lestrrat-go/file-rotatelogs"
|
rotates "github.com/lestrrat-go/file-rotatelogs"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
w, err := rotates.New(path.Join("data", "logs", "%Y-%m-%d.log"), rotates.WithRotationTime(time.Hour*24))
|
w, err := rotates.New(path.Join("data", "log", "qinglong-go", "%Y-%m-%d.log"), rotates.WithRotationTime(time.Hour*24))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("rotates init err: %v", err)
|
log.Errorf("rotates init err: %v", err)
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -36,6 +37,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
service.AppInit()
|
||||||
engine := controller.Router()
|
engine := controller.Router()
|
||||||
_ = engine.Run(":8080")
|
_ = engine.Run(":8080")
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,13 @@ func QueryRunningCron() ([]*Crontabs, error) {
|
||||||
return crontabs, err
|
return crontabs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func QueryCronByDir(dir string) ([]*Crontabs, error) {
|
||||||
|
crontabs := make([]*Crontabs, 0)
|
||||||
|
session := engine.Table(new(Crontabs)).Where(builder.Like{"command", "task " + dir + "%"})
|
||||||
|
err := session.Find(&crontabs)
|
||||||
|
return crontabs, err
|
||||||
|
}
|
||||||
|
|
||||||
func FindAllEnableCron() []*Crontabs {
|
func FindAllEnableCron() []*Crontabs {
|
||||||
crontabs := make([]*Crontabs, 0)
|
crontabs := make([]*Crontabs, 0)
|
||||||
err := engine.Table(new(Crontabs)).Where("isdisabled=?", 0).Find(&crontabs)
|
err := engine.Table(new(Crontabs)).Where("isdisabled=?", 0).Find(&crontabs)
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/huoxue1/qinglong-go/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AppInit() {
|
||||||
|
go runYarn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func runYarn() {
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
}()
|
||||||
|
_, err := os.Stat(path.Join("data", "scripts", "package.json"))
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch := make(chan int, 1)
|
||||||
|
utils.RunTask(context.WithValue(context.Background(), "cancel", ch), "yarn install", map[string]string{}, func(ctx context.Context) {
|
||||||
|
log.Infoln("开始执行yarn初始化!")
|
||||||
|
}, func(ctx context.Context) {
|
||||||
|
log.Infoln("yarn初始化执行完成!")
|
||||||
|
}, os.Stdout)
|
||||||
|
}
|
|
@ -129,16 +129,28 @@ func runCron(crontabs *models.Crontabs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddTask(crontabs *models.Crontabs) {
|
func AddTask(crontabs *models.Crontabs) {
|
||||||
c := cron.New()
|
crons := strings.Split(crontabs.Schedule, " ")
|
||||||
|
var c *cron.Cron
|
||||||
|
if len(crons) == 5 {
|
||||||
|
c = cron.New()
|
||||||
|
|
||||||
|
} else if len(crons) == 6 {
|
||||||
|
c = cron.New(cron.WithParser(
|
||||||
|
cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)))
|
||||||
|
} else {
|
||||||
|
log.Errorf("the task %s cron %s is error", crontabs.Name, crontabs.Command)
|
||||||
|
return
|
||||||
|
}
|
||||||
_, err := c.AddFunc(crontabs.Schedule, func() {
|
_, err := c.AddFunc(crontabs.Schedule, func() {
|
||||||
runCron(crontabs)
|
runCron(crontabs)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("添加task错误" + err.Error())
|
log.Errorln("添加task错误" + crontabs.Schedule + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Start()
|
c.Start()
|
||||||
manager.Store(crontabs.Id, c)
|
manager.Store(crontabs.Id, c)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handCommand(command string) *task {
|
func handCommand(command string) *task {
|
||||||
|
@ -189,32 +201,3 @@ func handCommand(command string) *task {
|
||||||
}
|
}
|
||||||
return ta
|
return ta
|
||||||
}
|
}
|
||||||
|
|
||||||
//type myWriter struct {
|
|
||||||
// fileName string
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (m *myWriter) Write(p []byte) (n int, err error) {
|
|
||||||
// file, _ := os.OpenFile(m.fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
|
||||||
// n, err = file.Write(p)
|
|
||||||
// file.Close()
|
|
||||||
// return n, err
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
////通过管道同步获取日志的函数
|
|
||||||
//func syncLog(reader io.ReadCloser, writer io.Writer) {
|
|
||||||
// buf := make([]byte, 1)
|
|
||||||
// for {
|
|
||||||
// strNum, err := reader.Read(buf)
|
|
||||||
// if strNum > 0 {
|
|
||||||
// outputByte := buf[:strNum]
|
|
||||||
// writer.Write(outputByte)
|
|
||||||
// }
|
|
||||||
// if err != nil {
|
|
||||||
// //读到结尾
|
|
||||||
// if err == io.EOF || strings.Contains(err.Error(), "file already closed") {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/huoxue1/qinglong-go/service/config"
|
"github.com/huoxue1/qinglong-go/service/config"
|
||||||
"github.com/huoxue1/qinglong-go/service/cron"
|
"github.com/huoxue1/qinglong-go/service/cron"
|
||||||
"github.com/huoxue1/qinglong-go/utils"
|
"github.com/huoxue1/qinglong-go/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -45,12 +46,60 @@ func downloadFiles(subscriptions *models.Subscriptions) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
addScripts(subscriptions)
|
if config.GetKey("AutoAddCron") == "true" {
|
||||||
|
addScripts(subscriptions)
|
||||||
|
} else {
|
||||||
|
log.Infoln("未配置自动添加定时任务,不添加任务!")
|
||||||
|
}
|
||||||
|
|
||||||
file, _ := os.OpenFile(subscriptions.LogPath, os.O_APPEND|os.O_RDWR, 0666)
|
file, _ := os.OpenFile(subscriptions.LogPath, os.O_APPEND|os.O_RDWR, 0666)
|
||||||
file.WriteString(fmt.Sprintf("\n##执行结束.. %s,耗时0秒\n\n", time.Now().Format("2006-01-02 15:04:05")))
|
file.WriteString(fmt.Sprintf("\n##执行结束.. %s,耗时0秒\n\n", time.Now().Format("2006-01-02 15:04:05")))
|
||||||
_ = file.Close()
|
_ = file.Close()
|
||||||
subscriptions.Status = 1
|
subscriptions.Status = 1
|
||||||
models.UpdateSubscription(subscriptions)
|
models.UpdateSubscription(subscriptions)
|
||||||
|
} else if subscriptions.Type == "file" {
|
||||||
|
addRawFiles(subscriptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addRawFiles(subscriptions *models.Subscriptions) {
|
||||||
|
subscriptions.LogPath = "data/log/" + time.Now().Format("2006-01-02") + "/" + subscriptions.Alias + "_" + uuid.New().String() + ".log"
|
||||||
|
subscriptions.Status = 0
|
||||||
|
file, _ := os.OpenFile(subscriptions.LogPath, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
|
defer file.Close()
|
||||||
|
_ = models.UpdateSubscription(subscriptions)
|
||||||
|
defer func() {
|
||||||
|
subscriptions.Status = 1
|
||||||
|
_ = models.UpdateSubscription(subscriptions)
|
||||||
|
}()
|
||||||
|
err := utils.DownloadFile(subscriptions.Url, path.Join("data", "raw", subscriptions.Alias))
|
||||||
|
if err != nil {
|
||||||
|
_, _ = file.WriteString(err.Error() + "\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name, c, err := getSubCron(path.Join("data", "raw", subscriptions.Alias))
|
||||||
|
if err != nil {
|
||||||
|
_, _ = file.WriteString(err.Error() + "\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
utils.Copy(path.Join("data", "raw", subscriptions.Alias), path.Join("data", "scripts", subscriptions.Alias))
|
||||||
|
if c != "" {
|
||||||
|
command, err := models.GetCronByCommand(fmt.Sprintf("task %s", subscriptions.Alias))
|
||||||
|
if err != nil {
|
||||||
|
file.WriteString("已添加新的定时任务 " + name + "\n")
|
||||||
|
_, _ = cron.AddCron(&models.Crontabs{
|
||||||
|
Name: name,
|
||||||
|
Command: fmt.Sprintf("task %s", subscriptions.Alias),
|
||||||
|
Schedule: c,
|
||||||
|
Timestamp: time.Now().Format("Mon Jan 02 2006 15:04:05 MST"),
|
||||||
|
Status: 1,
|
||||||
|
Labels: []string{},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
command.Name = name
|
||||||
|
command.Schedule = c
|
||||||
|
_ = cron.UpdateCron(command)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +147,11 @@ func addScripts(subscriptions *models.Subscriptions) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
crontabs, _ := models.QueryCronByDir(subscriptions.Alias)
|
||||||
|
cronMap := make(map[string]*models.Crontabs, len(crontabs))
|
||||||
|
for _, crontab := range crontabs {
|
||||||
|
cronMap[crontab.Command] = crontab
|
||||||
|
}
|
||||||
for _, entry := range dir {
|
for _, entry := range dir {
|
||||||
// 判断文件后缀
|
// 判断文件后缀
|
||||||
if !utils.In(strings.TrimPrefix(filepath.Ext(entry.Name()), "."), extensions) {
|
if !utils.In(strings.TrimPrefix(filepath.Ext(entry.Name()), "."), extensions) {
|
||||||
|
@ -128,6 +182,7 @@ func addScripts(subscriptions *models.Subscriptions) {
|
||||||
command.Name = name
|
command.Name = name
|
||||||
command.Schedule = c
|
command.Schedule = c
|
||||||
_ = cron.UpdateCron(command)
|
_ = cron.UpdateCron(command)
|
||||||
|
delete(cronMap, command.Command)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -139,6 +194,12 @@ func addScripts(subscriptions *models.Subscriptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if config.GetKey("AutoDelCron") == "true" {
|
||||||
|
for _, m := range cronMap {
|
||||||
|
file.WriteString("已删除失效的任务 " + m.Name + "\n")
|
||||||
|
models.DeleteCron(m.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSubCron(filePath string) (name string, cron string, err error) {
|
func getSubCron(filePath string) (name string, cron string, err error) {
|
||||||
|
@ -159,5 +220,6 @@ func getSubCron(filePath string) (name string, cron string, err error) {
|
||||||
} else {
|
} else {
|
||||||
return "", "", errors.New("not found cron")
|
return "", "", errors.New("not found cron")
|
||||||
}
|
}
|
||||||
|
cron = strings.TrimPrefix(cron, " ")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package utils
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -48,3 +49,31 @@ func Copy(src, dest string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DownloadFile(url, filePath string) error {
|
||||||
|
response, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
}(response.Body)
|
||||||
|
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
_, err = io.Copy(file, response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue