CI revamp part 2 (#1875)
* Added Makefile * Updated README with the new information * Updated Github Actions * Added FreeBSD ARM builds * Prepared to our internal CI * Improved the auto-update version check
This commit is contained in:
parent
ff23d7b6d7
commit
632a47d56f
|
@ -1,9 +1,13 @@
|
||||||
name: build
|
name: build
|
||||||
|
|
||||||
|
env:
|
||||||
|
GO_VERSION: 1.14
|
||||||
|
NODE_VERSION: 13
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
- v*
|
- v*
|
||||||
pull_request:
|
pull_request:
|
||||||
|
@ -26,16 +30,19 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.14
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
-
|
-
|
||||||
name: Set up Node
|
name: Set up Node
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 13
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
-
|
-
|
||||||
name: Set up Go modules cache
|
name: Set up Go modules cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -58,33 +65,14 @@ jobs:
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
-
|
-
|
||||||
name: Run node build-prod
|
name: Run make ci
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
npm --prefix client ci
|
make ci
|
||||||
npm --prefix client run build-prod
|
|
||||||
-
|
|
||||||
name: Download modules and generate
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
go mod download
|
|
||||||
go generate ./...
|
|
||||||
-
|
|
||||||
name: Golangci-lint
|
|
||||||
if: matrix.os != 'windows-latest'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.23.8
|
|
||||||
golangci-lint --version
|
|
||||||
golangci-lint run
|
|
||||||
-
|
|
||||||
name: Go test
|
|
||||||
run: |
|
|
||||||
go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
|
|
||||||
-
|
-
|
||||||
name: Upload coverage
|
name: Upload coverage
|
||||||
uses: codecov/codecov-action@v1
|
uses: codecov/codecov-action@v1
|
||||||
if: success()
|
if: success() && matrix.os == 'ubuntu-latest'
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
file: ./coverage.txt
|
file: ./coverage.txt
|
||||||
|
@ -96,26 +84,18 @@ jobs:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
-
|
with:
|
||||||
name: Prepare
|
fetch-depth: 0
|
||||||
id: prepare
|
|
||||||
run: |
|
|
||||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
|
||||||
echo ::set-output name=tag_name::${GITHUB_REF#refs/tags/}
|
|
||||||
echo ::set-output name=channel::release
|
|
||||||
else
|
|
||||||
echo ::set-output name=channel::none
|
|
||||||
fi
|
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.14
|
go-version: ${{ env.GO_VERSION }}
|
||||||
-
|
-
|
||||||
name: Set up Node
|
name: Set up Node
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 13
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
-
|
-
|
||||||
name: Set up Go modules cache
|
name: Set up Go modules cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -142,98 +122,30 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -yq --no-install-suggests --no-install-recommends install snapcraft
|
sudo apt-get -yq --no-install-suggests --no-install-recommends install snapcraft
|
||||||
-
|
-
|
||||||
name: Run node build-prod
|
name: Set up GoReleaser
|
||||||
run: |
|
run: |
|
||||||
npm --prefix client ci
|
curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | BINDIR="$(go env GOPATH)/bin" sh
|
||||||
npm --prefix client run build-prod
|
|
||||||
-
|
-
|
||||||
name: Snapcraft Login
|
name: Run snapshot build
|
||||||
if: success() && startsWith(github.ref, 'refs/tags/v')
|
|
||||||
env:
|
|
||||||
SNAPCRAFT_LOGIN: ${{ secrets.SNAPCRAFT_LOGIN }}
|
|
||||||
run: |
|
run: |
|
||||||
snapcraft login --with <(echo "$SNAPCRAFT_LOGIN")
|
make snapshot
|
||||||
-
|
|
||||||
name: GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v2
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --parallelism 2
|
|
||||||
env:
|
|
||||||
CHANNEL: ${{ steps.prepare.outputs.channel }}
|
|
||||||
-
|
|
||||||
name: GitHub Release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
if: success() && startsWith(github.ref, 'refs/tags/v')
|
|
||||||
with:
|
|
||||||
draft: true
|
|
||||||
files: |
|
|
||||||
dist/checksums.txt
|
|
||||||
dist/*.tar.gz
|
|
||||||
dist/*.zip
|
|
||||||
name: AdGuard Home ${{ steps.prepare.outputs.tag_name }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: test
|
needs: test
|
||||||
steps:
|
steps:
|
||||||
-
|
|
||||||
name: Prepare
|
|
||||||
id: prepare
|
|
||||||
run: |
|
|
||||||
DOCKER_IMAGE=adguard/adguardhome
|
|
||||||
DOCKER_PLATFORMS=linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le
|
|
||||||
VERSION=edge
|
|
||||||
CHANNEL=none
|
|
||||||
|
|
||||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
|
||||||
VERSION=${GITHUB_REF#refs/tags/v}
|
|
||||||
CHANNEL=release
|
|
||||||
fi
|
|
||||||
TAGS="--tag ${DOCKER_IMAGE}:${VERSION}"
|
|
||||||
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
|
||||||
TAGS="$TAGS --tag ${DOCKER_IMAGE}:latest"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ::set-output name=docker_image::${DOCKER_IMAGE}
|
|
||||||
echo ::set-output name=version::${VERSION}
|
|
||||||
echo ::set-output name=channel::${CHANNEL}
|
|
||||||
echo ::set-output name=buildx_args::--platform ${DOCKER_PLATFORMS} \
|
|
||||||
--build-arg VERSION=${VERSION} \
|
|
||||||
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
|
|
||||||
--build-arg VCS_REF=${GITHUB_SHA::8} \
|
|
||||||
${TAGS} \
|
|
||||||
--file Dockerfile .
|
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: crazy-max/ghaction-docker-buildx@v1
|
uses: crazy-max/ghaction-docker-buildx@v1
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Docker Buildx (build)
|
name: Docker Buildx (build)
|
||||||
run: |
|
run: |
|
||||||
docker buildx build --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args }}
|
make docker-multi-arch
|
||||||
-
|
|
||||||
name: Docker Login
|
|
||||||
if: success() && startsWith(github.ref, 'refs/tags/v')
|
|
||||||
env:
|
|
||||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin
|
|
||||||
-
|
|
||||||
name: Docker Buildx (push)
|
|
||||||
if: success() && startsWith(github.ref, 'refs/tags/v')
|
|
||||||
run: |
|
|
||||||
docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args }}
|
|
||||||
-
|
|
||||||
name: Docker Check Manifest
|
|
||||||
if: always() && startsWith(github.ref, 'refs/tags/v')
|
|
||||||
run: |
|
|
||||||
docker run --rm mplatform/mquery ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}
|
|
||||||
-
|
-
|
||||||
name: Clear
|
name: Clear
|
||||||
if: always() && startsWith(github.ref, 'refs/tags/v')
|
if: always() && startsWith(github.ref, 'refs/tags/v')
|
||||||
|
@ -242,7 +154,8 @@ jobs:
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
needs: [app, docker]
|
needs: [app, docker]
|
||||||
if: always()
|
# Secrets are not passed to workflows that are triggered by a pull request from a fork
|
||||||
|
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
name: gosum
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'master'
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/gosum.yml'
|
|
||||||
- 'go.mod'
|
|
||||||
- 'go.sum'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
fix:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.14
|
|
||||||
-
|
|
||||||
name: Tidy
|
|
||||||
run: |
|
|
||||||
rm -f go.sum
|
|
||||||
go mod tidy
|
|
||||||
-
|
|
||||||
name: Set up Git
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
git config user.name GitHub
|
|
||||||
git config user.email noreply@github.com
|
|
||||||
git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
|
|
||||||
-
|
|
||||||
name: Commit and push changes
|
|
||||||
run: |
|
|
||||||
git add .
|
|
||||||
if output=$(git status --porcelain) && [ ! -z "$output" ]; then
|
|
||||||
git commit --author "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" --message "Fix go modules"
|
|
||||||
git push
|
|
||||||
fi
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: golangci-lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
golangci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v1
|
||||||
|
with:
|
||||||
|
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||||
|
version: v1.27
|
||||||
|
|
||||||
|
eslint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install modules
|
||||||
|
run: npm --prefix client ci
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm --prefix client run lint
|
||||||
|
|
||||||
|
|
||||||
|
notify:
|
||||||
|
needs: [golangci,eslint]
|
||||||
|
# Secrets are not passed to workflows that are triggered by a pull request from a fork
|
||||||
|
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Conclusion
|
||||||
|
uses: technote-space/workflow-conclusion-action@v1
|
||||||
|
-
|
||||||
|
name: Send Slack notif
|
||||||
|
uses: 8398a7/action-slack@v3
|
||||||
|
with:
|
||||||
|
status: ${{ env.WORKFLOW_CONCLUSION }}
|
||||||
|
fields: repo,message,commit,author
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"Vendor": true,
|
|
||||||
"Test": true,
|
|
||||||
"Deadline": "2m",
|
|
||||||
"Sort": ["linter", "severity", "path", "line"],
|
|
||||||
"Exclude": [
|
|
||||||
".*generated.*",
|
|
||||||
"dnsfilter/rule_to_regexp.go"
|
|
||||||
],
|
|
||||||
"EnableGC": true,
|
|
||||||
"Linters": {
|
|
||||||
"nakedret": {
|
|
||||||
"Command": "nakedret",
|
|
||||||
"Pattern": "^(?P<path>.*?\\.go):(?P<line>\\d+)\\s*(?P<message>.*)$"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"WarnUnmatchedDirective": true,
|
|
||||||
|
|
||||||
"EnableAll": true,
|
|
||||||
"DisableAll": false,
|
|
||||||
"Disable": [
|
|
||||||
"maligned",
|
|
||||||
"goconst",
|
|
||||||
"vetshadow"
|
|
||||||
],
|
|
||||||
|
|
||||||
"Cyclo": 20,
|
|
||||||
"LineLength": 200
|
|
||||||
}
|
|
|
@ -24,23 +24,37 @@ builds:
|
||||||
- amd64
|
- amd64
|
||||||
- arm
|
- arm
|
||||||
- arm64
|
- arm64
|
||||||
|
- mips
|
||||||
|
- mipsle
|
||||||
|
- mips64
|
||||||
|
- mips64le
|
||||||
goarm:
|
goarm:
|
||||||
|
- 5
|
||||||
- 6
|
- 6
|
||||||
- 7
|
- 7
|
||||||
|
gomips:
|
||||||
|
- softfloat
|
||||||
ignore:
|
ignore:
|
||||||
- goos: freebsd
|
- goos: freebsd
|
||||||
goarch: arm
|
goarch: mips
|
||||||
- goos: freebsd
|
- goos: freebsd
|
||||||
goarch: arm64
|
goarch: mipsle
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
-
|
-
|
||||||
replacements:
|
# Archive name template.
|
||||||
386: i386
|
# Defaults:
|
||||||
amd64: x86_64
|
# - if format is `tar.gz`, `tar.xz`, `gz` or `zip`:
|
||||||
|
# - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}`
|
||||||
|
# - if format is `binary`:
|
||||||
|
# - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}`
|
||||||
|
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
|
||||||
|
wrap_in_directory: "AdGuardHome"
|
||||||
format_overrides:
|
format_overrides:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
format: zip
|
format: zip
|
||||||
|
- goos: darwin
|
||||||
|
format: zip
|
||||||
files:
|
files:
|
||||||
- LICENSE.txt
|
- LICENSE.txt
|
||||||
- README.md
|
- README.md
|
||||||
|
@ -62,7 +76,7 @@ snapcrafts:
|
||||||
of common code.
|
of common code.
|
||||||
grade: stable
|
grade: stable
|
||||||
confinement: strict
|
confinement: strict
|
||||||
publish: true
|
publish: false
|
||||||
license: GPL-3.0
|
license: GPL-3.0
|
||||||
apps:
|
apps:
|
||||||
adguard-home:
|
adguard-home:
|
||||||
|
|
|
@ -4,7 +4,7 @@ FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.14-alpine as builder
|
||||||
ARG BUILD_DATE
|
ARG BUILD_DATE
|
||||||
ARG VCS_REF
|
ARG VCS_REF
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG CHANNEL=none
|
ARG CHANNEL=release
|
||||||
|
|
||||||
ENV CGO_ENABLED 0
|
ENV CGO_ENABLED 0
|
||||||
ENV GO111MODULE on
|
ENV GO111MODULE on
|
||||||
|
@ -21,12 +21,17 @@ RUN apk --update --no-cache add \
|
||||||
&& rm -rf /tmp/* /var/cache/apk/*
|
&& rm -rf /tmp/* /var/cache/apk/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . ./
|
COPY . ./
|
||||||
|
|
||||||
|
# Prepare the client code
|
||||||
RUN npm --prefix client ci && npm --prefix client run build-prod
|
RUN npm --prefix client ci && npm --prefix client run build-prod
|
||||||
|
|
||||||
|
# Download go dependencies
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
RUN go generate ./...
|
RUN go generate ./...
|
||||||
|
|
||||||
|
# It's important to place TARGET* arguments here to avoid running npm and go mod download for every platform
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
#
|
||||||
|
# Available targets
|
||||||
|
#
|
||||||
|
# * build -- builds AdGuardHome for the current platform
|
||||||
|
# * client -- builds client-side code of AdGuard Home
|
||||||
|
# * client-watch -- builds client-side code of AdGuard Home and watches for changes there
|
||||||
|
# * docker -- builds a docker image for the current platform
|
||||||
|
# * clean -- clean everything created by previous builds
|
||||||
|
# * lint -- run all linters
|
||||||
|
# * test -- run all unit-tests
|
||||||
|
# * dependencies -- installs dependencies (go and npm modules)
|
||||||
|
# * ci -- installs dependencies, runs linters and tests, intended to be used by CI/CD
|
||||||
|
#
|
||||||
|
# Building releases:
|
||||||
|
#
|
||||||
|
# * release -- builds release version of AdGuard Home. CHANNEL must be specified (release or beta).
|
||||||
|
# * snapshot -- builds snapshot version of AdGuard Home. Use with CHANNEL=edge.
|
||||||
|
# * docker-multi-arch -- builds a multi-arch image. If you want it to be pushed to docker hub,
|
||||||
|
# you must specify:
|
||||||
|
# * DOCKER_IMAGE_NAME - adguard/adguard-home
|
||||||
|
# * DOCKER_OUTPUT - type=image,name=adguard/adguard-home,push=true
|
||||||
|
|
||||||
|
GOPATH := $(shell go env GOPATH)
|
||||||
|
PWD := $(shell pwd)
|
||||||
|
TARGET=AdGuardHome
|
||||||
|
BASE_URL="https://static.adguard.com/adguardhome/$(CHANNEL)"
|
||||||
|
|
||||||
|
# See release and snapshot targets
|
||||||
|
DIST_DIR=dist
|
||||||
|
|
||||||
|
# Update channel. Can be release, beta or edge. Uses edge by default.
|
||||||
|
CHANNEL ?= edge
|
||||||
|
|
||||||
|
# Validate channel
|
||||||
|
ifneq ($(CHANNEL),relese)
|
||||||
|
ifneq ($(CHANNEL),beta)
|
||||||
|
ifneq ($(CHANNEL),edge)
|
||||||
|
$(error CHANNEL value is not valid. Valid values are release,beta or edge)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Version properties
|
||||||
|
COMMIT=$(shell git rev-parse --short HEAD)
|
||||||
|
TAG_NAME=$(shell git describe --abbrev=0)
|
||||||
|
|
||||||
|
# Remove leading "v" from the tag name
|
||||||
|
RELEASE_VERSION=$(TAG_NAME:v%=%)
|
||||||
|
SNAPSHOT_VERSION=$(RELEASE_VERSION)-SNAPSHOT-$(COMMIT)
|
||||||
|
|
||||||
|
# Set proper version
|
||||||
|
VERSION=
|
||||||
|
ifeq ($(TAG_NAME),$(shell git describe --abbrev=4))
|
||||||
|
VERSION=$(RELEASE_VERSION)
|
||||||
|
else
|
||||||
|
VERSION=$(SNAPSHOT_VERSION)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Docker target parameters
|
||||||
|
DOCKER_IMAGE_NAME ?= adguardhome-dev
|
||||||
|
DOCKER_PLATFORMS=linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le
|
||||||
|
DOCKER_OUTPUT ?= type=image,name=$(DOCKER_IMAGE_NAME),push=false
|
||||||
|
BUILD_DATE=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
# Docker tags (can be redefined)
|
||||||
|
DOCKER_TAGS ?=
|
||||||
|
ifndef DOCKER_TAGS
|
||||||
|
ifeq ($(CHANNEL),release)
|
||||||
|
DOCKER_TAGS := $(DOCKER_TAGS) --tag $(DOCKER_IMAGE_NAME):latest
|
||||||
|
endif
|
||||||
|
ifeq ($(CHANNEL),beta)
|
||||||
|
DOCKER_TAGS := $(DOCKER_TAGS) --tag $(DOCKER_IMAGE_NAME):beta
|
||||||
|
endif
|
||||||
|
ifeq ($(CHANNEL),edge)
|
||||||
|
DOCKER_TAGS := $(DOCKER_TAGS) --tag $(DOCKER_IMAGE_NAME):edge
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Validate docker build arguments
|
||||||
|
ifndef DOCKER_IMAGE_NAME
|
||||||
|
$(error DOCKER_IMAGE_NAME value is not set)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all build client client-watch docker lint test dependencies clean release snapshot docker-multi-arch
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build: dependencies client
|
||||||
|
go generate ./...
|
||||||
|
CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=$(VERSION) -X main.channel=$(CHANNEL) -X main.goarm=$(GOARM)"
|
||||||
|
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
||||||
|
|
||||||
|
client:
|
||||||
|
npm --prefix client run build-prod
|
||||||
|
|
||||||
|
client-watch:
|
||||||
|
npm --prefix client run watch
|
||||||
|
|
||||||
|
docker:
|
||||||
|
DOCKER_CLI_EXPERIMENTAL=enabled \
|
||||||
|
docker buildx build \
|
||||||
|
--build-arg VERSION=$(VERSION) \
|
||||||
|
--build-arg CHANNEL=$(CHANNEL) \
|
||||||
|
--build-arg VCS_REF=$(COMMIT) \
|
||||||
|
--build-arg BUILD_DATE=$(BUILD_DATE) \
|
||||||
|
$(DOCKER_TAGS) \
|
||||||
|
--load \
|
||||||
|
-t "$(DOCKER_IMAGE_NAME)" -f ./Dockerfile .
|
||||||
|
|
||||||
|
@echo Now you can run the docker image:
|
||||||
|
@echo docker run --name "adguard-home" -p 53:53/tcp -p 53:53/udp -p 80:80/tcp -p 443:443/tcp -p 853:853/tcp -p 3000:3000/tcp $(DOCKER_IMAGE_NAME)
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@echo Running linters
|
||||||
|
golangci-lint run ./...
|
||||||
|
npm --prefix client run lint
|
||||||
|
|
||||||
|
test:
|
||||||
|
@echo Running unit-tests
|
||||||
|
go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
|
|
||||||
|
ci: dependencies client test
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
npm --prefix client ci
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
clean:
|
||||||
|
# make build output
|
||||||
|
rm -f AdGuardHome
|
||||||
|
rm -f AdGuardHome.exe
|
||||||
|
# static build output
|
||||||
|
rm -rf build
|
||||||
|
# dist folder
|
||||||
|
rm -rf $(DIST_DIR)
|
||||||
|
# client deps
|
||||||
|
rm -rf client/node_modules
|
||||||
|
# packr-generated files
|
||||||
|
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
||||||
|
|
||||||
|
docker-multi-arch:
|
||||||
|
DOCKER_CLI_EXPERIMENTAL=enabled \
|
||||||
|
docker buildx build \
|
||||||
|
--platform $(DOCKER_PLATFORMS) \
|
||||||
|
--build-arg VERSION=$(VERSION) \
|
||||||
|
--build-arg CHANNEL=$(CHANNEL) \
|
||||||
|
--build-arg VCS_REF=$(COMMIT) \
|
||||||
|
--build-arg BUILD_DATE=$(BUILD_DATE) \
|
||||||
|
$(DOCKER_TAGS) \
|
||||||
|
--output "$(DOCKER_OUTPUT)" \
|
||||||
|
-t "$(DOCKER_IMAGE_NAME):$(VERSION)" -f ./Dockerfile .
|
||||||
|
|
||||||
|
@echo If the image was pushed to the registry, you can now run it:
|
||||||
|
@echo docker run --name "adguard-home" -p 53:53/tcp -p 53:53/udp -p 80:80/tcp -p 443:443/tcp -p 853:853/tcp -p 3000:3000/tcp $(DOCKER_IMAGE_NAME)
|
||||||
|
|
||||||
|
snapshot: dependencies client
|
||||||
|
@echo Starting snapshot build: version $(VERSION), channel $(CHANNEL)
|
||||||
|
CHANNEL=$(CHANNEL) goreleaser release --rm-dist --skip-publish --snapshot
|
||||||
|
$(call write_version_file,$(VERSION))
|
||||||
|
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
||||||
|
|
||||||
|
release: dependencies client
|
||||||
|
@echo Starting release build: version $(VERSION), channel $(CHANNEL)
|
||||||
|
CHANNEL=$(CHANNEL) goreleaser release --rm-dist --skip-publish
|
||||||
|
$(call write_version_file,$(VERSION))
|
||||||
|
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
||||||
|
|
||||||
|
define write_version_file
|
||||||
|
$(eval version := $(1))
|
||||||
|
|
||||||
|
@echo Writing version file: $(version)
|
||||||
|
|
||||||
|
# Variables for CI
|
||||||
|
rm -f $(DIST_DIR)/version.txt
|
||||||
|
echo "version=v$(version)" > $(DIST_DIR)/version.txt
|
||||||
|
|
||||||
|
# Prepare the version.json file
|
||||||
|
rm -f $(DIST_DIR)/version.json
|
||||||
|
echo "{" >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"version\": \"v$(version)\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"announcement\": \"AdGuard Home $(version) is now available!\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"announcement_url\": \"https://github.com/AdguardTeam/AdGuardHome/releases\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"selfupdate_min_version\": \"v0.0\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# Windows builds
|
||||||
|
echo " \"download_windows_amd64\": \"$(BASE_URL)/AdGuardHome_windows_amd64.zip\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_windows_386\": \"$(BASE_URL)/AdGuardHome_windows_386.zip\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# MacOS builds
|
||||||
|
echo " \"download_darwin_386\": \"$(BASE_URL)/AdGuardHome_darwin_386.zip\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_darwin_amd64\": \"$(BASE_URL)/AdGuardHome_darwin_amd64.zip\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
echo " \"download_linux_amd64\": \"$(BASE_URL)/AdGuardHome_linux_amd64.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_386\": \"$(BASE_URL)/AdGuardHome_linux_386.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# Linux, all kinds of ARM
|
||||||
|
echo " \"download_linux_arm\": \"$(BASE_URL)/AdGuardHome_linux_armv6.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_armv5\": \"$(BASE_URL)/AdGuardHome_linux_armv5.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_armv6\": \"$(BASE_URL)/AdGuardHome_linux_armv6.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_armv7\": \"$(BASE_URL)/AdGuardHome_linux_armv7.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_arm64\": \"$(BASE_URL)/AdGuardHome_linux_arm64.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# Linux, MIPS
|
||||||
|
echo " \"download_linux_mips\": \"$(BASE_URL)/AdGuardHome_linux_mips_softfloat.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_mipsle\": \"$(BASE_URL)/AdGuardHome_linux_mipsle_softfloat.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_mips64\": \"$(BASE_URL)/AdGuardHome_linux_mips64_softfloat.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_linux_mips64le\": \"$(BASE_URL)/AdGuardHome_linux_mips64le_softfloat.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# FreeBSD
|
||||||
|
echo " \"download_freebsd_386\": \"$(BASE_URL)/AdGuardHome_freebsd_386.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_freebsd_amd64\": \"$(BASE_URL)/AdGuardHome_freebsd_amd64.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# FreeBSD, all kinds of ARM
|
||||||
|
echo " \"download_freebsd_arm\": \"$(BASE_URL)/AdGuardHome_freebsd_armv6.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_freebsd_armv5\": \"$(BASE_URL)/AdGuardHome_freebsd_armv5.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_freebsd_armv6\": \"$(BASE_URL)/AdGuardHome_freebsd_armv6.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_freebsd_armv7\": \"$(BASE_URL)/AdGuardHome_freebsd_armv7.tar.gz\"," >> $(DIST_DIR)/version.json
|
||||||
|
echo " \"download_freebsd_arm64\": \"$(BASE_URL)/AdGuardHome_freebsd_arm64.tar.gz\"" >> $(DIST_DIR)/version.json
|
||||||
|
|
||||||
|
# Finish
|
||||||
|
echo "}" >> $(DIST_DIR)/version.json
|
||||||
|
endef
|
38
README.md
38
README.md
|
@ -14,9 +14,6 @@
|
||||||
<a href="https://twitter.com/AdGuard">Twitter</a> |
|
<a href="https://twitter.com/AdGuard">Twitter</a> |
|
||||||
<a href="https://t.me/adguard_en">Telegram</a>
|
<a href="https://t.me/adguard_en">Telegram</a>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href="https://travis-ci.com/AdguardTeam/AdGuardHome">
|
|
||||||
<img src="https://travis-ci.com/AdguardTeam/AdGuardHome.svg" alt="Build status" />
|
|
||||||
</a>
|
|
||||||
<a href="https://codecov.io/github/AdguardTeam/AdGuardHome?branch=master">
|
<a href="https://codecov.io/github/AdguardTeam/AdGuardHome?branch=master">
|
||||||
<img src="https://img.shields.io/codecov/c/github/AdguardTeam/AdGuardHome/master.svg" alt="Code Coverage" />
|
<img src="https://img.shields.io/codecov/c/github/AdguardTeam/AdGuardHome/master.svg" alt="Code Coverage" />
|
||||||
</a>
|
</a>
|
||||||
|
@ -153,17 +150,11 @@ Is there a chance to handle this in the future? DNS will never be enough to do t
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
You will need:
|
You will need this to build AdGuard Home:
|
||||||
|
|
||||||
* [go](https://golang.org/dl/) v1.14 or later.
|
* [go](https://golang.org/dl/) v1.14 or later.
|
||||||
* [node.js](https://nodejs.org/en/download/) v10 or later.
|
* [node.js](https://nodejs.org/en/download/) v10 or later.
|
||||||
|
|
||||||
You can either install them via the provided links or use [brew.sh](https://brew.sh/) if you're on Mac:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
brew install go node
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Open Terminal and execute these commands:
|
Open Terminal and execute these commands:
|
||||||
|
@ -174,15 +165,26 @@ cd AdGuardHome
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
#### (For devs) Upload translations
|
Check the [`Makefile`](https://github.com/AdguardTeam/AdGuardHome/blob/master/Makefile) to learn about other commands.
|
||||||
```
|
|
||||||
node upload.js
|
|
||||||
```
|
|
||||||
|
|
||||||
#### (For devs) Download translations
|
#### Preparing release
|
||||||
```
|
|
||||||
node download.js
|
You'll need this to prepare a release build:
|
||||||
```
|
|
||||||
|
* [goreleaser](https://goreleaser.com/)
|
||||||
|
* [snapcraft](https://snapcraft.io/)
|
||||||
|
|
||||||
|
Run `make snapshot` or `make release` to build all AdGuard distrs.
|
||||||
|
|
||||||
|
#### Docker image
|
||||||
|
|
||||||
|
* Run `make docker` to build the Docker image locally.
|
||||||
|
* Run `make docker-multi-arch` to build the multi-arch Docker image (the one that we publish to Docker Hub).
|
||||||
|
|
||||||
|
### Resources that we update periodically
|
||||||
|
|
||||||
|
* `scripts/translations`
|
||||||
|
* `scripts/whotracksme`
|
||||||
|
|
||||||
<a id="contributing"></a>
|
<a id="contributing"></a>
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -146,6 +146,7 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
|
||||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
@ -18,61 +18,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/util"
|
"github.com/AdguardTeam/AdGuardHome/util"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Convert version.json data to our JSON response
|
type updateInfo struct {
|
||||||
func getVersionResp(data []byte) []byte {
|
pkgURL string // URL for the new package
|
||||||
versionJSON := make(map[string]interface{})
|
pkgName string // Full path to package file
|
||||||
err := json.Unmarshal(data, &versionJSON)
|
newVer string // New version string
|
||||||
if err != nil {
|
updateDir string // Full path to the directory containing unpacked files from the new package
|
||||||
log.Error("version.json: %s", err)
|
backupDir string // Full path to backup directory
|
||||||
return []byte{}
|
configName string // Full path to the current configuration file
|
||||||
}
|
updateConfigName string // Full path to the configuration file to check by the new binary
|
||||||
|
curBinName string // Full path to the current executable file
|
||||||
ret := make(map[string]interface{})
|
bkpBinName string // Full path to the current executable file in backup directory
|
||||||
ret["can_autoupdate"] = false
|
newBinName string // Full path to the new executable file
|
||||||
|
|
||||||
var ok1, ok2, ok3 bool
|
|
||||||
ret["new_version"], ok1 = versionJSON["version"].(string)
|
|
||||||
ret["announcement"], ok2 = versionJSON["announcement"].(string)
|
|
||||||
ret["announcement_url"], ok3 = versionJSON["announcement_url"].(string)
|
|
||||||
selfUpdateMinVersion, ok4 := versionJSON["selfupdate_min_version"].(string)
|
|
||||||
if !ok1 || !ok2 || !ok3 || !ok4 {
|
|
||||||
log.Error("version.json: invalid data")
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the key is download_linux_arm or download_linux_arm64 for regular ARM versions
|
|
||||||
dloadName := fmt.Sprintf("download_%s_%s", runtime.GOOS, runtime.GOARCH)
|
|
||||||
if runtime.GOARCH == "arm" && ARMVersion == "5" {
|
|
||||||
// the key is download_linux_armv5 for ARMv5
|
|
||||||
dloadName = fmt.Sprintf("download_%s_%sv%s", runtime.GOOS, runtime.GOARCH, ARMVersion)
|
|
||||||
}
|
|
||||||
_, ok := versionJSON[dloadName]
|
|
||||||
if ok && ret["new_version"] != versionString && versionString >= selfUpdateMinVersion {
|
|
||||||
canUpdate := true
|
|
||||||
|
|
||||||
tlsConf := tlsConfigSettings{}
|
|
||||||
Context.tls.WriteDiskConfig(&tlsConf)
|
|
||||||
|
|
||||||
if runtime.GOOS != "windows" &&
|
|
||||||
((tlsConf.Enabled && (tlsConf.PortHTTPS < 1024 || tlsConf.PortDNSOverTLS < 1024)) ||
|
|
||||||
config.BindPort < 1024 ||
|
|
||||||
config.DNS.Port < 1024) {
|
|
||||||
// On UNIX, if we're running under a regular user,
|
|
||||||
// but with CAP_NET_BIND_SERVICE set on a binary file,
|
|
||||||
// and we're listening on ports <1024,
|
|
||||||
// we won't be able to restart after we replace the binary file,
|
|
||||||
// because we'll lose CAP_NET_BIND_SERVICE capability.
|
|
||||||
canUpdate, _ = util.HaveAdminRights()
|
|
||||||
}
|
|
||||||
ret["can_autoupdate"] = canUpdate
|
|
||||||
}
|
|
||||||
|
|
||||||
d, _ := json.Marshal(ret)
|
|
||||||
return d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type getVersionJSONRequest struct {
|
type getVersionJSONRequest struct {
|
||||||
|
@ -81,7 +40,6 @@ type getVersionJSONRequest struct {
|
||||||
|
|
||||||
// Get the latest available version from the Internet
|
// Get the latest available version from the Internet
|
||||||
func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if Context.disableUpdate {
|
if Context.disableUpdate {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -103,7 +61,7 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
||||||
if cached {
|
if cached {
|
||||||
log.Tracef("Returning cached data")
|
log.Tracef("Returning cached data")
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write(getVersionResp(data))
|
_, _ = w.Write(getVersionResp(data))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,6 +104,80 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform an update procedure to the latest available version
|
||||||
|
func handleUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if len(config.versionCheckJSON) == 0 {
|
||||||
|
httpError(w, http.StatusBadRequest, "/update request isn't allowed now")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := getUpdateInfo(config.versionCheckJSON)
|
||||||
|
if err != nil {
|
||||||
|
httpError(w, http.StatusInternalServerError, "%s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = doUpdate(u)
|
||||||
|
if err != nil {
|
||||||
|
httpError(w, http.StatusInternalServerError, "%s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
returnOK(w)
|
||||||
|
if f, ok := w.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
go finishUpdate(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert version.json data to our JSON response
|
||||||
|
func getVersionResp(data []byte) []byte {
|
||||||
|
versionJSON := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &versionJSON)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("version.json: %s", err)
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make(map[string]interface{})
|
||||||
|
ret["can_autoupdate"] = false
|
||||||
|
|
||||||
|
var ok1, ok2, ok3 bool
|
||||||
|
ret["new_version"], ok1 = versionJSON["version"].(string)
|
||||||
|
ret["announcement"], ok2 = versionJSON["announcement"].(string)
|
||||||
|
ret["announcement_url"], ok3 = versionJSON["announcement_url"].(string)
|
||||||
|
selfUpdateMinVersion, ok4 := versionJSON["selfupdate_min_version"].(string)
|
||||||
|
if !ok1 || !ok2 || !ok3 || !ok4 {
|
||||||
|
log.Error("version.json: invalid data")
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := getDownloadURL(versionJSON)
|
||||||
|
if ok && ret["new_version"] != versionString && versionString >= selfUpdateMinVersion {
|
||||||
|
canUpdate := true
|
||||||
|
|
||||||
|
tlsConf := tlsConfigSettings{}
|
||||||
|
Context.tls.WriteDiskConfig(&tlsConf)
|
||||||
|
|
||||||
|
if runtime.GOOS != "windows" &&
|
||||||
|
((tlsConf.Enabled && (tlsConf.PortHTTPS < 1024 || tlsConf.PortDNSOverTLS < 1024)) ||
|
||||||
|
config.BindPort < 1024 ||
|
||||||
|
config.DNS.Port < 1024) {
|
||||||
|
// On UNIX, if we're running under a regular user,
|
||||||
|
// but with CAP_NET_BIND_SERVICE set on a binary file,
|
||||||
|
// and we're listening on ports <1024,
|
||||||
|
// we won't be able to restart after we replace the binary file,
|
||||||
|
// because we'll lose CAP_NET_BIND_SERVICE capability.
|
||||||
|
canUpdate, _ = util.HaveAdminRights()
|
||||||
|
}
|
||||||
|
ret["can_autoupdate"] = canUpdate
|
||||||
|
}
|
||||||
|
|
||||||
|
d, _ := json.Marshal(ret)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
// Copy file on disk
|
// Copy file on disk
|
||||||
func copyFile(src, dst string) error {
|
func copyFile(src, dst string) error {
|
||||||
d, e := ioutil.ReadFile(src)
|
d, e := ioutil.ReadFile(src)
|
||||||
|
@ -159,19 +191,6 @@ func copyFile(src, dst string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateInfo struct {
|
|
||||||
pkgURL string // URL for the new package
|
|
||||||
pkgName string // Full path to package file
|
|
||||||
newVer string // New version string
|
|
||||||
updateDir string // Full path to the directory containing unpacked files from the new package
|
|
||||||
backupDir string // Full path to backup directory
|
|
||||||
configName string // Full path to the current configuration file
|
|
||||||
updateConfigName string // Full path to the configuration file to check by the new binary
|
|
||||||
curBinName string // Full path to the current executable file
|
|
||||||
bkpBinName string // Full path to the current executable file in backup directory
|
|
||||||
newBinName string // Full path to the new executable file
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in updateInfo object
|
// Fill in updateInfo object
|
||||||
func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
||||||
var u updateInfo
|
var u updateInfo
|
||||||
|
@ -184,7 +203,12 @@ func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
||||||
return nil, fmt.Errorf("JSON parse: %s", err)
|
return nil, fmt.Errorf("JSON parse: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.pkgURL = versionJSON[fmt.Sprintf("download_%s_%s", runtime.GOOS, runtime.GOARCH)].(string)
|
pkgURL, ok := getDownloadURL(versionJSON)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("failed to get download URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
u.pkgURL = pkgURL
|
||||||
u.newVer = versionJSON["version"].(string)
|
u.newVer = versionJSON["version"].(string)
|
||||||
if len(u.pkgURL) == 0 || len(u.newVer) == 0 {
|
if len(u.pkgURL) == 0 || len(u.newVer) == 0 {
|
||||||
return nil, fmt.Errorf("invalid JSON")
|
return nil, fmt.Errorf("invalid JSON")
|
||||||
|
@ -226,6 +250,33 @@ func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
||||||
return &u, nil
|
return &u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDownloadURL - gets download URL for the current GOOS/GOARCH
|
||||||
|
// returns
|
||||||
|
func getDownloadURL(json map[string]interface{}) (string, bool) {
|
||||||
|
var key string
|
||||||
|
|
||||||
|
if runtime.GOARCH == "arm" && ARMVersion != "" {
|
||||||
|
// the key is:
|
||||||
|
// download_linux_armv5 for ARMv5
|
||||||
|
// download_linux_armv6 for ARMv6
|
||||||
|
// download_linux_armv7 for ARMv7
|
||||||
|
key = fmt.Sprintf("download_%s_%sv%s", runtime.GOOS, runtime.GOARCH, ARMVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
u, ok := json[key]
|
||||||
|
if !ok {
|
||||||
|
// the key is download_linux_arm or download_linux_arm64 for regular ARM versions
|
||||||
|
key = fmt.Sprintf("download_%s_%s", runtime.GOOS, runtime.GOARCH)
|
||||||
|
u, ok = json[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.(string), true
|
||||||
|
}
|
||||||
|
|
||||||
// Unpack all files from .zip file to the specified directory
|
// Unpack all files from .zip file to the specified directory
|
||||||
// Existing files are overwritten
|
// Existing files are overwritten
|
||||||
// Return the list of files (not directories) written
|
// Return the list of files (not directories) written
|
||||||
|
@ -526,31 +577,3 @@ func finishUpdate(u *updateInfo) {
|
||||||
// Unreachable code
|
// Unreachable code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform an update procedure to the latest available version
|
|
||||||
func handleUpdate(w http.ResponseWriter, r *http.Request) {
|
|
||||||
|
|
||||||
if len(config.versionCheckJSON) == 0 {
|
|
||||||
httpError(w, http.StatusBadRequest, "/update request isn't allowed now")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := getUpdateInfo(config.versionCheckJSON)
|
|
||||||
if err != nil {
|
|
||||||
httpError(w, http.StatusInternalServerError, "%s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = doUpdate(u)
|
|
||||||
if err != nil {
|
|
||||||
httpError(w, http.StatusInternalServerError, "%s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
returnOK(w)
|
|
||||||
if f, ok := w.(http.Flusher); ok {
|
|
||||||
f.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
go finishUpdate(u)
|
|
||||||
}
|
|
||||||
|
|
17
home/home.go
17
home/home.go
|
@ -134,6 +134,15 @@ func Main(version string, channel string, armVer string) {
|
||||||
run(args)
|
run(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// version - returns the current version string
|
||||||
|
func version() string {
|
||||||
|
msg := "AdGuard Home, version %s, channel %s, arch %s %s"
|
||||||
|
if ARMVersion != "" {
|
||||||
|
msg = msg + " v" + ARMVersion
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(msg, versionString, updateChannel, runtime.GOOS, runtime.GOARCH)
|
||||||
|
}
|
||||||
|
|
||||||
// run initializes configuration and runs the AdGuard Home
|
// run initializes configuration and runs the AdGuard Home
|
||||||
// run is a blocking method!
|
// run is a blocking method!
|
||||||
// nolint
|
// nolint
|
||||||
|
@ -153,11 +162,7 @@ func run(args options) {
|
||||||
configureLogger(args)
|
configureLogger(args)
|
||||||
|
|
||||||
// print the first message after logger is configured
|
// print the first message after logger is configured
|
||||||
msg := "AdGuard Home, version %s, channel %s, arch %s %s"
|
log.Println(version())
|
||||||
if ARMVersion != "" {
|
|
||||||
msg = msg + " v" + ARMVersion
|
|
||||||
}
|
|
||||||
log.Printf(msg, versionString, updateChannel, runtime.GOOS, runtime.GOARCH)
|
|
||||||
log.Debug("Current working directory is %s", Context.workDir)
|
log.Debug("Current working directory is %s", Context.workDir)
|
||||||
if args.runningAsService {
|
if args.runningAsService {
|
||||||
log.Info("AdGuard Home is running as a service")
|
log.Info("AdGuard Home is running as a service")
|
||||||
|
@ -564,7 +569,7 @@ func loadOptions() options {
|
||||||
{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
|
{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
|
||||||
{"glinet", "", "Run in GL-Inet compatibility mode", nil, func() { o.glinetMode = true }},
|
{"glinet", "", "Run in GL-Inet compatibility mode", nil, func() { o.glinetMode = true }},
|
||||||
{"version", "", "Show the version and exit", nil, func() {
|
{"version", "", "Show the version and exit", nil, func() {
|
||||||
fmt.Printf("AdGuardHome %s\n", versionString)
|
fmt.Println(version())
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}},
|
}},
|
||||||
{"help", "", "Print this help", nil, func() {
|
{"help", "", "Print this help", nil, func() {
|
||||||
|
|
Loading…
Reference in New Issue