Skip to content
Snippets Groups Projects
Commit d65c4208 authored by Jono Wenger's avatar Jono Wenger
Browse files

Merge branch 'XX-4271/versioning' into 'release'

XX-4271 / Versioning

See merge request !17
parents 1ff7728d f98ed5dc
No related branches found
No related tags found
2 merge requests!60Revert "Fail a test to be sure it works",!17XX-4271 / Versioning
......@@ -4,9 +4,16 @@ This repository contains the WebAssembly bindings for xxDK. It also includes
examples and a test server to serve the compiled WebAssembly module.
**Note:** If you are updating the version of Go that this repository uses, you
need to ensure that you update the wasm_exec.js file as described
need to ensure that you update the `wasm_exec.js` file as described
[below](#wasm_execjs).
## Updates
The current semantic version of this repository is stored in `SEMVER` in
`version.go`. When making major updates or updates that create an
incompatibility in the storage or databases, the semantic version needs to be
updated and an upgrade path needs to be provided.
## Building
The repository can only be compiled to a WebAssembly binary using `GOOS=js` and
......
......@@ -26,6 +26,12 @@ func init() {
ll := wasm.NewJsConsoleLogListener(jww.LevelInfo)
jww.SetLogListeners(ll.Listen)
jww.SetStdoutThreshold(jww.LevelFatal + 1)
// Check that the WASM binary version is correct
err := utils.CheckAndStoreVersions()
if err != nil {
jww.FATAL.Panicf("WASM binary version error: %+v", err)
}
}
func main() {
......
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file. //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
package utils
import (
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/bindings"
"os"
)
// SEMVER is the current semantic version of xxDK WASM.
const SEMVER = "0.0.0"
// Storage keys.
const (
semverKey = "xxdkWasmSemanticVersion"
clientVerKey = "xxdkClientSemanticVersion"
)
// CheckAndStoreVersions checks that the stored xxDK WASM version matches the
// current version and if not, upgrades it. It also stored the current xxDK
// client to storage.
//
// On first load, only the xxDK WASM and xxDK client versions are stored.
func CheckAndStoreVersions() error {
return checkAndStoreVersions(
SEMVER, bindings.GetVersion(), GetLocalStorage())
}
func checkAndStoreVersions(
currentWasmVer, currentClientVer string, ls *LocalStorage) error {
// Get the stored client and WASM versions, if they exists
storedClientVer, err := initOrLoadStoredSemver(
clientVerKey, currentClientVer, ls)
if err != nil {
return err
}
storedWasmVer, err := initOrLoadStoredSemver(semverKey, currentWasmVer, ls)
if err != nil {
return err
}
// Check if client needs an update
if storedClientVer != currentClientVer {
jww.INFO.Printf("xxDK client out of date; upgrading version: v%s → v%s",
storedClientVer, currentClientVer)
} else {
jww.INFO.Printf("xxDK client version is current: v%s", storedClientVer)
}
// Check if WASM needs an update
if storedWasmVer != currentWasmVer {
jww.INFO.Printf("xxDK WASM out of date; upgrading version: v%s → v%s",
storedWasmVer, currentWasmVer)
} else {
jww.INFO.Printf("xxDK WASM version is current: v%s", storedWasmVer)
}
// Upgrade path code goes here
// Save current versions
ls.SetItem(clientVerKey, []byte(currentClientVer))
ls.SetItem(semverKey, []byte(currentWasmVer))
return nil
}
// initOrLoadStoredSemver returns the semantic version stored at the key in
// local storage. If no version is stored, then the current version is stored
// and returned.
func initOrLoadStoredSemver(
key, currentVersion string, ls *LocalStorage) (string, error) {
storedVersion, err := ls.GetItem(key)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
// Save the current version if this is the first run
jww.INFO.Printf("Initialising %s to v%s", key, currentVersion)
ls.SetItem(key, []byte(currentVersion))
return currentVersion, nil
} else {
// If the item exists, but cannot be loaded, return an error
return "", errors.Errorf(
"could not load %s from storage: %+v", key, err)
}
}
// Return the stored version
return string(storedVersion), nil
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file. //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
package utils
import (
"testing"
)
// Tests that checkAndStoreVersions correct initialises the client and WASM
// versions on first run and upgrades them correctly on subsequent runs.
func Test_checkAndStoreVersions(t *testing.T) {
ls := GetLocalStorage()
ls.Clear()
oldWasmVer := "0.1"
newWasmVer := "1.0"
oldClientVer := "2.5"
newClientVer := "2.6"
err := checkAndStoreVersions(oldWasmVer, oldClientVer, ls)
if err != nil {
t.Errorf("CheckAndStoreVersions error: %+v", err)
}
// Check client version
storedClientVer, err := ls.GetItem(clientVerKey)
if err != nil {
t.Errorf("Failed to get client version from storage: %+v", err)
}
if string(storedClientVer) != oldClientVer {
t.Errorf("Loaded client version does not match expected."+
"\nexpected: %s\nreceived: %s", oldClientVer, storedClientVer)
}
// Check WASM version
storedWasmVer, err := ls.GetItem(semverKey)
if err != nil {
t.Errorf("Failed to get WASM version from storage: %+v", err)
}
if string(storedWasmVer) != oldWasmVer {
t.Errorf("Loaded WASM version does not match expected."+
"\nexpected: %s\nreceived: %s", oldWasmVer, storedWasmVer)
}
err = checkAndStoreVersions(newWasmVer, newClientVer, ls)
if err != nil {
t.Errorf("CheckAndStoreVersions error: %+v", err)
}
// Check client version
storedClientVer, err = ls.GetItem(clientVerKey)
if err != nil {
t.Errorf("Failed to get client version from storage: %+v", err)
}
if string(storedClientVer) != newClientVer {
t.Errorf("Loaded client version does not match expected."+
"\nexpected: %s\nreceived: %s", newClientVer, storedClientVer)
}
// Check WASM version
storedWasmVer, err = ls.GetItem(semverKey)
if err != nil {
t.Errorf("Failed to get WASM version from storage: %+v", err)
}
if string(storedWasmVer) != newWasmVer {
t.Errorf("Loaded WASM version does not match expected."+
"\nexpected: %s\nreceived: %s", newWasmVer, storedWasmVer)
}
}
// Tests that initOrLoadStoredSemver initialises the correct version on first run
// and returns the same version on subsequent runs.
func Test_initOrLoadStoredSemver(t *testing.T) {
ls := GetLocalStorage()
key := "testKey"
oldVersion := "0.1"
loadedVersion, err := initOrLoadStoredSemver(key, oldVersion, ls)
if err != nil {
t.Errorf("Failed to intilaise version: %+v", err)
}
if loadedVersion != oldVersion {
t.Errorf("Loaded version does not match expected."+
"\nexpected: %s\nreceived: %s", oldVersion, loadedVersion)
}
loadedVersion, err = initOrLoadStoredSemver(key, "something", ls)
if err != nil {
t.Errorf("Failed to load version: %+v", err)
}
if loadedVersion != oldVersion {
t.Errorf("Loaded version does not match expected."+
"\nexpected: %s\nreceived: %s", oldVersion, loadedVersion)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment