From 54a4fe72ef725ff59008ed9abb968c11fd824d3a Mon Sep 17 00:00:00 2001 From: Andreas Linde <42185+DerAndereAndi@users.noreply.github.com> Date: Sat, 4 Dec 2021 13:05:18 +0100 Subject: [PATCH] Add deb package and nightly distribution (#1977) - Add publishing automated debian package releases via Cloudsmith.io, which allows evcc to be installed and updated via `apt` - Add nightly docker (:latest) and deb distribution - Disable docker builds for every commit on master - Allow nightly builds to be triggered manually --- .github/workflows/build.yml | 204 ------------------------------- .github/workflows/default.yml | 89 ++++++++++++++ .github/workflows/nightly.yml | 113 +++++++++++++++++ .github/workflows/release.yml | 103 ++++++++++++++++ .goreleaser-nightly.yml | 60 +++++++++ .goreleaser.yml | 28 ++++- Makefile | 3 +- packaging/init/evcc.service | 17 +++ packaging/scripts/postinstall.sh | 26 ++++ packaging/scripts/postremove.sh | 18 +++ packaging/scripts/preremove.sh | 6 + 11 files changed, 459 insertions(+), 208 deletions(-) delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/default.yml create mode 100644 .github/workflows/nightly.yml create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser-nightly.yml create mode 100644 packaging/init/evcc.service create mode 100644 packaging/scripts/postinstall.sh create mode 100644 packaging/scripts/postremove.sh create mode 100644 packaging/scripts/preremove.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index cc3427ee32..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,204 +0,0 @@ -name: Build - -on: [push, pull_request] - -jobs: - - build: - name: Build - runs-on: ubuntu-latest - - steps: - - name: Setup - uses: actions/setup-go@v2 - with: - go-version: ^1.16 - id: go - - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.go-version }}-go- - - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Install tools - run: make install - - - name: Assets - run: make assets - - - name: Porcelain - run: | - go mod tidy - test -z "$(git status --porcelain)" || (git status; git diff; false) - - - name: Build - run: make build - - - name: Lint - uses: golangci/golangci-lint-action@v2 - with: - version: latest - skip-go-installation: true - skip-pkg-cache: true - skip-build-cache: true - - - name: Test - run: make test - - build-ui: - name: Build UI - runs-on: ubuntu-latest - - steps: - - name: Cache NPM modules - uses: actions/cache@v2 - with: - path: | - **/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-npm- - - - name: Checkout - uses: actions/checkout@v2 - - - name: Install tools - run: make install-ui - - - name: Build - run: make ui - - - name: Lint - run: make lint-ui - - - name: Test - run: make test-ui - - - name: Porcelain - run: | - test -z "$(git status --porcelain)" || (git status; git diff; false) - - dockerlatest: - name: Publish :latest - if: | - startsWith(github.ref, 'refs/heads/master') - && ! contains(github.head_ref, 'refs/heads/chore/') - needs: - - build - - build-ui - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Install - env: - SEIHON_VERSION: v0.8.4 - run: curl -sfL https://raw.githubusercontent.com/ldez/seihon/master/godownloader.sh | sudo bash -s -- -b $GOPATH/bin ${SEIHON_VERSION} - - - name: Login - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - - name: Publish - run: make publish-latest-ci - - - dockerrelease: - name: Publish :release - if: "startsWith(github.ref, 'refs/tags')" - needs: - - build - - build-ui - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: refs/heads/master # force master - fetch-depth: 0 - - - name: Install - run: curl -sfL https://raw.githubusercontent.com/ldez/seihon/master/godownloader.sh | sudo bash -s -- -b $GOPATH/bin v0.5.1 - - - name: Login - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - - name: Publish - run: make publish-images - - - release: - name: Release - if: "startsWith(github.ref, 'refs/tags')" - needs: - - build - - build-ui - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.go-version }}-go- - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: ^1.16 - id: go - - - name: Prepare Image - run: | - make prepare-image - sed -i -e 's#-ld.*$#& -X github.com/evcc-io/evcc/server/updater.Password=${{ secrets.IMAGE_PASS }}#' buildflags/github.com/evcc-io/evcc/buildflags.txt - mkdir /home/runner/.config/gokrazy - echo ${{ secrets.IMAGE_PASS }}> /home/runner/.config/gokrazy/http-password.txt - - - name: Build Image - run: make image - - - name: Build Root Filesystem - run: make image-rootfs - - - name: Clean git - run: | - git checkout go.* - rm -rf flags buildflags - - - name: Create Github Release - uses: goreleaser/goreleaser-action@v2 - with: - version: latest - args: release --rm-dist - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml new file mode 100644 index 0000000000..bf4bbce591 --- /dev/null +++ b/.github/workflows/default.yml @@ -0,0 +1,89 @@ +name: Default + +on: [push, pull_request, workflow_call] + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Setup + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + id: go + + - name: Cache Go modules + uses: actions/cache@v2 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.go-version }}-go- + + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install tools + run: make install + + - name: Assets + run: make assets + + - name: Porcelain + run: | + go mod tidy + test -z "$(git status --porcelain)" || (git status; git diff; false) + + - name: Build + run: make build + + - name: Lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest + skip-go-installation: true + skip-pkg-cache: true + skip-build-cache: true + + - name: Test + run: make test + + build-ui: + name: Build UI + runs-on: ubuntu-latest + + steps: + - name: Cache NPM modules + uses: actions/cache@v2 + with: + path: | + **/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Checkout + uses: actions/checkout@v2 + + - name: Install tools + run: make install-ui + + - name: Build + run: make ui + + - name: Lint + run: make lint-ui + + - name: Test + run: make test-ui + + - name: Porcelain + run: | + test -z "$(git status --porcelain)" || (git status; git diff; false) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000000..370adcd215 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,113 @@ +name: Nightly Build + +on: + schedule: # runs on the default branch: master + - cron: '0 2 * * *' # run at 2 AM UTC + workflow_dispatch: + +jobs: + check_date: + runs-on: ubuntu-latest + name: Check latest commit + outputs: + should_run: ${{ steps.should_run.outputs.should_run }} + steps: + - uses: actions/checkout@v2 + - name: print latest_commit + run: echo ${{ github.sha }} + + - id: should_run + continue-on-error: true + name: check latest commit is less than a day + if: ${{ github.event_name == 'schedule' }} + run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false" + + call-build-workflow: + name: Call Build + needs: check_date + if: | + ${{ needs.check_date.outputs.should_run != 'false' }} + && startsWith(github.ref, 'refs/heads/master') + && ! contains(github.head_ref, 'refs/heads/chore/') + uses: evcc-io/evcc/.github/workflows/default.yml@master + + dockerlatest: + name: Publish Docker :latest + needs: + - build + - build-ui + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install + env: + SEIHON_VERSION: v0.8.4 + run: curl -sfL https://raw.githubusercontent.com/ldez/seihon/master/godownloader.sh | sudo bash -s -- -b $GOPATH/bin ${SEIHON_VERSION} + + - name: Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + + - name: Publish + run: make publish-latest-ci + + nightly: + name: Publish APT nightly + needs: + - build + - build-ui + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Cache Go modules + uses: actions/cache@v2 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.go-version }}-go- + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + id: go + + - name: Install Cloudsmith CLI + run: pip install --upgrade cloudsmith-cli + + - name: Clean git + run: | + git checkout go.* + rm -rf flags buildflags + + - name: Create nightly build + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release -f .goreleaser-nightly.yml --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish .deb to Cloudsmith + env: + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + run: | + for filename in dist/*.deb; do + echo "Pushing $filename to 'unstable'" + cloudsmith push deb evcc/unstable/any-distro/any-version $filename + done \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..91521ab5e1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,103 @@ +name: Release + +on: [push] + +jobs: + call-build-workflow: + if: "startsWith(github.ref, 'refs/tags')" + uses: evcc-io/evcc/.github/workflows/default.yml@master + + dockerrelease: + name: Publish Docker :release + needs: + - build + - build-ui + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + ref: refs/heads/master # force master + fetch-depth: 0 + + - name: Install + run: curl -sfL https://raw.githubusercontent.com/ldez/seihon/master/godownloader.sh | sudo bash -s -- -b $GOPATH/bin v0.5.1 + + - name: Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + + - name: Publish + run: make publish-images + + + release: + name: Publish Github & APT release + needs: + - build + - build-ui + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Cache Go modules + uses: actions/cache@v2 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.go-version }}-go- + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + id: go + + - name: Install Cloudsmith CLI + run: pip install --upgrade cloudsmith-cli + + # gokrazy image + # - name: Prepare Image + # run: | + # make prepare-image + # sed -i -e 's#-ld.*$#& -X github.com/evcc-io/evcc/server/updater.Password=${{ secrets.IMAGE_PASS }}#' buildflags/github.com/evcc-io/evcc/buildflags.txt + # mkdir /home/runner/.config/gokrazy + # echo ${{ secrets.IMAGE_PASS }}> /home/runner/.config/gokrazy/http-password.txt + + # - name: Build Image + # run: make image + + # - name: Build Root Filesystem + # run: make image-rootfs + + - name: Clean git + run: | + git checkout go.* + rm -rf flags buildflags + + - name: Create Github Release + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish .deb to Cloudsmith + env: + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + run: | + for filename in dist/*.deb; do + echo "Pushing $filename to 'stable'" + cloudsmith push deb evcc/stable/any-distro/any-version $filename + done \ No newline at end of file diff --git a/.goreleaser-nightly.yml b/.goreleaser-nightly.yml new file mode 100644 index 0000000000..ef87f25a4c --- /dev/null +++ b/.goreleaser-nightly.yml @@ -0,0 +1,60 @@ +dist: release +release: + disable: true +builds: +- id: evcc + main: main.go + flags: + - -tags=release + ldflags: + - -X github.com/evcc-io/evcc/server.Version={{.Version}}.0-nightly.{{.Date}} -X github.com/evcc-io/evcc/server.Commit={{.ShortCommit}} -s -w + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + - windows + goarch: + - amd64 + - arm + - arm64 + goarm: + - "6" +archives: +- builds: + - evcc + replacements: + darwin: macOS + format: tar.gz + format_overrides: + - goos: windows + format: zip + files: + - evcc.dist.yaml + name_template: "{{.ProjectName}}_{{ .Version }}.0-nightly.{{.Date}}_{{.Os}}-{{.Arch}}" +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "nightly" +nfpms: + - id: default + package_name: evcc + file_name_template: "{{.ProjectName}}_{{ .Version }}.0-nightly.{{.Date}}_{{.Os}}-{{.Arch}}" + + homepage: https://evcc.io + description: EV Charge Controller + maintainer: andig + license: MIT + vendor: evcc.io + + formats: + - deb + + contents: + - src: ./packaging/init/evcc.service + dst: /lib/systemd/system/evcc.service + + scripts: + postinstall: ./packaging/scripts/postinstall.sh + preremove: ./packaging/scripts/preremove.sh + postremove: ./packaging/scripts/postremove.sh \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml index 22c93fd0ef..55712329d0 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -3,9 +3,9 @@ release: github: owner: evcc-io name: evcc - extra_files: - - glob: evcc_*.image.gz - - glob: evcc_*.rootfs.gz +# extra_files: +# - glob: evcc_*.image.gz +# - glob: evcc_*.rootfs.gz builds: - id: evcc main: main.go @@ -48,3 +48,25 @@ changelog: - '^bump' - '^docs:' - '^test:' +nfpms: + - id: default + package_name: evcc + file_name_template: '{{ .ConventionalFileName }}' + + homepage: https://evcc.io + description: EV Charge Controller + maintainer: andig + license: MIT + vendor: evcc.io + + formats: + - deb + + contents: + - src: ./packaging/init/evcc.service + dst: /lib/systemd/system/evcc.service + + scripts: + postinstall: ./packaging/scripts/postinstall.sh + preremove: ./packaging/scripts/preremove.sh + postremove: ./packaging/scripts/postremove.sh \ No newline at end of file diff --git a/Makefile b/Makefile index da57405f38..bfba42367f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ DOCKER_IMAGE := andig/evcc ALPINE_VERSION := 3.13 TARGETS := arm.v6,arm.v8,amd64 -# image +# gokrazy image IMAGE_FILE := evcc_$(TAG_NAME).image IMAGE_ROOTFS := evcc_$(TAG_NAME).rootfs IMAGE_OPTIONS := -hostname evcc -http_port 8080 github.com/gokrazy/serial-busybox github.com/gokrazy/breakglass github.com/evcc-io/evcc @@ -88,6 +88,7 @@ publish-images: seihon publish --dry-run=false --template docker/tmpl.Dockerfile --base-runtime-image alpine:$(ALPINE_VERSION) \ --image-name $(DOCKER_IMAGE) -v "latest" -v "$(TAG_NAME)" --targets=$(TARGETS) +# gokrazy image prepare-image: go get github.com/gokrazy/tools/cmd/gokr-packer@latest mkdir -p flags/github.com/gokrazy/breakglass diff --git a/packaging/init/evcc.service b/packaging/init/evcc.service new file mode 100644 index 0000000000..b88f9ce108 --- /dev/null +++ b/packaging/init/evcc.service @@ -0,0 +1,17 @@ +# evcc.service +# + +[Unit] +Description=evcc +Requires=network-online.target +After=syslog.target network.target network-online.target +Wants=network-online.target +StartLimitIntervalSec=10 +StartLimitBurst=10 + +[Service] +ExecStart=/usr/local/bin/evcc --log error +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/packaging/scripts/postinstall.sh b/packaging/scripts/postinstall.sh new file mode 100644 index 0000000000..c10f87964e --- /dev/null +++ b/packaging/scripts/postinstall.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -e + +if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then + # This will only remove masks created by d-s-h on package removal. + deb-systemd-helper unmask evcc.service >/dev/null || true + + # was-enabled defaults to true, so new installations run enable. + if deb-systemd-helper --quiet was-enabled evcc.service; then + # Enables the unit on first installation, creates new + # symlinks on upgrades if the unit file has changed. + deb-systemd-helper enable evcc.service >/dev/null || true + else + # Update the statefile to add new symlinks (if any), which need to be + # cleaned up on purge. Also remove old symlinks. + deb-systemd-helper update-state evcc.service >/dev/null || true + fi + + # Restart only if it was already started + if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true + if [ -n "$2" ]; then + deb-systemd-invoke try-restart evcc.service >/dev/null || true + fi + fi +fi \ No newline at end of file diff --git a/packaging/scripts/postremove.sh b/packaging/scripts/postremove.sh new file mode 100644 index 0000000000..4de8d7878e --- /dev/null +++ b/packaging/scripts/postremove.sh @@ -0,0 +1,18 @@ +set -e + +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true +fi + +if [ "$1" = "remove" ]; then + if [ -x "/usr/bin/deb-systemd-helper" ]; then + deb-systemd-helper mask evcc.service >/dev/null || true + fi +fi + +if [ "$1" = "purge" ]; then + if [ -x "/usr/bin/deb-systemd-helper" ]; then + deb-systemd-helper purge evcc.service >/dev/null || true + deb-systemd-helper unmask evcc.service >/dev/null || true + fi +fi \ No newline at end of file diff --git a/packaging/scripts/preremove.sh b/packaging/scripts/preremove.sh new file mode 100644 index 0000000000..3a2eb0adaf --- /dev/null +++ b/packaging/scripts/preremove.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e + +if [ -d /run/systemd/system ] && [ "$1" = remove ]; then + deb-systemd-invoke stop evcc.service >/dev/null || true +fi