feat: initial commit
This commit is contained in:
23
pkg/wails3kit/updates/wails/BUILD.bazel
Normal file
23
pkg/wails3kit/updates/wails/BUILD.bazel
Normal file
@@ -0,0 +1,23 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "wails",
|
||||
srcs = ["service.go"],
|
||||
importpath = "github.com/Eriyc/rules_wails/pkg/wails3kit/updates/wails",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/wails3kit/updates",
|
||||
"@com_github_wailsapp_wails_v3//pkg/application",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "wails_test",
|
||||
srcs = ["service_test.go"],
|
||||
embed = [":wails"],
|
||||
deps = [
|
||||
"//pkg/wails3kit/updates",
|
||||
"//pkg/wails3kit/updates/storage/file",
|
||||
"@com_github_wailsapp_wails_v3//pkg/application",
|
||||
],
|
||||
)
|
||||
110
pkg/wails3kit/updates/wails/service.go
Normal file
110
pkg/wails3kit/updates/wails/service.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Eriyc/rules_wails/pkg/wails3kit/updates"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
App *application.App
|
||||
Controller *updates.Controller
|
||||
EventName string
|
||||
AutoCheckOnStartup bool
|
||||
Emitter func(string, any)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
controller *updates.Controller
|
||||
eventName string
|
||||
autoCheckOnStartup bool
|
||||
emitter func(string, any)
|
||||
stop func()
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func RegisterEvents(eventName string) {
|
||||
if eventName == "" {
|
||||
eventName = "updates:state"
|
||||
}
|
||||
application.RegisterEvent[updates.Snapshot](eventName)
|
||||
}
|
||||
|
||||
func NewService(opts Options) *Service {
|
||||
eventName := opts.EventName
|
||||
if eventName == "" {
|
||||
eventName = "updates:state"
|
||||
}
|
||||
|
||||
emitter := opts.Emitter
|
||||
if emitter == nil && opts.App != nil {
|
||||
emitter = func(name string, data any) {
|
||||
opts.App.Event.Emit(name, data)
|
||||
}
|
||||
}
|
||||
|
||||
return &Service{
|
||||
controller: opts.Controller,
|
||||
eventName: eventName,
|
||||
autoCheckOnStartup: opts.AutoCheckOnStartup,
|
||||
emitter: emitter,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (service *Service) ServiceStartup(_ context.Context, _ application.ServiceOptions) error {
|
||||
if service.controller == nil {
|
||||
return updates.ErrInvalidConfig
|
||||
}
|
||||
|
||||
channel, stop := service.controller.Subscribe(4)
|
||||
service.stop = stop
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-service.done:
|
||||
return
|
||||
case snapshot := <-channel:
|
||||
if service.emitter != nil {
|
||||
service.emitter(service.eventName, snapshot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if service.autoCheckOnStartup {
|
||||
go func() {
|
||||
_, _ = service.Check()
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (service *Service) ServiceShutdown() error {
|
||||
if service.stop != nil {
|
||||
service.stop()
|
||||
}
|
||||
select {
|
||||
case <-service.done:
|
||||
default:
|
||||
close(service.done)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (service *Service) Snapshot() updates.Snapshot {
|
||||
return service.controller.Snapshot()
|
||||
}
|
||||
|
||||
func (service *Service) Check() (updates.Snapshot, error) {
|
||||
return service.controller.Check(context.Background(), updates.CheckRequest{})
|
||||
}
|
||||
|
||||
func (service *Service) Download() (updates.Snapshot, error) {
|
||||
return service.controller.Download(context.Background())
|
||||
}
|
||||
|
||||
func (service *Service) ApplyAndRestart() error {
|
||||
return service.controller.ApplyAndRestart(context.Background())
|
||||
}
|
||||
104
pkg/wails3kit/updates/wails/service_test.go
Normal file
104
pkg/wails3kit/updates/wails/service_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Eriyc/rules_wails/pkg/wails3kit/updates"
|
||||
filestore "github.com/Eriyc/rules_wails/pkg/wails3kit/updates/storage/file"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
func TestServiceEmitsSnapshots(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
release := &updates.Release{
|
||||
Version: "1.1.0",
|
||||
Channel: updates.ChannelStable,
|
||||
Artifact: updates.Artifact{
|
||||
Kind: updates.ArtifactKindBundleArchive,
|
||||
Format: updates.ArtifactFormatZip,
|
||||
URL: "https://example.invalid/app.zip",
|
||||
SHA256: "abc",
|
||||
},
|
||||
}
|
||||
controller, err := updates.NewController(updates.Config{
|
||||
App: updates.AppDescriptor{
|
||||
ProductID: "com.example.app",
|
||||
CurrentVersion: "1.0.0",
|
||||
Channel: updates.ChannelStable,
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
ExecutablePath: filepath.Join(t.TempDir(), "App"),
|
||||
},
|
||||
Provider: serviceFakeProvider{release: release},
|
||||
Downloader: serviceFakeDownloader{},
|
||||
Store: filestore.New(filepath.Join(t.TempDir(), "snapshot.json")),
|
||||
Platform: &serviceFakePlatform{root: updates.InstallRoot{Path: t.TempDir()}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("NewController returned error: %v", err)
|
||||
}
|
||||
|
||||
emitted := make(chan updates.Snapshot, 2)
|
||||
service := NewService(Options{
|
||||
Controller: controller,
|
||||
Emitter: func(_ string, data any) {
|
||||
emitted <- data.(updates.Snapshot)
|
||||
},
|
||||
})
|
||||
if err := service.ServiceStartup(context.Background(), application.ServiceOptions{}); err != nil {
|
||||
t.Fatalf("ServiceStartup returned error: %v", err)
|
||||
}
|
||||
defer service.ServiceShutdown()
|
||||
|
||||
if _, err := service.Check(); err != nil {
|
||||
t.Fatalf("Check returned error: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case snapshot := <-emitted:
|
||||
if snapshot.State == "" {
|
||||
t.Fatal("expected emitted snapshot state")
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timed out waiting for emitted snapshot")
|
||||
}
|
||||
}
|
||||
|
||||
type serviceFakeProvider struct {
|
||||
release *updates.Release
|
||||
}
|
||||
|
||||
func (provider serviceFakeProvider) Resolve(context.Context, updates.ResolveRequest) (*updates.Release, error) {
|
||||
return provider.release, nil
|
||||
}
|
||||
|
||||
func (provider serviceFakeProvider) OpenArtifact(context.Context, updates.Release) (io.ReadCloser, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type serviceFakeDownloader struct{}
|
||||
|
||||
func (serviceFakeDownloader) Download(context.Context, updates.Artifact) (updates.DownloadedFile, error) {
|
||||
return updates.DownloadedFile{}, nil
|
||||
}
|
||||
|
||||
type serviceFakePlatform struct {
|
||||
root updates.InstallRoot
|
||||
}
|
||||
|
||||
func (platform *serviceFakePlatform) DetectInstallRoot(updates.AppDescriptor) (updates.InstallRoot, error) {
|
||||
return platform.root, nil
|
||||
}
|
||||
|
||||
func (platform *serviceFakePlatform) Stage(context.Context, updates.InstallRoot, updates.DownloadedFile, updates.Release) (updates.StagedArtifact, error) {
|
||||
return updates.StagedArtifact{}, nil
|
||||
}
|
||||
|
||||
func (platform *serviceFakePlatform) SpawnApplyAndRestart(context.Context, updates.ApplyRequest) error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user