Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 80 additions & 41 deletions .github/workflows/build-artifacts.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: Build artifacts

on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
version:
Expand All @@ -13,7 +16,11 @@ permissions:
contents: read

env:
RELEASE_VERSION: ${{ inputs.version }}
RELEASE_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}

concurrency:
group: build-artifacts-${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
cancel-in-progress: false

jobs:
frontend:
Expand Down Expand Up @@ -57,7 +64,7 @@ jobs:

build:
needs: frontend
name: Build ${{ matrix.target.platform }} ${{ matrix.arch }}
name: Build ${{ matrix.target.platform }} ${{ matrix.arch.label }}
runs-on: ${{ matrix.target.runner }}
strategy:
fail-fast: false
Expand All @@ -73,13 +80,15 @@ jobs:
cgo: 0
suffix: .exe
desktop_ldflags: -w -s -H windowsgui
arch: [x64, arm64]
arch:
- {label: x64, goarch: amd64, ota: amd64}
- {label: arm64, goarch: arm64, ota: arm64}

env:
CGO_ENABLED: ${{ matrix.target.cgo }}
CGO_CFLAGS: ${{ matrix.target.platform == 'macos' && '-mmacosx-version-min=12.0' || '' }}
CGO_LDFLAGS: ${{ matrix.target.platform == 'macos' && '-mmacosx-version-min=12.0' || '' }}
GOARCH: ${{ matrix.arch == 'x64' && 'amd64' || 'arm64' }}
GOARCH: ${{ matrix.arch.goarch }}
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.target.platform == 'macos' && '12.0' || '' }}

steps:
Expand All @@ -104,14 +113,6 @@ jobs:
go build -tags wails,production -trimpath -buildvcs=false -ldflags="${{ matrix.target.desktop_ldflags }} $version_ldflag" -o "bin/oneagent-desktop${{ matrix.target.suffix }}" ./cmd/oneagent-desktop
go build -trimpath -buildvcs=false -ldflags="-w -s $version_ldflag" -o "bin/oneagent${{ matrix.target.suffix }}" ./cmd/oneagent

- name: Verify production Go dependency inventory
shell: bash
run: |
python3 scripts/generate_third_party_licenses.py \
--verify-platform "${{ matrix.target.platform }}-${{ matrix.arch }}" \
--verify-go-binary "bin/oneagent-desktop${{ matrix.target.suffix }}" \
--verify-go-binary "bin/oneagent${{ matrix.target.suffix }}"

- name: Package macOS app
if: matrix.target.platform == 'macos'
shell: bash
Expand All @@ -126,39 +127,77 @@ jobs:
codesign --force --deep --sign - "bin/OneAgent.app"
rm "bin/oneagent-desktop"

- name: Add license material to artifact
shell: bash
run: |
cp LICENSE NOTICE third_party/THIRD_PARTY_NOTICES.md bin/
cp -R third_party/licenses bin/licenses
if [[ "${{ matrix.target.platform }}" == "macos" ]]; then
compliance="bin/OneAgent.app/Contents/Resources/compliance"
mkdir -p "$compliance"
cp LICENSE NOTICE third_party/THIRD_PARTY_NOTICES.md "$compliance/"
cp -R third_party/licenses "$compliance/licenses"
fi
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: OneAgent-${{ matrix.target.platform }}-${{ matrix.arch.label }}
path: bin/*
if-no-files-found: error
compression-level: 0

- name: Verify artifact license material
- name: Package macOS OTA archive
if: matrix.target.platform == 'macos'
shell: bash
run: |
test -f bin/LICENSE
test -f bin/NOTICE
test -f bin/THIRD_PARTY_NOTICES.md
test -f bin/licenses/go/github.com_go-ole_go-ole@v1.3.0/LICENSE
test -f bin/licenses/npm/react-router@7.18.1/LICENSE.md
test -f bin/licenses/npm/scheduler@0.27.0/LICENSE
test -f bin/licenses/npm/cookie@1.0.1/LICENSE
test -f bin/licenses/npm/set-cookie-parser@2.6.0/LICENSE
if [[ "${{ matrix.target.platform }}" == "macos" ]]; then
test -f bin/OneAgent.app/Contents/Resources/compliance/LICENSE
test -f bin/OneAgent.app/Contents/Resources/compliance/NOTICE
test -f bin/OneAgent.app/Contents/Resources/compliance/THIRD_PARTY_NOTICES.md
fi
(cd bin && zip -qry "OneAgent-darwin-${{ matrix.arch.ota }}.zip" OneAgent.app)
roots="$(unzip -Z1 "bin/OneAgent-darwin-${{ matrix.arch.ota }}.zip" | awk -F/ 'NF {print $1}' | sort -u)"
test "$roots" = OneAgent.app

- name: Upload artifact
- name: Package Windows OTA archive
if: matrix.target.platform == 'windows'
shell: pwsh
run: |
$archive = "bin/OneAgent-windows-${{ matrix.arch.ota }}.zip"
Compress-Archive -Path "bin/oneagent-desktop.exe" -DestinationPath $archive
$roots = @(tar -tf $archive | ForEach-Object { ($_ -split '/')[0] } | Where-Object { $_ } | Sort-Object -Unique)
if ($roots.Count -ne 1 -or $roots[0] -ne "oneagent-desktop.exe") {
throw "unexpected OTA archive roots: $($roots -join ', ')"
}

- name: Upload OTA archive
uses: actions/upload-artifact@v7
with:
name: OneAgent-${{ matrix.target.platform }}-${{ matrix.arch }}
path: bin/*
name: ota-${{ matrix.target.platform }}-${{ matrix.arch.label }}
path: bin/OneAgent-${{ matrix.target.platform == 'macos' && 'darwin' || 'windows' }}-${{ matrix.arch.ota }}.zip
if-no-files-found: error
compression-level: 0

release:
needs: build
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
name: Publish release
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- name: Download OTA archives
uses: actions/download-artifact@v8
with:
pattern: ota-*
path: release-assets
merge-multiple: true

- name: Validate and publish release
shell: bash
run: |
set -euo pipefail
expected=(
OneAgent-darwin-amd64.zip
OneAgent-darwin-arm64.zip
OneAgent-windows-amd64.zip
OneAgent-windows-arm64.zip
)
mapfile -t archives < <(find release-assets -maxdepth 1 -type f -name 'OneAgent-*.zip' -printf '%f\n' | sort)
test "${#archives[@]}" -eq 4
diff <(printf '%s\n' "${expected[@]}" | sort) <(printf '%s\n' "${archives[@]}")
(cd release-assets && sha256sum OneAgent-*.zip > SHA256SUMS)
test "$(wc -l < release-assets/SHA256SUMS)" -eq 4

if gh release view "$RELEASE_VERSION" >/dev/null 2>&1; then
gh release upload "$RELEASE_VERSION" release-assets/* --clobber
gh release edit "$RELEASE_VERSION" --draft=false --prerelease=false
else
gh release create "$RELEASE_VERSION" release-assets/* --verify-tag --title "$RELEASE_VERSION" --generate-notes
fi
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,10 @@ documentation link and language check.

## Releasing

Release packages are built by `.github/workflows/build-artifacts.yml`, triggered manually
via `workflow_dispatch`. It builds x64 and arm64 Wails desktop binaries and pure Go CLIs
for macOS and Windows, packaging the macOS artifacts as `.app`.
Pushing a stable `vX.Y.Z` tag triggers `.github/workflows/build-artifacts.yml` and publishes
macOS and Windows OTA archives for amd64 and arm64, plus `SHA256SUMS`, to the matching
GitHub Release. Each macOS archive contains `OneAgent.app`; each Windows archive contains
`oneagent-desktop.exe`. The workflow can also be run manually with a required version.

Wails is still in Alpha, so there is no Stable release, and no platform signing,
notarization, or store distribution. The signing gate for Stable is deferred to a later
Expand Down
34 changes: 34 additions & 0 deletions cmd/oneagent-desktop/main_wails.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,33 @@ import (
"github.com/MaimoryLab/OneAgent/internal/binding"
oneerrors "github.com/MaimoryLab/OneAgent/internal/errors"
"github.com/MaimoryLab/OneAgent/internal/process"
"github.com/MaimoryLab/OneAgent/internal/version"
"github.com/wailsapp/wails/v3/pkg/application"
"github.com/wailsapp/wails/v3/pkg/updater"
"github.com/wailsapp/wails/v3/pkg/updater/providers/github"
)

func configureUpdater(appInstance *application.App) binding.UpdateBackend {
current := version.UpdaterVersion()
if current == "" {
return nil
}
provider, err := github.New(github.Config{Repository: "MaimoryLab/OneAgent", ChecksumAsset: "SHA256SUMS"})
if err != nil {
slog.Error("OneAgent updater provider is unavailable", "error", err)
return nil
}
if err := appInstance.Updater.Init(updater.Config{
CurrentVersion: current,
Providers: []updater.Provider{provider},
Window: updater.WindowNone,
}); err != nil {
slog.Error("OneAgent updater is unavailable", "error", err)
return nil
}
return appInstance.Updater
}

func main() {
var appInstance *application.App
core := newDesktopUseCases()
Expand Down Expand Up @@ -70,6 +94,16 @@ func main() {
},
Mac: application.MacOptions{ApplicationShouldTerminateAfterLastWindowClosed: true},
})
updateBackend := configureUpdater(appInstance)
appInstance.Event.On(updater.EventDownloadProgress, func(event *application.CustomEvent) {
if event == nil {
return
}
if output, ok := binding.UpdateProgressOutput(event.Data); ok {
appInstance.Event.Emit("oneagent:install-output", output)
}
})
appInstance.RegisterService(application.NewServiceWithOptions(binding.NewUpdateService(updateBackend), application.ServiceOptions{MarshalError: oneerrors.Marshal}))
if !application.System.IsServer() {
// A floor, not a second breakpoint: the sidebar deliberately collapses to
// a 72px icon rail under 900px, and the layout is verified down to 560px.
Expand Down
Loading
Loading