-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(updater): add self-update from github releases
- Loading branch information
Showing
11 changed files
with
314 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,46 +18,22 @@ jobs: | |
fail-fast: false | ||
matrix: | ||
build: | ||
- name: 'mult-game' | ||
- name: 'mult-game_linux-amd64' | ||
platform: 'linux/amd64' | ||
arch: 'linux-amd64' | ||
os: 'ubuntu-latest' | ||
- name: 'mult-game' | ||
- name: 'mult-game_windows-amd64' | ||
platform: 'windows/amd64' | ||
arch: 'windows-amd64' | ||
os: 'windows-latest' | ||
- name: 'mult-game' | ||
platform: 'darwin/universal' | ||
os: 'macos-latest' | ||
arch: 'darwin-universal' | ||
|
||
runs-on: ${{ matrix.build.os }} | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
submodules: recursive | ||
|
||
- name: Build wails | ||
- name: Build & Deploy | ||
uses: dAppServer/[email protected] | ||
id: build | ||
with: | ||
build-name: ${{ matrix.build.name }}_${{ matrix.build.arch }} | ||
build-name: ${{ matrix.build.name }} | ||
build-platform: ${{ matrix.build.platform }} | ||
package: false | ||
go-version: '1.21' | ||
# - name: Build Windows App + Installer | ||
# run: wails build --platform windows/amd64 -webview2 download -nsis -o 'mult-game-installer' | ||
# shell: bash | ||
- uses: actions/upload-artifact@v3 | ||
with: | ||
name: Wails Build ${{runner.os}} mult-game | ||
path: | | ||
*/bin/ | ||
*\bin\* | ||
- name: Release | ||
uses: softprops/action-gh-release@v1 | ||
if: startsWith(github.ref, 'refs/tags/') | ||
with: | ||
files: | | ||
*/bin/* | ||
go-version: 1.21 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,17 @@ | ||
# README | ||
# Mult-game | ||
|
||
## About | ||
|
||
This is the official Wails Vue-TS template. | ||
Mult-game is a little game made to help memorizing multiplication table. | ||
|
||
You can configure the project by editing `wails.json`. More information about the project settings can be found | ||
here: https://wails.io/docs/reference/project-config | ||
It's pretty simple : once you started the game, it will ask you to solve a multiplication in less than 20 sec. | ||
- If you succeed, it will increase your current streak. Every five successful answer, the max timer duration will decrease by 4 second to a limit of 4 second (to ensure you remembered the results). | ||
- If you fail, it's game over. You'll be able to register your score (using a 3 characters long nickname) and start over !. | ||
|
||
## Live Development | ||
The game is supposed to be able to update itself on launch. | ||
|
||
To run in live development mode, run `wails dev` in the project directory. This will run a Vite development | ||
server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser | ||
and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect | ||
to this in your browser, and you can call your Go code from devtools. | ||
More features are to come : | ||
|
||
## Building | ||
|
||
To build a redistributable, production mode package, use `wails build`. | ||
- [ ] live score display | ||
- [ ] new difficulty mode (easier than the existing one) | ||
- [ ] might add some other mod later |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
package update | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"mult-game/backend/logger" | ||
"mult-game/backend/version" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"runtime" | ||
"strings" | ||
|
||
"github.com/blang/semver" | ||
"github.com/google/go-github/v59/github" | ||
"go.uber.org/fx" | ||
"golang.org/x/exp/slices" | ||
) | ||
|
||
const ( | ||
owner = "mJehanno" | ||
repo = "op-game" | ||
) | ||
|
||
type ErrorHandler struct { | ||
log *logger.Logger | ||
} | ||
|
||
func NewErrorHandler(log *logger.Logger) *ErrorHandler { | ||
return &ErrorHandler{ | ||
log: log, | ||
} | ||
} | ||
|
||
func (eh *ErrorHandler) handleErr(err error, message string) { | ||
if err != nil { | ||
eh.log.ErrLogger.WithError(err).Error(message) | ||
} | ||
} | ||
|
||
type Updater struct { | ||
log *logger.Logger | ||
eh *ErrorHandler | ||
vm *version.VersionManager | ||
client *github.Client | ||
latest semver.Version | ||
rel *github.RepositoryRelease | ||
platform string | ||
dlPath string | ||
} | ||
|
||
type UpdaterParams struct { | ||
fx.In | ||
|
||
Log *logger.Logger | ||
Eh *ErrorHandler | ||
Vm *version.VersionManager | ||
Client *github.Client | ||
} | ||
|
||
func NewUpdater(p UpdaterParams) *Updater { | ||
platf := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH) | ||
return &Updater{ | ||
log: p.Log, | ||
eh: p.Eh, | ||
vm: p.Vm, | ||
client: p.Client, | ||
platform: platf, | ||
} | ||
} | ||
|
||
func (u *Updater) isCurrentLatest(ctx context.Context) bool { | ||
rel, _, err := u.client.Repositories.GetLatestRelease(ctx, owner, repo) | ||
if err != nil { | ||
u.eh.handleErr(err, "failed to retrieve latest release") | ||
return true | ||
} | ||
u.rel = rel | ||
|
||
latest := semver.MustParse(strings.ReplaceAll(rel.GetTagName(), "v", "")) | ||
u.latest = latest | ||
return latest.EQ(semver.MustParse(u.vm.GetCurrentVersion())) | ||
} | ||
|
||
func (u *Updater) getAsset() (*github.ReleaseAsset, error) { | ||
|
||
index := slices.IndexFunc(u.rel.Assets, func(ra *github.ReleaseAsset) bool { | ||
return strings.Contains(*ra.Name, u.platform) | ||
}) | ||
|
||
if index == -1 { | ||
err := fmt.Errorf("asszt not found") | ||
u.log.ErrLogger.WithError(err).Error("failed to retrieve corresponding release asset") | ||
return nil, err | ||
} | ||
|
||
return u.rel.Assets[index], nil | ||
} | ||
|
||
func (u *Updater) downloadAsset(ctx context.Context, asset github.ReleaseAsset) error { | ||
reader, redirect, err := u.client.Repositories.DownloadReleaseAsset(ctx, owner, repo, asset.GetID(), http.DefaultClient) | ||
if err != nil { | ||
err = fmt.Errorf("failed to download release asset -> %w", err) | ||
return err | ||
} | ||
|
||
if redirect != "" { | ||
return fmt.Errorf("need to learn how to use the redirect url") | ||
} | ||
|
||
u.dlPath = path.Join(os.TempDir(), *asset.Name) | ||
|
||
f, err := os.Create(u.dlPath) | ||
if err != nil { | ||
err = fmt.Errorf("failed to create temp downloaded release asset -> %w", err) | ||
return err | ||
} | ||
|
||
defer func() { | ||
f.Close() | ||
reader.Close() | ||
}() | ||
|
||
_, err = io.Copy(f, reader) | ||
if err != nil { | ||
err = fmt.Errorf("failed to write downloaded release asset -> %w", err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (u *Updater) installNewRelease() error { | ||
exePath, err := os.Executable() | ||
if err != nil { | ||
u.log.ErrLogger.WithError(err).Error("failed to retrieve current process executable") | ||
return err | ||
} | ||
|
||
err = os.Rename(exePath, fmt.Sprintf("%s-old", exePath)) | ||
if err != nil { | ||
u.log.ErrLogger.WithError(err).Error("failed to rename old binary") | ||
return err | ||
} | ||
|
||
if strings.Contains(u.platform, "linux") { | ||
os.Rename(u.dlPath, exePath) | ||
os.Chmod(exePath, 0775) | ||
err := exec.Command(exePath).Run() | ||
if err != nil { | ||
u.log.ErrLogger.WithError(err).Error("failed to launch new binary") | ||
// rollingback | ||
err = os.Remove(exePath) | ||
if err != nil { | ||
u.log.ErrLogger.WithError(err).Error("failed to remove new binary") | ||
} | ||
err = os.Rename(fmt.Sprintf("%s-old", exePath), exePath) | ||
if err != nil { | ||
u.log.ErrLogger.WithError(err).Error("failed to rename old binary") | ||
} | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (u *Updater) DoSelfUpdate(ctx context.Context) { | ||
if u.isCurrentLatest(ctx) { | ||
u.log.DebugLogger.Debug("current version is the latest") | ||
return | ||
} | ||
u.log.DebugLogger.Debugf("latest version is %s, current is %s", u.latest, u.vm.GetCurrentVersion()) | ||
|
||
asset, err := u.getAsset() | ||
u.eh.handleErr(err, "failed to find asset") | ||
if err != nil { | ||
return | ||
} | ||
|
||
err = u.downloadAsset(ctx, *asset) | ||
u.eh.handleErr(err, "failed to download asset") | ||
if err != nil { | ||
return | ||
} | ||
|
||
err = u.installNewRelease() | ||
u.eh.handleErr(err, "failed to install new release") | ||
if err == nil { | ||
os.Exit(0) | ||
} | ||
|
||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
64960eb47bdef8bcd540e66fad35bb73 | ||
3a91b86ead97a4984943fff36a4cf9ac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.