Establish beta and staging release channels, move indexes to helper
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/safing/portbase/notifications"
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
"github.com/tevino/abool"
|
||||
|
||||
"github.com/safing/portbase/config"
|
||||
@@ -20,6 +21,7 @@ var (
|
||||
devMode config.BoolOption
|
||||
enableUpdates config.BoolOption
|
||||
|
||||
initialReleaseChannel string
|
||||
previousReleaseChannel string
|
||||
updatesCurrentlyEnabled bool
|
||||
previousDevMode bool
|
||||
@@ -29,21 +31,28 @@ var (
|
||||
func registerConfig() error {
|
||||
err := config.Register(&config.Option{
|
||||
Name: "Release Channel",
|
||||
Key: releaseChannelKey,
|
||||
Key: helper.ReleaseChannelKey,
|
||||
Description: "Switch release channel.",
|
||||
OptType: config.OptTypeString,
|
||||
ExpertiseLevel: config.ExpertiseLevelDeveloper,
|
||||
ReleaseLevel: config.ReleaseLevelExperimental,
|
||||
RequiresRestart: false,
|
||||
DefaultValue: releaseChannelStable,
|
||||
RequiresRestart: true,
|
||||
DefaultValue: helper.ReleaseChannelStable,
|
||||
PossibleValues: []config.PossibleValue{
|
||||
{
|
||||
Name: "Stable",
|
||||
Value: releaseChannelStable,
|
||||
Name: "Stable",
|
||||
Description: "Production releases.",
|
||||
Value: helper.ReleaseChannelStable,
|
||||
},
|
||||
{
|
||||
Name: "Beta",
|
||||
Value: releaseChannelBeta,
|
||||
Name: "Beta",
|
||||
Description: "Production releases for testing new features that may break and cause interruption.",
|
||||
Value: helper.ReleaseChannelBeta,
|
||||
},
|
||||
{
|
||||
Name: "Staging",
|
||||
Description: "Development releases for testing random things and experimenting. Dangerous - only use when told so.",
|
||||
Value: helper.ReleaseChannelStaging,
|
||||
},
|
||||
},
|
||||
Annotations: config.Annotations{
|
||||
@@ -78,7 +87,8 @@ func registerConfig() error {
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
releaseChannel = config.GetAsString(releaseChannelKey, releaseChannelStable)
|
||||
releaseChannel = config.GetAsString(helper.ReleaseChannelKey, helper.ReleaseChannelStable)
|
||||
initialReleaseChannel = releaseChannel()
|
||||
previousReleaseChannel = releaseChannel()
|
||||
|
||||
enableUpdates = config.GetAsBool(enableUpdatesKey, true)
|
||||
@@ -107,7 +117,7 @@ func updateRegistryConfig(_ context.Context, _ interface{}) error {
|
||||
changed := false
|
||||
|
||||
if releaseChannel() != previousReleaseChannel {
|
||||
registry.SetBeta(releaseChannel() == releaseChannelBeta)
|
||||
registry.SetUsePreReleases(releaseChannel() != helper.ReleaseChannelStable)
|
||||
previousReleaseChannel = releaseChannel()
|
||||
changed = true
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ import (
|
||||
"github.com/safing/portbase/info"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/updater"
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
)
|
||||
|
||||
// database key for update information
|
||||
// Database key for update information.
|
||||
const (
|
||||
versionsDBKey = "core:status/versions"
|
||||
)
|
||||
|
||||
// working vars
|
||||
var (
|
||||
versionExport *versions
|
||||
versionExportDB = database.NewInterface(&database.Options{
|
||||
@@ -35,6 +35,7 @@ type versions struct {
|
||||
|
||||
Core *info.Info
|
||||
Resources map[string]*updater.Resource
|
||||
Channel string
|
||||
Beta bool
|
||||
Staging bool
|
||||
|
||||
@@ -45,8 +46,9 @@ func initVersionExport() (err error) {
|
||||
// init export struct
|
||||
versionExport = &versions{
|
||||
internalSave: true,
|
||||
Beta: registry.Beta,
|
||||
Staging: staging,
|
||||
Channel: initialReleaseChannel,
|
||||
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
|
||||
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
|
||||
}
|
||||
versionExport.SetKey(versionsDBKey)
|
||||
|
||||
@@ -68,7 +70,7 @@ func stopVersionExport() error {
|
||||
return versionExportHook.Cancel()
|
||||
}
|
||||
|
||||
// export is an event hook
|
||||
// export is an event hook.
|
||||
func export(_ context.Context, _ interface{}) error {
|
||||
// populate
|
||||
versionExport.lock.Lock()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -54,14 +53,6 @@ func EnsureChromeSandboxPermissions(reg *updater.ResourceRegistry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlatformIdentifier converts identifier for the current platform.
|
||||
func PlatformIdentifier(identifier string) string {
|
||||
// From https://golang.org/pkg/runtime/#GOARCH
|
||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
func checkSysctl(setting string, value byte) bool {
|
||||
c, err := sysctl(setting)
|
||||
if err != nil {
|
||||
|
||||
50
updates/helper/indexes.go
Normal file
50
updates/helper/indexes.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/updater"
|
||||
)
|
||||
|
||||
const (
|
||||
ReleaseChannelKey = "core/releaseChannel"
|
||||
ReleaseChannelJSONKey = "core.releaseChannel"
|
||||
ReleaseChannelStable = "stable"
|
||||
ReleaseChannelBeta = "beta"
|
||||
ReleaseChannelStaging = "staging"
|
||||
)
|
||||
|
||||
func SetIndexes(registry *updater.ResourceRegistry, releaseChannel string) {
|
||||
// Be reminded that the order is important, as indexes added later will
|
||||
// override the current release from earlier indexes.
|
||||
|
||||
// Reset indexes before adding them (again).
|
||||
registry.ResetIndexes()
|
||||
|
||||
// Always add the stable index as a base.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "stable.json",
|
||||
})
|
||||
|
||||
// Add beta index if in beta or staging channel.
|
||||
if releaseChannel == ReleaseChannelBeta ||
|
||||
releaseChannel == ReleaseChannelStaging {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "beta.json",
|
||||
PreRelease: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add staging index if in staging channel.
|
||||
if releaseChannel == ReleaseChannelStaging {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "staging.json",
|
||||
PreRelease: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add the intel index last, as it updates the fastest and should not be
|
||||
// crippled by other faulty indexes. It can only specify versions for its
|
||||
// scope anyway.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "all/intel/intel.json",
|
||||
})
|
||||
}
|
||||
68
updates/helper/updates.go
Normal file
68
updates/helper/updates.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
onWindows = runtime.GOOS == "windows"
|
||||
)
|
||||
|
||||
// PlatformIdentifier converts identifier for the current platform.
|
||||
func PlatformIdentifier(identifier string) string {
|
||||
// From https://golang.org/pkg/runtime/#GOARCH
|
||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
// MandatoryUpdates returns mandatory updates that should be loaded on install
|
||||
// or reset.
|
||||
func MandatoryUpdates() (identifiers []string) {
|
||||
// Binaries
|
||||
if onWindows {
|
||||
identifiers = []string{
|
||||
PlatformIdentifier("core/portmaster-core.exe"),
|
||||
PlatformIdentifier("kext/portmaster-kext.dll"),
|
||||
PlatformIdentifier("kext/portmaster-kext.sys"),
|
||||
PlatformIdentifier("start/portmaster-start.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-snoretoast.exe"),
|
||||
}
|
||||
} else {
|
||||
identifiers = []string{
|
||||
PlatformIdentifier("core/portmaster-core"),
|
||||
PlatformIdentifier("start/portmaster-start"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier"),
|
||||
}
|
||||
}
|
||||
|
||||
// Components, Assets and Data
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
|
||||
// User interface components
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
"all/ui/modules/assets.zip",
|
||||
|
||||
// Filter lists data
|
||||
"all/intel/lists/base.dsdl",
|
||||
"all/intel/lists/intermediate.dsdl",
|
||||
"all/intel/lists/urgent.dsdl",
|
||||
|
||||
// Geo IP data
|
||||
"all/intel/geoip/geoipv4.mmdb.gz",
|
||||
"all/intel/geoip/geoipv6.mmdb.gz",
|
||||
)
|
||||
|
||||
return identifiers
|
||||
}
|
||||
|
||||
// AutoUnpackUpdates returns assets that need unpacking.
|
||||
func AutoUnpackUpdates() []string {
|
||||
return []string{
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
}
|
||||
}
|
||||
105
updates/main.go
105
updates/main.go
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
|
||||
"github.com/safing/portbase/dataroot"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/modules"
|
||||
@@ -19,10 +19,6 @@ import (
|
||||
const (
|
||||
onWindows = runtime.GOOS == "windows"
|
||||
|
||||
releaseChannelKey = "core/releaseChannel"
|
||||
releaseChannelStable = "stable"
|
||||
releaseChannelBeta = "beta"
|
||||
|
||||
enableUpdatesKey = "core/automaticUpdates"
|
||||
|
||||
// ModuleName is the name of the update module
|
||||
@@ -48,16 +44,11 @@ var (
|
||||
module *modules.Module
|
||||
registry *updater.ResourceRegistry
|
||||
userAgentFromFlag string
|
||||
staging bool
|
||||
|
||||
updateTask *modules.Task
|
||||
updateASAP bool
|
||||
disableTaskSchedule bool
|
||||
|
||||
// MandatoryUpdates is a list of full identifiers that
|
||||
// should always be kept up to date.
|
||||
MandatoryUpdates []string
|
||||
|
||||
// UserAgent is an HTTP User-Agent that is used to add
|
||||
// more context to requests made by the registry when
|
||||
// fetching resources from the update server.
|
||||
@@ -65,9 +56,8 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
updateInProgress = "updates:in-progress"
|
||||
updateFailed = "updates:failed"
|
||||
updateSuccess = "updates:success"
|
||||
updateFailed = "updates:failed"
|
||||
updateSuccess = "updates:success"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -76,29 +66,9 @@ func init() {
|
||||
module.RegisterEvent(ResourceUpdateEvent, true)
|
||||
|
||||
flag.StringVar(&userAgentFromFlag, "update-agent", "", "set the user agent for requests to the update server")
|
||||
flag.BoolVar(&staging, "staging", false, "use staging update channel; for testing only")
|
||||
|
||||
// initialize mandatory updates
|
||||
if onWindows {
|
||||
MandatoryUpdates = []string{
|
||||
platform("core/portmaster-core.exe"),
|
||||
platform("start/portmaster-start.exe"),
|
||||
platform("notifier/portmaster-notifier.exe"),
|
||||
platform("notifier/portmaster-snoretoast.exe"),
|
||||
}
|
||||
} else {
|
||||
MandatoryUpdates = []string{
|
||||
platform("core/portmaster-core"),
|
||||
platform("start/portmaster-start"),
|
||||
platform("notifier/portmaster-notifier"),
|
||||
}
|
||||
}
|
||||
|
||||
MandatoryUpdates = append(
|
||||
MandatoryUpdates,
|
||||
platform("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
)
|
||||
var dummy bool
|
||||
flag.BoolVar(&dummy, "staging", false, "deprecated, configure in settings instead")
|
||||
}
|
||||
|
||||
func prep() error {
|
||||
@@ -107,8 +77,6 @@ func prep() error {
|
||||
}
|
||||
|
||||
return registerAPIEndpoints()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func start() error {
|
||||
@@ -131,13 +99,11 @@ func start() error {
|
||||
"https://updates.safing.io",
|
||||
},
|
||||
UserAgent: UserAgent,
|
||||
MandatoryUpdates: MandatoryUpdates,
|
||||
AutoUnpack: []string{
|
||||
platform("app/portmaster-app.zip"),
|
||||
},
|
||||
Beta: releaseChannel() == releaseChannelBeta,
|
||||
DevMode: devMode(),
|
||||
Online: true,
|
||||
MandatoryUpdates: helper.MandatoryUpdates(),
|
||||
AutoUnpack: helper.AutoUnpackUpdates(),
|
||||
UsePreReleases: initialReleaseChannel != helper.ReleaseChannelStable,
|
||||
DevMode: devMode(),
|
||||
Online: true,
|
||||
}
|
||||
if userAgentFromFlag != "" {
|
||||
// override with flag value
|
||||
@@ -149,38 +115,8 @@ func start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "stable.json",
|
||||
Stable: true,
|
||||
Beta: false,
|
||||
})
|
||||
|
||||
if registry.Beta {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "beta.json",
|
||||
Stable: false,
|
||||
Beta: true,
|
||||
})
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "all/intel/intel.json",
|
||||
Stable: true,
|
||||
Beta: true,
|
||||
})
|
||||
|
||||
if stagingActive() {
|
||||
// Set flag no matter how staging was activated.
|
||||
staging = true
|
||||
|
||||
log.Warning("updates: staging environment is active")
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "staging.json",
|
||||
Stable: true,
|
||||
Beta: true,
|
||||
})
|
||||
}
|
||||
// Set indexes based on the release channel.
|
||||
helper.SetIndexes(registry, initialReleaseChannel)
|
||||
|
||||
err = registry.LoadIndexes(module.Ctx)
|
||||
if err != nil {
|
||||
@@ -342,21 +278,6 @@ func stop() error {
|
||||
return stopVersionExport()
|
||||
}
|
||||
|
||||
func platform(identifier string) string {
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
func stagingActive() bool {
|
||||
// Check flag and env variable.
|
||||
if staging || os.Getenv("PORTMASTER_STAGING") == "enabled" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if staging index is present and acessible.
|
||||
_, err := os.Stat(filepath.Join(registry.StorageDir().Path, "staging.json"))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RootPath returns the root path used for storing updates.
|
||||
func RootPath() string {
|
||||
if !module.Online() {
|
||||
|
||||
@@ -351,10 +351,9 @@ func upgradeFile(fileToUpgrade string, file *updater.File) error {
|
||||
}
|
||||
|
||||
// CopyFile atomically copies a file using the update registry's tmp dir.
|
||||
func CopyFile(srcPath, dstPath string) (err error) {
|
||||
|
||||
func CopyFile(srcPath, dstPath string) error {
|
||||
// check tmp dir
|
||||
err = registry.TmpDir().Ensure()
|
||||
err := registry.TmpDir().Ensure()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not prepare tmp directory for copying file: %w", err)
|
||||
}
|
||||
@@ -369,14 +368,14 @@ func CopyFile(srcPath, dstPath string) (err error) {
|
||||
// open source
|
||||
srcFile, err := os.Open(srcPath)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// copy data
|
||||
_, err = io.Copy(atomicDstFile, srcFile)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// finalize file
|
||||
|
||||
Reference in New Issue
Block a user