diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..af65798 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,37 @@ +name: build +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + env: + GOPROXY: direct + steps: + - name: install packages + run: | + sudo apt update + sudo apt -y install libayatana-appindicator3-dev libappindicator3-dev libgtk-3-dev + - uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - uses: actions/setup-go@v2 + with: + go-version: 1.16 + - name: cache + uses: actions/cache@v2.1.6 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: | + ${{ runner.os }}-build-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-build-${{ hashFiles('**/go.mod') }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: build + run: | + go generate + VER=$(go run version_generate.go) + go build -buildmode=pie -trimpath -ldflags "-s -w -buildid= -X main.version=$VER" + go build -buildmode=pie -trimpath -ldflags "-s -w -buildid= -X main.version=$VER" -tags legacyappindicator diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 0000000..ef362f6 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,38 @@ +name: codecov +on: [push] +jobs: + codecov: + name: codecov + runs-on: ubuntu-latest + env: + GOPROXY: direct + steps: + - name: install packages + run: | + sudo apt update + sudo apt -y install libayatana-appindicator3-dev libappindicator3-dev libgtk-3-dev + - uses: actions/checkout@v2.4.0 + - uses: actions/setup-go@v2 + with: + go-version: 1.16 + - name: cache + uses: actions/cache@v2.1.6 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: | + ${{ runner.os }}-build-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-build-${{ hashFiles('**/go.mod') }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: vet + run: | + go generate + go vet ./... + - name: generate report + run: | + go test -v -race -coverprofile=coverage.txt -covermode=atomic ./... + - name: upload coverage report + uses: codecov/codecov-action@v2.1.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0ed6656 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,84 @@ +name: release + +on: + push: + tags: + - "v*" + +jobs: + release: + runs-on: ubuntu-latest + env: + GOPROXY: direct + steps: + - name: install packages + run: | + sudo apt update + sudo apt -y install libayatana-appindicator3-dev libappindicator3-dev libgtk-3-dev + - uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - uses: actions/setup-go@v2 + with: + go-version: 1.16 + + - name: install changelog + run: | + go install evgenykuznetsov.org/go/changelog/cmd/changelog@latest + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + + - name: install fpm + run: gem install fpm + + - name: build packages + run: | + git fetch --tags --force + mkdir release + changelog -n "Evgeny Kuznetsov" -e "evgeny@kuznetsov.md" -p "matebook-applet" CHANGELOG.md + go generate + VER=$(go run version_generate.go) + go build -buildmode=pie -trimpath -ldflags "-s -w -buildid= -X main.version=$VER" -tags legacyappindicator + tar -czf release/matebook-applet-amd64-$VER-legacy.tar.gz matebook-applet LICENSE README.md CHANGELOG.md SOURCE.txt + go build -buildmode=pie -trimpath -ldflags "-s -w -buildid= -X main.version=$VER" + tar -czf release/matebook-applet-amd64-$VER.tar.gz matebook-applet LICENSE README.md CHANGELOG.md SOURCE.txt + fpm -t deb -s dir \ + -d libayatana-appindicator3-1 \ + -d libc6 \ + -d "libgtk-3-0 >= 3.10" \ + --deb-recommends huawei-wmi \ + -a amd64 \ + -n matebook-applet -v $VER \ + -m "Evgeny Kuznetsov " \ + --deb-changelog debian.changelog \ + --license GPL-3 \ + --deb-priority optional \ + --url https://evgenykuznetsov.org/go/matebook-applet \ + --category misc \ + --vendor "Evgeny Kuznetsov " \ + --description "System tray applet for Huawei MateBook\nAllows one to control Huawei MateBook features,\nlike Fn-Lock and Battery Protection settings, via GUI." \ + LICENSE=/usr/share/doc/matebook-applet/ \ + README.md=/usr/share/doc/matebook-applet/ \ + SOURCE.txt=/usr/share/doc/matebook-applet \ + matebook-applet=/usr/bin/ \ + matebook-applet.1=/usr/share/man/man1/ \ + assets/matebook-applet.png=/usr/share/icons/hicolor/512x512/apps/ \ + matebook-applet.desktop=/usr/share/applications/ + mv *.deb release/ + - name: release + uses: marvinpinto/action-automatic-releases@v1.2.1 + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: false + files: "release/*" + + - name: trigger repository update + uses: appleboy/ssh-action@v0.1.4 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_KEY }} + script: matebook-applet diff --git a/.gitignore b/.gitignore index f9cbb0a..5485d28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,8 @@ matebook-applet -*.asc -*.sig .*.swp *.tar.gz *.deb assets.go debian.changelog -secrets.tar coverage.txt -id_rsa /release/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 59276e8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,98 +0,0 @@ -language: go - -go: - - 1.15.x - -os: linux - -dist: bionic - -addons: - apt: - packages: - - libayatana-appindicator3-dev - - libappindicator3-dev - - libgtk-3-dev - - aptly - - gnupg1 - - rsync - -env: - - GO111MODULE=on - -before_install: - -install: - - echo "not using Travis's builtin logic to install Go dependencies, it's broken" - -before_script: - - go generate - - go vet ./... - - git reset --hard - -script: - - go test -v -race -coverprofile=coverage.txt -covermode=atomic ./... - - go run build.go - -before_deploy: - - > - if ! [ "$BEFORE_DEPLOY_RUN" ]; then - export BEFORE_DEPLOY_RUN=1; - openssl aes-256-cbc -K $encrypted_3b9f0b9d36d1_key -iv $encrypted_3b9f0b9d36d1_iv -in secrets.tar.enc -out secrets.tar -d; - tar xvf secrets.tar; - mv id_rsa ~/.ssh/; - cat .known_hosts >> $HOME/.ssh/known_hosts; - gpg --batch --passphrase $GPG_PASSPHRASE --pinentry-mode loopback --import gpgsecret.asc; - echo -e "5\ny\n" | gpg --command-fd 0 --expert --edit-key FA32B7DDA1A3AC2C trust; - gem install fpm; - gpg1 --no-default-keyring --keyring trustedkeys.gpg --import matebook-applet.key; - aptly mirror create repo http://evgenykuznetsov.org/repo buster; - aptly mirror update repo; - aptly repo create -distribution="buster" matebook-applet; - aptly repo import repo matebook-applet Name; - git reset --hard; - mkdir release; - fi - -deploy: - - provider: script - script: rvm default do go run release.go - on: - tags: true - skip_cleanup: true - - provider: script - script: go run release.go -c - on: - condition: $TRAVIS_EVENT_TYPE = cron - - provider: releases - api_key: $GITHUB_TOKEN - file_glob: true - file: release/* - skip_cleanup: true - on: - tags: true - -cache: - directories: - - $HOME/.cache/go-build - - $HOME/gopath/pkg/mod - -after_success: - - export CODECOV_NEEDED=1 - -after_script: - - > - if [ "$CODECOV_NEEDED" ]; then - export GITHUB_TOKEN=""; - export GPG_PASSPHRASE=""; - export encrypted_3b9f0b9d36d1_key=""; - export encrypted_3b9f0b9d36d1_iv=""; - rm $HOME/.ssh/id_rsa; - rm gpgsecret.asc; - rm secrets.tar; - bash <(curl -s https://codecov.io/bash); - fi - -branches: - except: - - /^dependabot\/.*$/ diff --git a/README.md b/README.md index 2f38f26..6bab16a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # matebook-applet System tray applet/control app for Huawei Matebook -[![Build Status](https://travis-ci.com/nekr0z/matebook-applet.svg?branch=master)](https://travis-ci.com/nekr0z/matebook-applet) [![codecov](https://codecov.io/gh/nekr0z/matebook-applet/branch/master/graph/badge.svg)](https://codecov.io/gh/nekr0z/matebook-applet) [![Go Report Card](https://goreportcard.com/badge/evgenykuznetsov.org/go/matebook-applet)](https://goreportcard.com/report/evgenykuznetsov.org/go/matebook-applet) +![Build Status](https://github.com/nekr0z/matebook-applet/actions/workflows/build.yml/badge.svg) [![codecov](https://codecov.io/gh/nekr0z/matebook-applet/branch/master/graph/badge.svg)](https://codecov.io/gh/nekr0z/matebook-applet) [![Go Report Card](https://goreportcard.com/badge/evgenykuznetsov.org/go/matebook-applet)](https://goreportcard.com/report/evgenykuznetsov.org/go/matebook-applet) --- @@ -130,9 +130,10 @@ You can always download precompiled amd64 binary from the [releases page](https: $ git clone https://github.com/nekr0z/matebook-applet.git $ cd matebook-applet - $ go run build.go + $ go generate + $ go build -To build against `libappindicator` instead, append the last command with the `-l` switch. +To build against `libappindicator` instead, append the last command with `-tags legacyappindicator`. ## Usage The user interface is intentionally as simple as they get. You get an icon in system tray that you can click and get a menu. The menu consists of current status, options to change it, and an option to quit the applet. Please be aware that the applet does not probe for current status on its own (this is intentional), so if you change your battery protection settings by other means it will not reflect the change. Clicking on the status line (top of the menu) updates it. diff --git a/build.go b/build.go deleted file mode 100644 index 44086f3..0000000 --- a/build.go +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (C) 2019 Evgeny Kuznetsov (evgeny@kuznetsov.md) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build ignore - -package main - -import ( - "archive/tar" - "bufio" - "bytes" - "compress/gzip" - "flag" - "fmt" - "io" - "log" - "os" - "os/exec" - "regexp" - "strconv" - "strings" - "time" - - "github.com/nekr0z/changelog" -) - -type packFile struct { - src string - dst string - mod os.FileMode -} - -type distFile struct { - src string - dst string -} - -var ( - filename string - keyID string = "FA32B7DDA1A3AC2C" - packFiles = []packFile{ - {src: "LICENSE", dst: "LICENSE", mod: 0644}, - {src: "README.md", dst: "README.md", mod: 0644}, - {src: "SOURCE.txt", dst: "SOURCE.txt", mod: 0644}, - {src: "matebook-applet.1", dst: "matebook-applet.1", mod: 0644}, - {src: "CHANGELOG.md", dst: "CHANGELOG.md", mod: 0644}, - } - distFiles = []distFile{ - {src: "LICENSE", dst: "/usr/share/doc/matebook-applet/"}, - {src: "README.md", dst: "/usr/share/doc/matebook-applet/"}, - {src: "SOURCE.txt", dst: "/usr/share/doc/matebook-applet/"}, - {src: "matebook-applet.1", dst: "/usr/share/man/man1/"}, - {src: "matebook-applet.desktop", dst: "/usr/share/applications/"}, - {src: "assets/matebook-applet.png", dst: "/usr/share/icons/hicolor/512x512/apps/"}, - } - debDeps = []string{ - "libayatana-appindicator3-1", - "libc6", - "libgtk-3-0 >= 3.10", - } - debRecs = []string{ - "huawei-wmi", - } -) - -func main() { - sign := flag.Bool("s", false, "sign binary") - tar := flag.Bool("t", false, "generate tar.gz") - deb := flag.Bool("d", false, "build .deb") - legacy := flag.Bool("l", false, "build against libappindicator") - flag.Parse() - version := getVersion() - if *legacy { - version = version + "-legacy" - } - btime := buildTime() - if *tar { - *sign = true - } - - fmt.Printf("Building version %s\n", version) - fmt.Println("Building as of", time.Unix(btime, 0)) - buildAssets(btime) - buildBinary(version, btime) - - if *sign { - signFile("matebook-applet", keyID) - } - - if *tar { - filename = "matebook-applet-amd64" + "-" + version - buildTar() - fmt.Println("archive", filename, "created") - } - - if *deb { - buildDeb(version) - } -} - -func buildBinary(version string, t int64) { - cmdline := fmt.Sprintf("go build -buildmode=pie -trimpath -ldflags=\"-s -w -buildid= -X main.version=%s\"", version) - if strings.HasSuffix(version, "-legacy") { - cmdline = cmdline + " -tags legacyappindicator" - } - cmd := exec.Command("bash", "-c", cmdline) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stdout - if err := cmd.Run(); err != nil { - log.Fatalln("failed to build binary") - } - setFileTime("matebook-applet", t) - packFiles = append(packFiles, packFile{"matebook-applet", "matebook-applet", 0755}) - distFiles = append(distFiles, distFile{"matebook-applet", "/usr/bin/"}) -} - -func buildAssets(t int64) { - cmd := exec.Command("go", "run", "assets_generate.go") - if err := cmd.Run(); err != nil { - log.Fatalln("failed to rebuild assets") - } - setFileTime("assets.go", t) -} - -func buildDeb(ver string) { - maintainer := changelog.Maintainer{Name: "Evgeny Kuznetsov", Email: "evgeny@kuznetsov.md"} - var clok bool - fd, err := os.Open("CHANGELOG.md") - if err != nil { - fmt.Printf("error opening changelog: %s\n", err) - } else { - defer fd.Close() - cl, err := changelog.ParseMd(fd) - if err != nil { - fmt.Printf("error parsing changelog: %s\n", err) - } - cmd := exec.Command("git", "tag", "-l", `--format=%(creatordate:iso)|%(refname:short)`) - var bb bytes.Buffer - out := bufio.NewWriter(&bb) - cmd.Stdout = out - if err := cmd.Run(); err != nil { - fmt.Printf("failed to read tag times: %s", err) - } else { - out.Flush() - scanner := bufio.NewScanner(&bb) - for scanner.Scan() { - line := scanner.Text() - s := strings.Split(line, "|") - if len(s) == 2 { - d, err := time.Parse("2006-01-02 15:04:05 -0700", s[0]) - if err == nil { - ver, err := changelog.ToVersion(strings.TrimPrefix(s[1], "v")) - if err == nil { - rel := cl[ver] - rel.Date = d - cl[ver] = rel - } - } - } - } - } - for v, rel := range cl { - rel.Maintainer = maintainer - cl[v] = rel - } - b, err := cl.Debian("matebook-applet") - if err != nil { - fmt.Printf("error converting changelog to Debian format: %s\n", err) - } - clDeb, err := os.Create("debian.changelog") - if err != nil { - fmt.Printf("error creating Debian changelog: %s\n", err) - } else { - defer clDeb.Close() - _, err := clDeb.Write(b) - if err != nil { - fmt.Printf("error writing Debian changelog: %s\n", err) - } - clDeb.Sync() - clok = true - } - } - ver = strings.Replace(strings.TrimPrefix(ver, "v"), "-", "~", 1) - args := []string{ - "-f", - "-t", "deb", - "-s", "dir", - "-n", "matebook-applet", - "-v", ver, - "-m", fmt.Sprintf("%s <%s>", maintainer.Name, maintainer.Email), - "--vendor", fmt.Sprintf("%s <%s>", maintainer.Name, maintainer.Email), - "--category", "misc", - "--description", "System tray applet for Huawei MateBook\nAllows one to control Huawei MateBook features,\nlike Fn-Lock and Battery Protection settings, via GUI.", - "--url", "https://github.com/nekr0z/matebook-applet", - "--license", "GPL-3", - "--deb-priority", "optional", - } - if clok { - args = append(args, "--deb-changelog", "debian.changelog") - } - for _, dep := range debDeps { - args = append(args, "-d", dep) - } - for _, rec := range debRecs { - args = append(args, "--deb-recommends", rec) - } - for _, file := range distFiles { - arg := file.src + "=" + file.dst - args = append(args, arg) - } - cmd := exec.Command("fpm", args...) - if err := cmd.Run(); err != nil { - fmt.Println(err) - log.Fatalln("failed to build .deb") - } - fmt.Println(".deb package created") -} - -func buildTar() { - for i := range packFiles { - packFiles[i].dst = filename + "/" + packFiles[i].dst - } - filename = filename + ".tar.gz" - fd, err := os.Create(filename) - if err != nil { - log.Fatal(err) - } - gw, err := gzip.NewWriterLevel(fd, gzip.BestCompression) - if err != nil { - log.Fatal(err) - } - tw := tar.NewWriter(gw) - for _, f := range packFiles { - sf, err := os.Open(f.src) - if err != nil { - log.Fatal(err) - } - info, err := sf.Stat() - if err != nil { - log.Fatal(err) - } - h := &tar.Header{ - Name: f.dst, - Size: info.Size(), - Mode: int64(f.mod), - ModTime: info.ModTime(), - } - err = tw.WriteHeader(h) - if err != nil { - log.Fatal(err) - } - _, err = io.Copy(tw, sf) - if err != nil { - log.Fatal(err) - } - sf.Close() - } - err = tw.Close() - if err != nil { - log.Fatal(err) - } - err = gw.Close() - if err != nil { - log.Fatal(err) - } - err = fd.Close() - if err != nil { - log.Fatal(err) - } -} - -func setFileTime(f string, t int64) { - cmd := exec.Command("touch", "-t", fmt.Sprint(time.Unix(t, 0).Format("200601021504.05")), f) - if err := cmd.Run(); err != nil { - log.Fatalln("failed to set time on", f) - } -} - -func signFile(f string, k string) { - cmd := exec.Command("gpg", "--detach-sign", "--yes", "--passphrase", os.Getenv("GPG_PASSPHRASE"), "--pinentry-mode", "loopback", "-a", "-u", k, f) - cmd.Stderr = os.Stdout - cmd.Stdout = os.Stdout - if err := cmd.Run(); err != nil { - fmt.Println("signing", f, "failed") - filename = filename + "-unsigned" - } else { - fmt.Println(f, "successfully signed with key", k) - packFiles = append(packFiles, packFile{"matebook-applet.asc", "matebook-applet.asc", 0644}) - } -} - -func getVersion() string { - desc, err1 := getString("git", "describe", "--always", "--dirty") - br, err2 := getString("git", "symbolic-ref", "--short", "-q", "HEAD") - if err1 == nil && (br == "" || err2 == nil) { - return parseVersion(desc, br) - } - return "unknown" -} - -func parseVersion(desc, branch string) string { - descRe := regexp.MustCompile(`^v?(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))??(?:\-(?P0|[1-9]\d*)\-(?Pg[0-9a-f]{5,15}))?(?:\-(?Pdirty))??$`) - if !descRe.MatchString(desc) { - return "unknown" - } - - ver := descRe.ReplaceAllString(desc, "${major}.${minor}.${patch}") - pre := descRe.ReplaceAllString(desc, "${prerelease}") - after := descRe.ReplaceAllString(desc, "${after}") - commit := descRe.ReplaceAllString(desc, "${commit}") - dirty := descRe.ReplaceAllString(desc, "${dirty}") - - if pre != "" { - ver = fmt.Sprintf("%s-%s", ver, pre) - } - - if (after != "" || dirty != "") && branch != "master" && branch != "" { - ver = fmt.Sprintf("%s-%s", ver, branch) - } - - if after != "" { - ver = fmt.Sprintf("%s-%s", ver, after) - } - - if dirty != "" { - ver = fmt.Sprintf("%s-%s", ver, "dirty") - } - - if commit != "" { - ver = fmt.Sprintf("%s+%s", ver, commit) - } - - return ver -} - -func getString(c string, a ...string) (string, error) { - cmd := exec.Command(c, a...) - b, err := cmd.CombinedOutput() - return string(bytes.TrimSpace(b)), err -} - -func buildTime() int64 { - s, err := getString("git", "show", "-s", "--format=%ct") - if err == nil { - if i, e := strconv.ParseInt(s, 10, 64); e == nil { - return i - } - } - return time.Now().Unix() -} diff --git a/build_test.go b/build_test.go deleted file mode 100644 index 2b9a676..0000000 --- a/build_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2019 Evgeny Kuznetsov (evgeny@kuznetsov.md) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build ignore - -package main - -import ( - "testing" -) - -func TestParseVersion(t *testing.T) { - testCases := []struct { - desc string - branch string - v string - }{ - {"v2.3.0-6-g30208ef-dirty", "master", "2.3.0.6.dirty+g30208ef"}, - {"1.2.3", "master", "1.2.3"}, - {"2.2.2-3.3.3", "master", "2.2.2-3.3.3"}, - {"1.1.1-4", "master", "1.1.1-4"}, - {"43.765.39-beta", "dev", "43.765.39-beta"}, - {"67.1.1-3-g0101afde", "dev", "67.1.1.dev.3+g0101afde"}, - {"v2.0.0-dirty", "dev", "2.0.0.dev.dirty"}, - {"1.0.1-dirty", "master", "1.0.1.dirty"}, - {"3.2.1-beta.2-4-g666eafde", "master", "3.2.1-beta.2.4+g666eafde"}, - {"afd", "fake", "unknown"}, - } - - for _, tc := range testCases { - s := parseVersion(tc.desc, tc.branch) - if s != tc.v { - t.Errorf("for %s on %s want %s, got %s", tc.desc, tc.branch, tc.v, s) - } - } -} diff --git a/release.go b/release.go deleted file mode 100644 index 8f80e8f..0000000 --- a/release.go +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (C) 2019 Evgeny Kuznetsov (evgeny@kuznetsov.md) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// +build ignore - -package main - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "log" - "os" - "os/exec" - "os/user" - "path/filepath" - "strings" -) - -const ( - keyID string = "FA32B7DDA1A3AC2C" - githubRepo string = "matebook-applet" - maxKeep = 10 -) - -func main() { - cleanup := flag.Bool("c", false, "clean debian repository") - flag.Parse() - - if *cleanup { - if cleanRepo(githubRepo) { - publishRepo(githubRepo) - } - os.Exit(0) - } - - if os.Getenv("GITHUB_TOKEN") == "" { - log.Fatalln("github token not available, can't work") - } - if os.Getenv("GITHUB_USER") == "" { - log.Fatalln("github user not set, can't work") - } - - version, err := getString("git", "describe") - if err != nil { - log.Fatalln(err) - } - - log.Println("Trying to release version", version) - process(version) -} - -func process(version string) { - gitVersion := version - - release := true - // check if corresponding tag even exists - res, err := getString("git", "ls-remote", "origin", gitVersion) - if err != nil || res == "" { - fmt.Println("Tag doesn't seem to exist, won't be releasing.") - release = false - } - - releaseGithub := true - - // build - fmt.Println("building...") - if err := runWithOutput("go", "run", "build.go", "-t", "-d"); err != nil { - log.Fatalln(err) - } - if err := runWithOutput("go", "run", "build.go", "-t", "-l"); err != nil { - log.Fatalln(err) - } - - debFilenames, err := filepath.Glob("./*.deb") - if err != nil { - log.Fatalln(err) - } - - if release && releaseGithub { - // release packages - fileNames := []string{ - "matebook-applet-amd64-" + gitVersion + ".tar.gz", - "matebook-applet-amd64-" + gitVersion + "-legacy.tar.gz", - } - fileNames = append(fileNames, debFilenames...) - for _, fileName := range fileNames { - args := []string{ - fileName, - "release/", - } - cmd := exec.Command("cp", args...) - if err := cmd.Run(); err != nil { - fmt.Println("failed to copy", fileName) - } - fmt.Println(fileName, "copied to release/ successfully") - } - } - - // update debian repo - if release && !(strings.Contains(version, "-")) { - updateRepo(debFilenames) - } -} - -func getString(c string, a ...string) (string, error) { - cmd := exec.Command(c, a...) - b, err := cmd.CombinedOutput() - return string(bytes.TrimSpace(b)), err -} - -func runWithOutput(c string, a ...string) error { - cmd := exec.Command(c, a...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - return err -} - -// use aptly and rsync to update debian repo -func updateRepo(filenames []string) { - if updateLocalRepo(filenames) { - publishRepo("matebook-applet") - } -} - -// update aptly local repo -func updateLocalRepo(filenames []string) bool { - for _, filename := range filenames { - cmd := exec.Command("aptly", "repo", "add", "matebook-applet", filename) - if err := cmd.Run(); err != nil { - fmt.Println("failed to add", filename, "to local aptly repo") - return false - } - } - return true -} -func publishRepo(repo string) { - // need to prime GPG with passphrase for signing, because aptly can't really do that - if err := runWithOutput("gpg", "--detach-sign", "--yes", "--passphrase", os.Getenv("GPG_PASSPHRASE"), "--pinentry-mode", "loopback", "-a", "-u", keyID, ".travis.yml"); err != nil { - log.Fatalln(err) - } - - if err := runWithOutput("aptly", "publish", "repo", repo); err != nil { - log.Fatalln("failed to locally publish repo") - return - } - fmt.Println("local repo update successful") - usr, err := user.Current() - if err != nil { - log.Fatalln(err) - } - local := filepath.Join(usr.HomeDir, ".aptly/public/") - if err := runWithOutput("rsync", "-r", "-v", "--del", local+"/", "evgeny@evgenykuznetsov.org:~/repository/"); err != nil { - fmt.Printf("failed to rsync to evgenykuznetsov.org: %s", err) - } -} - -func cleanRepo(repo string) bool { - repoContents := readRepo(repo) - done := false - - for pkg, versions := range repoContents { - var drop string - if len(versions) > maxKeep { - drop = fmt.Sprintf("%s (<= %s)", pkg, versions[maxKeep]) - } else if len(versions) > 1 { - drop = fmt.Sprintf("%s (= %s)", pkg, versions[len(versions)-1]) - } - if drop != "" { - err := runWithOutput("aptly", "repo", "remove", repo, drop) - if err != nil { - log.Fatalln(err) - } - done = true - } - } - return done -} - -func readRepo(repo string) map[string][]string { - contents := make(map[string][]string) - cmd := exec.Command("aptly", "repo", "search", `-format={{.Package}} {{.Version}}`, repo, "Name") - b, err := cmd.CombinedOutput() - if err != nil { - return contents - } - - r := bytes.NewReader(b) - scanner := bufio.NewScanner(r) - for scanner.Scan() { - line := scanner.Text() - values := strings.Split(line, " ") - if len(values) != 2 { - continue - } - var versions []string - versions = contents[values[0]] - versions = append(versions, values[1]) - contents[values[0]] = versions - } - - return contents -} diff --git a/secrets.tar.enc b/secrets.tar.enc deleted file mode 100644 index 5b09530..0000000 Binary files a/secrets.tar.enc and /dev/null differ diff --git a/version_generate.go b/version_generate.go new file mode 100644 index 0000000..1d65555 --- /dev/null +++ b/version_generate.go @@ -0,0 +1,80 @@ +// Copyright (C) 2019-2020 Evgeny Kuznetsov (evgeny@kuznetsov.md) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//+build ignore + +package main + +import ( + "bytes" + "fmt" + "os/exec" + "regexp" +) + +func main() { + ver := getVersion() + fmt.Println(ver) +} + +func getVersion() string { + desc, err1 := getString("git", "describe", "--always", "--dirty") + br, err2 := getString("git", "symbolic-ref", "--short", "-q", "HEAD") + if err1 == nil && (br == "" || err2 == nil) { + return parseVersion(desc, br) + } + return "unknown" +} + +func parseVersion(desc, branch string) string { + descRe := regexp.MustCompile(`^v?(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))??(?:\-(?P0|[1-9]\d*)\-(?Pg[0-9a-f]{5,15}))?(?:\-(?Pdirty))??$`) + if !descRe.MatchString(desc) { + return "unknown" + } + + ver := descRe.ReplaceAllString(desc, "${major}.${minor}.${patch}") + pre := descRe.ReplaceAllString(desc, "${prerelease}") + after := descRe.ReplaceAllString(desc, "${after}") + commit := descRe.ReplaceAllString(desc, "${commit}") + dirty := descRe.ReplaceAllString(desc, "${dirty}") + + if pre != "" { + ver = fmt.Sprintf("%s-%s", ver, pre) + } + + if (after != "" || dirty != "") && branch != "master" && branch != "" { + ver = fmt.Sprintf("%s.%s", ver, branch) + } + + if after != "" { + ver = fmt.Sprintf("%s.%s", ver, after) + } + + if dirty != "" { + ver = fmt.Sprintf("%s.%s", ver, "dirty") + } + + if commit != "" { + ver = fmt.Sprintf("%s+%s", ver, commit) + } + + return ver +} + +func getString(c string, a ...string) (string, error) { + cmd := exec.Command(c, a...) + b, err := cmd.CombinedOutput() + return string(bytes.TrimSpace(b)), err +}