chore: semver-compliant version for dev and nightly builds (#32663)
This commit is contained in:
parent
c1fac30171
commit
09c2ce3055
14 changed files with 103 additions and 64 deletions
|
|
@ -11,7 +11,7 @@ builds:
|
||||||
- -trimpath
|
- -trimpath
|
||||||
- -tags=release
|
- -tags=release
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/evcc-io/evcc/util.Version={{ .Tag }} -X github.com/evcc-io/evcc/util.Commit={{ .ShortCommit }} -s -w
|
- -X github.com/evcc-io/evcc/util.Version={{ .Version }} -X github.com/evcc-io/evcc/util.Commit={{ .ShortCommit }} -s -w
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
goos:
|
goos:
|
||||||
|
|
@ -56,7 +56,8 @@ checksum:
|
||||||
name_template: "checksums.txt"
|
name_template: "checksums.txt"
|
||||||
|
|
||||||
snapshot:
|
snapshot:
|
||||||
version_template: '{{ .Version }}{{ if eq (len (split .Version ".")) 2 }}.0{{ end }}+{{ .Timestamp }}'
|
# semver pre-release of the upcoming version
|
||||||
|
version_template: "{{ incminor .Version }}-dev+{{ .ShortCommit }}"
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
sort: asc
|
sort: asc
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,8 @@ checksum:
|
||||||
name_template: "checksums.txt"
|
name_template: "checksums.txt"
|
||||||
|
|
||||||
snapshot:
|
snapshot:
|
||||||
version_template: "{{ .Tag }}-next"
|
# semver pre-release of the upcoming version
|
||||||
|
version_template: "{{ incminor .Version }}-dev+{{ .ShortCommit }}"
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
sort: asc
|
sort: asc
|
||||||
|
|
|
||||||
9
Makefile
9
Makefile
|
|
@ -1,6 +1,13 @@
|
||||||
# build vars
|
# build vars
|
||||||
TAG_NAME ?= $(shell test -d .git && git describe --abbrev=0 --tags)
|
# part of the latest tag incremented for untagged builds: minor or patch
|
||||||
|
BUMP ?= minor
|
||||||
SHA ?= $(shell test -d .git && git rev-parse --short HEAD)
|
SHA ?= $(shell test -d .git && git rev-parse --short HEAD)
|
||||||
|
GIT_TAG := $(shell test -d .git && git describe --abbrev=0 --tags)
|
||||||
|
# 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)
|
||||||
|
NEXT_TAG = $(shell echo $(GIT_TAG) | awk -F. -v b='$(BUMP)' '{if (b == "patch") $$NF++; else {$$2++; $$3=0}} 1' OFS=.)
|
||||||
|
# untagged builds are semver pre-releases of the upcoming version
|
||||||
|
TAG_NAME ?= $(if $(filter-out 0,$(GIT_DIST)),$(NEXT_TAG)-dev+$(SHA),$(GIT_TAG))
|
||||||
COMMIT := $(SHA)
|
COMMIT := $(SHA)
|
||||||
# hide commit for releases
|
# hide commit for releases
|
||||||
ifeq ($(RELEASE),1)
|
ifeq ($(RELEASE),1)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ export default {
|
||||||
component: AboutModal,
|
component: AboutModal,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
installed: { control: "text" },
|
installed: { control: "text" },
|
||||||
commit: { control: "text" },
|
|
||||||
availableVersion: { control: "text" },
|
availableVersion: { control: "text" },
|
||||||
releaseNotes: { control: "text" },
|
releaseNotes: { control: "text" },
|
||||||
hasUpdater: { control: "boolean" },
|
hasUpdater: { control: "boolean" },
|
||||||
|
|
@ -95,9 +94,7 @@ StableUpdateWithUpdater.args = {
|
||||||
|
|
||||||
export const Nightly = Template.bind({});
|
export const Nightly = Template.bind({});
|
||||||
Nightly.args = {
|
Nightly.args = {
|
||||||
installed: "0.303.1",
|
installed: "0.304.0-dev+5ce7be4",
|
||||||
commit: "5ce7be4a9f3b2c1d",
|
|
||||||
availableVersion: "0.303.1",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DevBuild = Template.bind({});
|
export const DevBuild = Template.bind({});
|
||||||
|
|
|
||||||
|
|
@ -36,25 +36,14 @@
|
||||||
<td v-if="development">---</td>
|
<td v-if="development">---</td>
|
||||||
<td v-else>
|
<td v-else>
|
||||||
<div class="d-flex flex-wrap column-gap-2 align-items-baseline">
|
<div class="d-flex flex-wrap column-gap-2 align-items-baseline">
|
||||||
<span class="text-nowrap">
|
<a
|
||||||
<a
|
class="text-nowrap"
|
||||||
:href="releaseNotesUrl(installed)"
|
:href="nightly ? githubCommitUrl : releaseNotesUrl(installed)"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
v{{ installed }}
|
v{{ installed }}
|
||||||
</a>
|
</a>
|
||||||
<template v-if="nightly">
|
|
||||||
(<a
|
|
||||||
:href="githubCommitUrl"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
><span class="font-monospace">{{
|
|
||||||
shortCommit
|
|
||||||
}}</span></a
|
|
||||||
>)
|
|
||||||
</template>
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
v-if="!nightly && !newVersionAvailable"
|
v-if="!nightly && !newVersionAvailable"
|
||||||
class="text-muted text-nowrap"
|
class="text-muted text-nowrap"
|
||||||
|
|
@ -162,7 +151,7 @@ import {
|
||||||
isDevelopment,
|
isDevelopment,
|
||||||
isNightly,
|
isNightly,
|
||||||
getReleaseName,
|
getReleaseName,
|
||||||
shortCommit,
|
commitFromVersion,
|
||||||
isNewVersionAvailable,
|
isNewVersionAvailable,
|
||||||
} from "@/utils/version";
|
} from "@/utils/version";
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
@ -175,7 +164,6 @@ export default defineComponent({
|
||||||
components: { GenericModal, Logo },
|
components: { GenericModal, Logo },
|
||||||
props: {
|
props: {
|
||||||
installed: { type: String, default: "" },
|
installed: { type: String, default: "" },
|
||||||
commit: String,
|
|
||||||
availableVersion: String,
|
availableVersion: String,
|
||||||
releaseNotes: String,
|
releaseNotes: String,
|
||||||
hasUpdater: Boolean,
|
hasUpdater: Boolean,
|
||||||
|
|
@ -198,10 +186,10 @@ export default defineComponent({
|
||||||
return isDevelopment(this.installed);
|
return isDevelopment(this.installed);
|
||||||
},
|
},
|
||||||
nightly() {
|
nightly() {
|
||||||
return isNightly(this.installed, this.commit);
|
return isNightly(this.installed);
|
||||||
},
|
},
|
||||||
releaseName() {
|
releaseName() {
|
||||||
return getReleaseName(this.installed, this.commit);
|
return getReleaseName(this.installed);
|
||||||
},
|
},
|
||||||
websiteUrl() {
|
websiteUrl() {
|
||||||
return this.customWebsite || EVCC_WEBSITE;
|
return this.customWebsite || EVCC_WEBSITE;
|
||||||
|
|
@ -219,11 +207,8 @@ export default defineComponent({
|
||||||
githubDependenciesUrl() {
|
githubDependenciesUrl() {
|
||||||
return `${GITHUB_REPO}/network/dependencies`;
|
return `${GITHUB_REPO}/network/dependencies`;
|
||||||
},
|
},
|
||||||
shortCommit() {
|
|
||||||
return shortCommit(this.commit);
|
|
||||||
},
|
|
||||||
githubCommitUrl() {
|
githubCommitUrl() {
|
||||||
return `${GITHUB_REPO}/commit/${this.commit}`;
|
return `${GITHUB_REPO}/commit/${commitFromVersion(this.installed)}`;
|
||||||
},
|
},
|
||||||
modalSize() {
|
modalSize() {
|
||||||
return this.newVersionAvailable ? undefined : "sm";
|
return this.newVersionAvailable ? undefined : "sm";
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@
|
||||||
:auth-disabled="authDisabled"
|
:auth-disabled="authDisabled"
|
||||||
:evopt="evopt"
|
:evopt="evopt"
|
||||||
:installed="installed"
|
:installed="installed"
|
||||||
:commit="commit"
|
|
||||||
:available-version="availableVersion"
|
:available-version="availableVersion"
|
||||||
:custom-brand="customBrand"
|
:custom-brand="customBrand"
|
||||||
/>
|
/>
|
||||||
|
|
@ -77,7 +76,6 @@ export default defineComponent({
|
||||||
startupCompleted: Boolean,
|
startupCompleted: Boolean,
|
||||||
evopt: { type: Object as PropType<EvOpt>, required: false },
|
evopt: { type: Object as PropType<EvOpt>, required: false },
|
||||||
installed: String,
|
installed: String,
|
||||||
commit: String,
|
|
||||||
availableVersion: String,
|
availableVersion: String,
|
||||||
customBrand: String,
|
customBrand: String,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
:auth-disabled="authDisabled"
|
:auth-disabled="authDisabled"
|
||||||
:evopt="evopt"
|
:evopt="evopt"
|
||||||
:installed="installed"
|
:installed="installed"
|
||||||
:commit="commit"
|
|
||||||
:available-version="availableVersion"
|
:available-version="availableVersion"
|
||||||
:custom-brand="customBrand"
|
:custom-brand="customBrand"
|
||||||
@close="open = false"
|
@close="open = false"
|
||||||
|
|
@ -51,7 +50,6 @@ export default defineComponent({
|
||||||
authDisabled: Boolean,
|
authDisabled: Boolean,
|
||||||
evopt: { type: Object as PropType<EvOpt>, required: false },
|
evopt: { type: Object as PropType<EvOpt>, required: false },
|
||||||
installed: String,
|
installed: String,
|
||||||
commit: String,
|
|
||||||
availableVersion: String,
|
availableVersion: String,
|
||||||
customBrand: String,
|
customBrand: String,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ export default defineComponent({
|
||||||
authDisabled: Boolean,
|
authDisabled: Boolean,
|
||||||
evopt: { type: Object as PropType<EvOpt>, required: false },
|
evopt: { type: Object as PropType<EvOpt>, required: false },
|
||||||
installed: String,
|
installed: String,
|
||||||
commit: String,
|
|
||||||
availableVersion: String,
|
availableVersion: String,
|
||||||
customBrand: String,
|
customBrand: String,
|
||||||
},
|
},
|
||||||
|
|
@ -144,7 +143,7 @@ export default defineComponent({
|
||||||
return "bg-warning";
|
return "bg-warning";
|
||||||
},
|
},
|
||||||
versionLabel() {
|
versionLabel() {
|
||||||
return getShortVersion(this.installed || "", this.commit);
|
return getShortVersion(this.installed || "");
|
||||||
},
|
},
|
||||||
newVersionAvailable() {
|
newVersionAvailable() {
|
||||||
return isNewVersionAvailable(this.installed, this.availableVersion);
|
return isNewVersionAvailable(this.installed, this.availableVersion);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ 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;
|
||||||
|
|
|
||||||
63
assets/js/utils/version.test.ts
Normal file
63
assets/js/utils/version.test.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { describe, expect, test } from "vite-plus/test";
|
||||||
|
import {
|
||||||
|
isDevelopment,
|
||||||
|
isNightly,
|
||||||
|
commitFromVersion,
|
||||||
|
getReleaseName,
|
||||||
|
getShortVersion,
|
||||||
|
isNewVersionAvailable,
|
||||||
|
} from "./version";
|
||||||
|
|
||||||
|
const DEV = "0.0.0";
|
||||||
|
const NIGHTLY = "0.304.0-dev+abc1234";
|
||||||
|
const STABLE = "0.303.1";
|
||||||
|
|
||||||
|
describe("isDevelopment", () => {
|
||||||
|
test("only dev builds", () => {
|
||||||
|
expect(isDevelopment(DEV)).toBe(true);
|
||||||
|
expect(isDevelopment(NIGHTLY)).toBe(false);
|
||||||
|
expect(isDevelopment(STABLE)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isNightly", () => {
|
||||||
|
test("only versions with build metadata", () => {
|
||||||
|
expect(isNightly(DEV)).toBe(false);
|
||||||
|
expect(isNightly(NIGHTLY)).toBe(true);
|
||||||
|
expect(isNightly(STABLE)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("commitFromVersion", () => {
|
||||||
|
test("extracts build metadata", () => {
|
||||||
|
expect(commitFromVersion(NIGHTLY)).toBe("abc1234");
|
||||||
|
expect(commitFromVersion(STABLE)).toBe("");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getReleaseName", () => {
|
||||||
|
test("maps version to release name", () => {
|
||||||
|
expect(getReleaseName(DEV)).toBe("development");
|
||||||
|
expect(getReleaseName(NIGHTLY)).toBe("nightly");
|
||||||
|
expect(getReleaseName(STABLE)).toBe("stable");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getShortVersion", () => {
|
||||||
|
test("formats version", () => {
|
||||||
|
expect(getShortVersion(DEV)).toBe("dev build");
|
||||||
|
expect(getShortVersion(NIGHTLY)).toBe("v0.304.0-dev+abc1234");
|
||||||
|
expect(getShortVersion(STABLE)).toBe("v0.303.1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isNewVersionAvailable", () => {
|
||||||
|
test("never for dev builds", () => {
|
||||||
|
expect(isNewVersionAvailable(DEV, "0.303.1")).toBe(false);
|
||||||
|
});
|
||||||
|
test("only when available differs", () => {
|
||||||
|
expect(isNewVersionAvailable(STABLE, "0.303.1")).toBe(false);
|
||||||
|
expect(isNewVersionAvailable("0.303.0", "0.303.1")).toBe(true);
|
||||||
|
expect(isNewVersionAvailable(STABLE, undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
export function isDevelopment(version: string): boolean {
|
export function isDevelopment(version: string): boolean {
|
||||||
return version === "[[.Version]]" || version === "0.0.0";
|
return version === "0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNightly(version: string, commit?: string): boolean {
|
// untagged builds carry the commit as build metadata: 0.304.0-dev+abc1234
|
||||||
return !isDevelopment(version) && !!commit;
|
export function isNightly(version: string): boolean {
|
||||||
|
return version.includes("+");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getReleaseName(version: string, commit?: string): string {
|
export function commitFromVersion(version: string): string {
|
||||||
|
return version.split("+")[1] ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getReleaseName(version: string): string {
|
||||||
if (isDevelopment(version)) return "development";
|
if (isDevelopment(version)) return "development";
|
||||||
if (isNightly(version, commit)) return "nightly";
|
if (isNightly(version)) return "nightly";
|
||||||
return "stable";
|
return "stable";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shortCommit(commit?: string): string {
|
export function getShortVersion(version: string): string {
|
||||||
return commit?.substring(0, 7) || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getShortVersion(version: string, commit?: string): string {
|
|
||||||
if (isDevelopment(version)) return "dev build";
|
if (isDevelopment(version)) return "dev build";
|
||||||
if (isNightly(version, commit)) return `v${version} (${shortCommit(commit)})`;
|
|
||||||
return `v${version}`;
|
return `v${version}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,6 @@ 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,
|
||||||
|
|
@ -117,7 +116,6 @@ export default defineComponent({
|
||||||
bottomTabBarProps() {
|
bottomTabBarProps() {
|
||||||
return {
|
return {
|
||||||
installed: window.evcc?.version,
|
installed: window.evcc?.version,
|
||||||
commit: window.evcc?.commit,
|
|
||||||
customBrand: this.custom.brand,
|
customBrand: this.custom.brand,
|
||||||
...this.collectProps(BottomTabBar, this.state),
|
...this.collectProps(BottomTabBar, this.state),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ 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"`
|
||||||
|
|
@ -54,7 +53,6 @@ func globalsJsHandler(custom Customization) http.HandlerFunc {
|
||||||
Phone string `json:"customPhone"`
|
Phone string `json:"customPhone"`
|
||||||
}{
|
}{
|
||||||
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,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import "runtime"
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DevVersion = "0.0.0"
|
const DevVersion = "0.0.0"
|
||||||
|
|
||||||
|
|
@ -15,10 +12,8 @@ var (
|
||||||
Commit = ""
|
Commit = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FormattedVersion returns the version, untagged builds carry the commit as build metadata
|
||||||
func FormattedVersion() string {
|
func FormattedVersion() string {
|
||||||
if Commit != "" {
|
|
||||||
return fmt.Sprintf("%s (%s)", Version, Commit)
|
|
||||||
}
|
|
||||||
return Version
|
return Version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue