chore: make dev versions increase monotonically (#33205)

This commit is contained in:
andig 2026-08-26 21:11:46 +02:00 • committed by GitHub
parent 01ffc7d12f
commit 10b0c99f17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 32 additions and 47 deletions

View file

@ -11,8 +11,7 @@ builds:
- -trimpath - -trimpath
- -tags=release - -tags=release
ldflags: ldflags:
# the package version carries a timestamp for ordering, the reported version does not - -X github.com/evcc-io/evcc/util.Version={{ .Version }} -X github.com/evcc-io/evcc/util.Commit={{ .ShortCommit }} -s -w
- -X github.com/evcc-io/evcc/util.Version={{ if .IsSnapshot }}{{ incminor .Tag }}-dev+{{ .ShortCommit }}{{ else }}{{ .Version }}{{ end }} -X github.com/evcc-io/evcc/util.Commit={{ .ShortCommit }} -s -w
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
goos: goos:
@ -57,10 +56,9 @@ checksum:
name_template: "checksums.txt" name_template: "checksums.txt"
snapshot: snapshot:
# semver pre-release of the upcoming version. The timestamp makes the package # semver pre-release of the upcoming version, the timestamp keeps the package
# version increase monotonically: apt compares it numerically, while the commit # version increasing monotonically for apt
# alone would sort randomly. version_template: "{{ incminor .Version }}-dev.{{ .Timestamp }}"
version_template: "{{ incminor .Version }}-dev.{{ .Timestamp }}+{{ .ShortCommit }}"
changelog: changelog:
sort: asc sort: asc

View file

@ -16,8 +16,7 @@ builds:
- -trimpath - -trimpath
- -tags=release - -tags=release
ldflags: ldflags:
# the package version carries a timestamp for ordering, the reported version does not - -X github.com/evcc-io/evcc/util.Version={{ .Version }} -s -w
- -X github.com/evcc-io/evcc/util.Version={{ if .IsSnapshot }}{{ incminor .Tag }}-dev+{{ .ShortCommit }}{{ else }}{{ .Version }}{{ end }} -s -w
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
goos: goos:
@ -77,10 +76,9 @@ checksum:
name_template: "checksums.txt" name_template: "checksums.txt"
snapshot: snapshot:
# semver pre-release of the upcoming version. The timestamp makes the package # semver pre-release of the upcoming version, the timestamp keeps the package
# version increase monotonically: apt compares it numerically, while the commit # version increasing monotonically for apt
# alone would sort randomly. version_template: "{{ incminor .Version }}-dev.{{ .Timestamp }}"
version_template: "{{ incminor .Version }}-dev.{{ .Timestamp }}+{{ .ShortCommit }}"
changelog: changelog:
sort: asc sort: asc

View file

@ -6,15 +6,16 @@ GIT_TAG := $(shell test -d .git && git describe --abbrev=0 --tags)
# commits since the latest tag, empty or 0 means the commit is tagged # commits since the latest tag, empty or 0 means the commit is tagged
GIT_DIST := $(shell test -n "$(GIT_TAG)" && git rev-list --count $(GIT_TAG)..HEAD) GIT_DIST := $(shell test -n "$(GIT_TAG)" && git rev-list --count $(GIT_TAG)..HEAD)
NEXT_TAG = $(shell echo $(GIT_TAG) | awk -F. -v b='$(BUMP)' '{ if (b == "patch") { m = $$2; p = $$3 + 1 } else { m = $$2 + 1; p = 0 }; print $$1 "." m "." p }') NEXT_TAG = $(shell echo $(GIT_TAG) | awk -F. -v b='$(BUMP)' '{ if (b == "patch") { m = $$2; p = $$3 + 1 } else { m = $$2 + 1; p = 0 }; print $$1 "." m "." p }')
# untagged builds are semver pre-releases of the upcoming version # untagged builds are semver pre-releases of the upcoming version, the build
TAG_NAME ?= $(if $(filter-out 0,$(GIT_DIST)),$(NEXT_TAG)-dev+$(SHA),$(GIT_TAG)) # timestamp keeps them increasing monotonically
BUILD_TIMESTAMP := $(shell date -u '+%s')
TAG_NAME ?= $(if $(filter-out 0,$(GIT_DIST)),$(NEXT_TAG)-dev.$(BUILD_TIMESTAMP),$(GIT_TAG))
COMMIT := $(SHA) COMMIT := $(SHA)
# hide commit for releases # hide commit for releases
ifeq ($(RELEASE),1) ifeq ($(RELEASE),1)
COMMIT := COMMIT :=
endif endif
VERSION := $(if $(TAG_NAME),$(TAG_NAME),$(SHA)) VERSION := $(if $(TAG_NAME),$(TAG_NAME),$(SHA))
BUILD_DATE := $(shell date -u '+%Y-%m-%d_%H:%M:%S')
BUILD_TAGS := -tags=release BUILD_TAGS := -tags=release
LD_FLAGS := -X github.com/evcc-io/evcc/util.Version=$(VERSION) -X github.com/evcc-io/evcc/util.Commit=$(COMMIT) -s -w LD_FLAGS := -X github.com/evcc-io/evcc/util.Version=$(VERSION) -X github.com/evcc-io/evcc/util.Commit=$(COMMIT) -s -w
BUILD_ARGS := -trimpath -ldflags='$(LD_FLAGS)' BUILD_ARGS := -trimpath -ldflags='$(LD_FLAGS)'
@ -99,7 +100,7 @@ porcelain::
test -z "$$(git status --porcelain)" || (git status; git diff; false) test -z "$$(git status --porcelain)" || (git status; git diff; false)
build:: build::
@echo Version: $(VERSION) $(SHA) $(BUILD_DATE) @echo Version: $(VERSION) $(SHA)
CGO_ENABLED=0 go build -v $(BUILD_TAGS) $(BUILD_ARGS) CGO_ENABLED=0 go build -v $(BUILD_TAGS) $(BUILD_ARGS)
snapshot:: snapshot::
@ -109,15 +110,15 @@ release::
goreleaser --clean goreleaser --clean
docker:: docker::
@echo Version: $(VERSION) $(SHA) $(BUILD_DATE) @echo Version: $(VERSION) $(SHA)
docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):$(DOCKER_TAG) --push . docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):$(DOCKER_TAG) --push .
publish-nightly:: publish-nightly::
@echo Version: $(VERSION) $(SHA) $(BUILD_DATE) @echo Version: $(VERSION) $(SHA)
docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):nightly --push . docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):nightly --push .
publish-release:: publish-release::
@echo Version: $(VERSION) $(SHA) $(BUILD_DATE) @echo Version: $(VERSION) $(SHA)
docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):latest --tag $(DOCKER_IMAGE):$(VERSION) --build-arg RELEASE=1 --push . docker buildx build --platform $(PLATFORM) --tag $(DOCKER_IMAGE):latest --tag $(DOCKER_IMAGE):$(VERSION) --build-arg RELEASE=1 --push .
apt-nightly:: apt-nightly::
@ -153,7 +154,7 @@ gok-update::
${GOK} update yes ${GOK} update yes
soc:: soc::
@echo Version: $(VERSION) $(SHA) $(BUILD_DATE) @echo Version: $(VERSION) $(SHA)
go build $(BUILD_TAGS) $(BUILD_ARGS) github.com/evcc-io/evcc/cmd/soc go build $(BUILD_TAGS) $(BUILD_ARGS) github.com/evcc-io/evcc/cmd/soc
# patch asn1.go to allow Elli buggy certificates to be accepted with EEBUS # patch asn1.go to allow Elli buggy certificates to be accepted with EEBUS

View file

@ -94,7 +94,8 @@ StableUpdateWithUpdater.args = {
export const Nightly = Template.bind({}); export const Nightly = Template.bind({});
Nightly.args = { Nightly.args = {
installed: "0.304.0-dev+5ce7be4", installed: "0.304.0-dev.1712345678",
commit: "5ce7be4",
}; };
export const DevBuild = Template.bind({}); export const DevBuild = Template.bind({});

View file

@ -147,13 +147,7 @@ import Logo from "./Footer/Logo.vue";
import api from "@/api"; import api from "@/api";
import settings from "@/settings"; import settings from "@/settings";
import { extractDomain } from "@/utils/extractDomain"; import { extractDomain } from "@/utils/extractDomain";
import { import { isDevelopment, isNightly, getReleaseName, isNewVersionAvailable } from "@/utils/version";
isDevelopment,
isNightly,
getReleaseName,
commitFromVersion,
isNewVersionAvailable,
} from "@/utils/version";
import { defineComponent } from "vue"; import { defineComponent } from "vue";
const GITHUB_REPO = "https://github.com/evcc-io/evcc"; const GITHUB_REPO = "https://github.com/evcc-io/evcc";
@ -164,6 +158,7 @@ export default defineComponent({
components: { GenericModal, Logo }, components: { GenericModal, Logo },
props: { props: {
installed: { type: String, default: "" }, installed: { type: String, default: "" },
commit: { type: String, default: "" },
availableVersion: String, availableVersion: String,
releaseNotes: String, releaseNotes: String,
hasUpdater: Boolean, hasUpdater: Boolean,
@ -208,7 +203,7 @@ export default defineComponent({
return `${GITHUB_REPO}/network/dependencies`; return `${GITHUB_REPO}/network/dependencies`;
}, },
githubCommitUrl() { githubCommitUrl() {
return `${GITHUB_REPO}/commit/${commitFromVersion(this.installed)}`; return `${GITHUB_REPO}/commit/${this.commit}`;
}, },
modalSize() { modalSize() {
return this.newVersionAvailable ? undefined : "sm"; return this.newVersionAvailable ? undefined : "sm";

View file

@ -8,6 +8,7 @@ declare global {
app: any; app: any;
evcc?: { evcc?: {
version: string; version: string;
commit: string;
customCss: boolean; customCss: boolean;
customLogo: boolean; customLogo: boolean;
customBrand: string; customBrand: string;

View file

@ -2,14 +2,13 @@ import { describe, expect, test } from "vite-plus/test";
import { import {
isDevelopment, isDevelopment,
isNightly, isNightly,
commitFromVersion,
getReleaseName, getReleaseName,
getShortVersion, getShortVersion,
isNewVersionAvailable, isNewVersionAvailable,
} from "./version"; } from "./version";
const DEV = "0.0.0"; const DEV = "0.0.0";
const NIGHTLY = "0.304.0-dev+abc1234"; const NIGHTLY = "0.304.0-dev.1712345678";
const STABLE = "0.303.1"; const STABLE = "0.303.1";
describe("isDevelopment", () => { describe("isDevelopment", () => {
@ -21,20 +20,13 @@ describe("isDevelopment", () => {
}); });
describe("isNightly", () => { describe("isNightly", () => {
test("only versions with build metadata", () => { test("only pre-release versions", () => {
expect(isNightly(DEV)).toBe(false); expect(isNightly(DEV)).toBe(false);
expect(isNightly(NIGHTLY)).toBe(true); expect(isNightly(NIGHTLY)).toBe(true);
expect(isNightly(STABLE)).toBe(false); expect(isNightly(STABLE)).toBe(false);
}); });
}); });
describe("commitFromVersion", () => {
test("extracts build metadata", () => {
expect(commitFromVersion(NIGHTLY)).toBe("abc1234");
expect(commitFromVersion(STABLE)).toBe("");
});
});
describe("getReleaseName", () => { describe("getReleaseName", () => {
test("maps version to release name", () => { test("maps version to release name", () => {
expect(getReleaseName(DEV)).toBe("development"); expect(getReleaseName(DEV)).toBe("development");
@ -46,7 +38,7 @@ describe("getReleaseName", () => {
describe("getShortVersion", () => { describe("getShortVersion", () => {
test("formats version", () => { test("formats version", () => {
expect(getShortVersion(DEV)).toBe("dev build"); expect(getShortVersion(DEV)).toBe("dev build");
expect(getShortVersion(NIGHTLY)).toBe("v0.304.0-dev+abc1234"); expect(getShortVersion(NIGHTLY)).toBe("v0.304.0-dev.1712345678");
expect(getShortVersion(STABLE)).toBe("v0.303.1"); expect(getShortVersion(STABLE)).toBe("v0.303.1");
}); });
}); });

View file

@ -2,13 +2,9 @@ export function isDevelopment(version: string): boolean {
return version === "0.0.0"; return version === "0.0.0";
} }
// untagged builds carry the commit as build metadata: 0.304.0-dev+abc1234 // untagged builds are pre-releases carrying the build timestamp: 0.304.0-dev.1712345678
export function isNightly(version: string): boolean { export function isNightly(version: string): boolean {
return version.includes("+"); return version.includes("-dev.");
}
export function commitFromVersion(version: string): string {
return version.split("+")[1] ?? "";
} }
export function getReleaseName(version: string): string { export function getReleaseName(version: string): string {

View file

@ -105,6 +105,7 @@ export default defineComponent({
aboutModalProps() { aboutModalProps() {
return { return {
installed: window.evcc?.version, installed: window.evcc?.version,
commit: window.evcc?.commit,
customLogo: this.custom.logo, customLogo: this.custom.logo,
customBrand: this.custom.brand, customBrand: this.custom.brand,
customWebsite: this.custom.website, customWebsite: this.custom.website,

View file

@ -54,6 +54,7 @@ func getPreferredLanguage(header string) string {
func globalsJsHandler(custom Customization) http.HandlerFunc { func globalsJsHandler(custom Customization) http.HandlerFunc {
globals := struct { globals := struct {
Version string `json:"version"` Version string `json:"version"`
Commit string `json:"commit"`
CustomCss bool `json:"customCss"` CustomCss bool `json:"customCss"`
CustomLogo bool `json:"customLogo"` CustomLogo bool `json:"customLogo"`
Brand string `json:"customBrand"` Brand string `json:"customBrand"`
@ -63,6 +64,7 @@ func globalsJsHandler(custom Customization) http.HandlerFunc {
Theme string `json:"customTheme"` Theme string `json:"customTheme"`
}{ }{
Version: util.Version, Version: util.Version,
Commit: util.Commit,
CustomCss: custom.Css != "", CustomCss: custom.Css != "",
CustomLogo: custom.LogoLight != "", CustomLogo: custom.LogoLight != "",
Brand: custom.Brand, Brand: custom.Brand,

View file

@ -12,7 +12,7 @@ var (
Commit = "" Commit = ""
) )
// FormattedVersion returns the version, untagged builds carry the commit as build metadata // FormattedVersion returns the version, untagged builds carry a build timestamp
func FormattedVersion() string { func FormattedVersion() string {
return Version return Version
} }