diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e139013 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,492 @@ +name: Build Action self-tests + +on: + push: + branches: [ "main", "v3", "dev", "*-*" ] + pull_request: + branches: [ "main", "v3", "dev", "*-*" ] + workflow_dispatch: + +jobs: + discovery-tests: + name: Discovery sub-action tests on ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - id: disc + uses: ./actions/discovery + - name: Assert outputs (bash) + if: runner.os != 'Windows' + shell: bash + run: | + set -euo pipefail + : "${{ steps.disc.outputs.OS }}" + : "${{ steps.disc.outputs.ARCH }}" + : "${{ steps.disc.outputs.REF }}" + : "${{ steps.disc.outputs.SHORT_SHA }}" + echo "OS=${{ steps.disc.outputs.OS }} ARCH=${{ steps.disc.outputs.ARCH }} REF=${{ steps.disc.outputs.REF }} SHORT_SHA=${{ steps.disc.outputs.SHORT_SHA }}" + - name: Assert outputs (pwsh) + if: runner.os == 'Windows' + shell: powershell + run: | + if (-not "${{ steps.disc.outputs.OS }}") { throw 'OS output empty' } + if (-not "${{ steps.disc.outputs.ARCH }}") { throw 'ARCH output empty' } + if (-not "${{ steps.disc.outputs.REF }}") { throw 'REF output empty' } + if (-not "${{ steps.disc.outputs.SHORT_SHA }}") { throw 'SHORT_SHA output empty' } + + discovery-fixture-tests: + name: Discovery fixture tests (project markers and stack suggestion) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - { dir: 'tdd/wails2-root', expect: 'wails2', expect_root_pkg: '0', expect_frontend_pkg: '1', expect_go_mod: '1', expect_main_go: '1', expect_cmake: '0' } + - { dir: 'tdd/cpp-root', expect: 'cpp', expect_root_pkg: '0', expect_frontend_pkg: '0', expect_go_mod: '0', expect_main_go: '0', expect_cmake: '1' } + - { dir: 'tdd/node-only', expect: 'unknown', expect_root_pkg: '1', expect_frontend_pkg: '0', expect_go_mod: '0', expect_main_go: '0', expect_cmake: '0' } + - { dir: 'tdd/docs', expect: 'unknown', expect_root_pkg: '0', expect_frontend_pkg: '0', expect_go_mod: '0', expect_main_go: '0', expect_cmake: '0' } + steps: + - uses: actions/checkout@v4 + - id: disc + uses: ./actions/discovery + with: + working-directory: ${{ matrix.dir }} + - name: Assert markers and suggestion + shell: bash + run: | + set -euo pipefail + echo "[DEBUG_LOG] Tested dir=${{ matrix.dir }}" + test "${{ steps.disc.outputs.PRIMARY_STACK_SUGGESTION }}" = "${{ matrix.expect }}" + test "${{ steps.disc.outputs.HAS_ROOT_PACKAGE_JSON }}" = "${{ matrix.expect_root_pkg }}" + test "${{ steps.disc.outputs.HAS_FRONTEND_PACKAGE_JSON }}" = "${{ matrix.expect_frontend_pkg }}" + test "${{ steps.disc.outputs.HAS_ROOT_GO_MOD }}" = "${{ matrix.expect_go_mod }}" + test "${{ steps.disc.outputs.HAS_ROOT_MAIN_GO }}" = "${{ matrix.expect_main_go }}" + test "${{ steps.disc.outputs.HAS_ROOT_CMAKELISTS }}" = "${{ matrix.expect_cmake }}" + + + options-tests: + name: Options sub-action matrix (Ubuntu) + needs: [discovery-tests,discovery-fixture-tests] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - { distro: '22.04', obf: 'false', nsis: 'false', tags: 'false', expect_webkit: 'false' } + - { distro: '24.04', obf: 'false', nsis: 'false', tags: 'false', expect_webkit: 'true' } + - { distro: '24.04', obf: 'true', nsis: 'true', tags: 'release', expect_webkit: 'true' } + - { distro: '24.04', obf: 'false', nsis: 'false', tags: 'release,custom,custom', expect_webkit: 'true', expect_dedupe: 'custom' } + - { distro: '24.04', obf: 'false', nsis: 'false', tags: 'release custom', expect_webkit: 'true', expect_dedupe: '' } + - { distro: '24.04', obf: 'false', nsis: 'false', tags: 'false', expect_webkit: 'false', disable_webkit: 'true' } + steps: + - uses: actions/checkout@v4 + - id: opts + uses: ./actions/options + with: + build-obfuscate: ${{ matrix.obf }} + build-tags: ${{ matrix.tags }} + nsis: ${{ matrix.nsis }} + distro: ${{ matrix.distro }} + disable-webkit-auto-tag: ${{ matrix.disable_webkit || 'false' }} + - name: Assert BUILD_OPTIONS + shell: bash + run: | + set -euo pipefail + BO='${{ steps.opts.outputs.BUILD_OPTIONS }}' + echo "BUILD_OPTIONS=$BO" + if [ "${{ matrix.obf }}" = "true" ] && ! echo "$BO" | grep -q -- "-obfuscated"; then echo "missing -obfuscated"; exit 1; fi + if [ "${{ matrix.nsis }}" = "true" ] && ! echo "$BO" | grep -q -- "-nsis"; then echo "missing -nsis"; exit 1; fi + if [ "${{ matrix.expect_webkit }}" = "true" ] && ! echo "$BO" | grep -q -- "webkit2_41"; then echo "missing webkit2_41"; exit 1; fi + if [ "${{ matrix.disable_webkit || 'false' }}" = "true" ] && echo "$BO" | grep -q -- "webkit2_41"; then echo "webkit2_41 should be disabled"; exit 1; fi + if [ -n "${{ matrix.expect_dedupe || '' }}" ]; then + count=$(echo "$BO" | grep -o -- "${{ matrix.expect_dedupe }}" | wc -l | tr -d ' ') + if [ "$count" -ne 1 ]; then echo "expected tag '${{ matrix.expect_dedupe }}' to appear once, got $count"; exit 1; fi + fi + + + + + + setup-go-tests: + needs: [options-tests, wails-env-mapping, wails-env-mapping-wrapper] + name: Setup Go/Wails sub-action on ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Setup Go/Wails + uses: ./actions/setup/go + with: + go-version: '1.23' + build-cache: 'true' + build-obfuscate: 'false' + wails-version: 'latest' + wails-dev-build: 'false' + - name: Assert go and wails available + shell: bash + run: | + set -euo pipefail + go version + if command -v wails >/dev/null 2>&1; then wails version || true; else echo "wails not on PATH (may be Windows PATH nuance), continuing"; fi + + + setup-npm-tests: + name: Setup npm sub-action on ${{ matrix.os }} + needs: [options-tests, wails-env-mapping, wails-env-mapping-wrapper] + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Setup Node/npm (no install) + uses: ./actions/setup/npm + with: + node-version: '18.x' + working-directory: '.' + install: 'false' + - name: Assert node/npm + shell: bash + run: | + node -v + npm -v + + setup-conan-tests: + needs: [options-tests, wails-env-mapping, wails-env-mapping-wrapper] + name: Setup Conan sub-action (Linux only) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Conan + uses: ./actions/setup/conan + - name: Assert conan version present + shell: bash + run: | + if command -v conan >/dev/null 2>&1; then conan --version; else echo "Conan not found in PATH (ok for placeholder)"; fi + + + # setup-deno-tests: +# name: Setup Deno sub-action behavior (skip vs enable) +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# - name: Skip path (no env) +# uses: ./actions/setup/deno +# - name: Enable via env and run a command +# env: +# DENO_ENABLE: 'true' +# DENO_VERSION: 'v1.44.x' +# DENO_WORKDIR: '.' +# DENO_BUILD: 'deno --version' +# uses: ./actions/setup/deno + + package-tests: + needs: [setup-conan-tests,setup-go-tests,setup-npm-tests] + name: Package sub-action with dummy artifact (Ubuntu) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Prepare dummy artifact + shell: bash + run: | + mkdir -p tmp/bin + echo "hello" > tmp/bin/dummy.txt + - name: Package (no release on branches) + uses: ./actions/package + with: + package: 'true' + build-name: 'ci-test' + os: 'Linux' + arch: 'amd64' + short-sha: '${{ github.sha }}' + - name: Check log + run: echo "Ensure [DEBUG_LOG] ARTIFACT_NAME is visible above" + + package-smoke-ubuntu: + name: Packaging smoke (Ubuntu, package:true, no release on non-tags) + runs-on: ubuntu-latest + needs: package-tests + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Prepare dummy artifact + shell: bash + run: | + mkdir -p tmp/bin + echo "dummy" > tmp/bin/dummy.txt + - name: Run root action with packaging + uses: ./ + with: + build-name: wails-smoke-${{ github.run_id }} + build-platform: linux/amd64 + app-working-directory: tdd/wails2-root + package: true + sign: false + nsis: false + - name: Note + run: | + echo "[DEBUG_LOG] Packaging smoke complete. Check previous step for ARTIFACT_NAME echo." + + signing-diagnostics: + name: Signing diagnostics (dry-run) + needs: package-tests + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: macOS gon presence + if: runner.os == 'macOS' + shell: bash + run: | + if command -v gon >/dev/null 2>&1; then + echo "[DEBUG_LOG] gon present: $(gon --version)" + else + echo "[DEBUG_LOG] gon not found. It is installed during the Go setup step in real builds (macOS only)." + fi + - name: Windows signtool discovery + if: runner.os == 'Windows' + shell: powershell + run: | + $paths = @( + 'C:/Program Files (x86)/Windows Kits/10/bin', + 'C:/Program Files (x86)/Windows Kits/11/bin' + ) + $found = $false + foreach ($base in $paths) { + if (Test-Path $base) { + $sig = Get-ChildItem -Path $base -Recurse -Filter signtool.exe -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($sig) { Write-Host "[DEBUG_LOG] signtool found at $($sig.FullName)"; $found = $true; break } + } + } + if (-not $found) { + Write-Host "[DEBUG_LOG] signtool.exe not found in common SDK paths. It is typically available with Windows 10/11 SDK." + } + + subactions-smoke: + needs: package-tests + name: Sub-actions smoke (workflow-local ./actions/*) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Discovery (workflow-local path) + id: disc + uses: ./actions/discovery + - name: Compute options (with distro) + id: opts + uses: ./actions/options + with: + build-obfuscate: 'true' + build-tags: 'release' + nsis: 'false' + distro: ${{ steps.disc.outputs.DISTRO }} + - name: Show computed options + run: echo "BUILD_OPTIONS='${{ steps.opts.outputs.BUILD_OPTIONS }}'" + + + auto-stack-smoke: + needs: package-tests + name: Auto stack routing smoke (root action on Wails2-like repo) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run root action with AUTO_STACK in tdd/wails2-root + id: root + uses: ./ + with: + build-name: wails + build-platform: linux/amd64 + app-working-directory: tdd/wails2-root + build: false + package: false + sign: false + nsis: false + - name: Assert orchestrator selected wails2 + shell: bash + run: | + set -euo pipefail + sel='${{ steps.root.outputs.SELECTED_STACK }}' + echo "[DEBUG_LOG] SELECTED_STACK=$sel" + test "$sel" = "wails2" || { echo "Expected SELECTED_STACK=wails2, got '$sel'"; exit 1; } + + matrix-root-action: + name: Root action (./) on ${{ matrix.os }} for ${{ matrix.platform }} + runs-on: ${{ matrix.os }} + needs: [ package-tests] + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + platform: linux/amd64 + - os: windows-latest + platform: windows/amd64 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Prepare dummy artifact + shell: bash + run: | + mkdir -p tmp/bin + echo "dummy" > tmp/bin/dummy.txt + - name: Run root action locally + uses: ./ + with: + build-name: wails-root-action-${{ matrix.os }} + build-platform: ${{ matrix.platform }} + app-working-directory: tdd/wails2-root + build: false + package: true + sign: false + + wrapper-wails2: + name: Wails2 wrapper (./actions/build/wails2) on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + needs: [package-tests] + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + platform: linux/amd64 + - os: windows-latest + platform: windows/amd64 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Run wails2 wrapper locally + uses: ./actions/build/wails2 + with: + build-name: wails-wrapper-${{ matrix.os }} + build-platform: ${{ matrix.platform }} + app-working-directory: tdd/wails2-root + package: true + sign: false + nsis: false + + +# deno-env-path-test: +# name: Deno env-first path (root action on Ubuntu) +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# - name: Configure Deno via $GITHUB_ENV +# run: | +# echo "DENO_ENABLE=true" >> "$GITHUB_ENV" +# echo "DENO_VERSION=v1.44.x" >> "$GITHUB_ENV" +# echo "DENO_WORKDIR=frontend" >> "$GITHUB_ENV" +# echo "DENO_BUILD=deno --version" >> "$GITHUB_ENV" +# - name: Run root action (should set up Deno and run command) +# uses: ./ +# with: +# build-name: wails +# build-platform: linux/amd64 +# build: false +# package: false + + wails-env-mapping: + name: WAILS_* env mapping (root action) + needs: [discovery-tests,discovery-fixture-tests] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Configure WAILS_* via $GITHUB_ENV + run: | + echo "WAILS_OBFUSCATE=true" >> "$GITHUB_ENV" + echo "WAILS_NSIS=false" >> "$GITHUB_ENV" + echo "WAILS_BUILD_TAGS=release custom" >> "$GITHUB_ENV" + echo "WAILS_VERSION=latest" >> "$GITHUB_ENV" + echo "WAILS_GO_VERSION=1.23" >> "$GITHUB_ENV" + echo "WAILS_NODE_VERSION=18.x" >> "$GITHUB_ENV" + echo "WAILS_WEBVIEW2=download" >> "$GITHUB_ENV" + - name: Run root action (uses ENV mapping) + uses: ./ + with: + build-name: wails + build-platform: linux/amd64 + app-working-directory: tdd/wails2-root + build: false + package: false + sign: false + + wails-env-mapping-wrapper: + name: WAILS_* env mapping (wrapper outputs) + needs: [discovery-tests,discovery-fixture-tests] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Configure WAILS_* via $GITHUB_ENV (wrapper) + run: | + echo "WAILS_OBFUSCATE=true" >> "$GITHUB_ENV" + echo "WAILS_NSIS=false" >> "$GITHUB_ENV" + echo "WAILS_BUILD_TAGS=release custom" >> "$GITHUB_ENV" + echo "WAILS_VERSION=latest" >> "$GITHUB_ENV" + echo "WAILS_GO_VERSION=1.23" >> "$GITHUB_ENV" + echo "WAILS_NODE_VERSION=18.x" >> "$GITHUB_ENV" + echo "WAILS_WEBVIEW2=download" >> "$GITHUB_ENV" + - name: Run wails2 wrapper (capture outputs) + id: wrap + uses: ./actions/build/wails2 + with: + build-name: wails-wrapper-${{ github.run_id }} + build-platform: linux/amd64 + app-working-directory: tdd/wails2-root + build: false + package: false + sign: false + nsis: false + - name: Assert wrapper resolved envs + shell: bash + run: | + set -euo pipefail + tags='${{ steps.wrap.outputs.BUILD_TAGS }}' + obf='${{ steps.wrap.outputs.OBFUSCATE }}' + nsis='${{ steps.wrap.outputs.NSIS }}' + echo "[DEBUG_LOG] WRAP_BUILD_TAGS=$tags OBFUSCATE=$obf NSIS=$nsis" + grep -q "release" <<< "$tags" + grep -q "custom" <<< "$tags" + test "$obf" = "true" + test "$nsis" = "false" + + readme-snippets: + name: README snippets validation (non-signing, non-release) + needs: [package-tests] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Discovery example + id: disc + uses: ./actions/discovery + with: + working-directory: tdd/wails2-root + - name: Options example + id: opts + uses: ./actions/options + with: + build-obfuscate: 'true' + build-tags: 'release' + nsis: 'false' + distro: ${{ steps.disc.outputs.DISTRO }} + - name: Package example + uses: ./actions/package + with: + package: 'true' + build-name: 'ci-snippet' + os: 'Linux' + arch: 'amd64' + short-sha: '${{ github.sha }}' + include-meta: 'true' + - name: Note + run: echo "[DEBUG_LOG] README snippets validated" diff --git a/.github/workflows/wails-build.yml b/.github/workflows/wails-build.yml new file mode 100644 index 0000000..e6f2bad --- /dev/null +++ b/.github/workflows/wails-build.yml @@ -0,0 +1,120 @@ +name: Reusable Wails Build + +on: + workflow_call: + inputs: + build: + type: string + default: 'true' + sign: + type: string + default: 'false' + package: + type: string + default: 'true' + nsis: + type: string + default: 'false' + build-name: + type: string + required: true + build-cache: + type: string + default: 'true' + build-platform: + type: string + default: 'darwin/universal' + build-tags: + type: string + default: 'false' + build-obfuscate: + type: string + default: 'false' + wails-version: + type: string + default: 'latest' + wails-build-webview2: + type: string + default: 'download' + go-version: + type: string + default: '1.23' + deno-build: + type: string + default: '' + app-working-directory: + type: string + default: '.' + deno-working-directory: + type: string + default: '.' + deno-version: + type: string + default: 'v1.20.x' + sign-macos-app-id: + type: string + default: '' + sign-macos-apple-password: + type: string + default: '' + sign-macos-app-cert: + type: string + default: '' + sign-macos-app-cert-password: + type: string + default: '' + sign-macos-installer-id: + type: string + default: '' + sign-macos-installer-cert: + type: string + default: '' + sign-macos-installer-cert-password: + type: string + default: '' + sign-windows-cert: + type: string + default: '' + sign-windows-cert-password: + type: string + default: '' + wails-dev-build: + type: string + default: 'false' + +jobs: + build: + runs-on: ${{ inputs.build-platform == 'windows/amd64' && 'windows-latest' || inputs.build-platform == 'linux/amd64' && 'ubuntu-latest' || 'macos-latest' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Wails build action (wrapper) + uses: ./actions/build/wails2 + with: + build: ${{ inputs.build }} + sign: ${{ inputs.sign }} + package: ${{ inputs.package }} + nsis: ${{ inputs.nsis }} + build-name: ${{ inputs.build-name }} + build-cache: ${{ inputs.build-cache }} + build-platform: ${{ inputs.build-platform }} + build-tags: ${{ inputs.build-tags }} + build-obfuscate: ${{ inputs.build-obfuscate }} + wails-version: ${{ inputs.wails-version }} + wails-build-webview2: ${{ inputs.wails-build-webview2 }} + go-version: ${{ inputs.go-version }} + deno-build: ${{ inputs.deno-build }} + app-working-directory: ${{ inputs.app-working-directory }} + deno-working-directory: ${{ inputs.deno-working-directory }} + deno-version: ${{ inputs.deno-version }} + sign-macos-app-id: ${{ inputs.sign-macos-app-id }} + sign-macos-apple-password: ${{ inputs.sign-macos-apple-password }} + sign-macos-app-cert: ${{ inputs.sign-macos-app-cert }} + sign-macos-app-cert-password: ${{ inputs.sign-macos-app-cert-password }} + sign-macos-installer-id: ${{ inputs.sign-macos-installer-id }} + sign-macos-installer-cert: ${{ inputs.sign-macos-installer-cert }} + sign-macos-installer-cert-password: ${{ inputs.sign-macos-installer-cert-password }} + sign-windows-cert: ${{ inputs.sign-windows-cert }} + sign-windows-cert-password: ${{ inputs.sign-windows-cert-password }} + wails-dev-build: ${{ inputs.wails-dev-build }} diff --git a/.github/workflows/wails2.yml b/.github/workflows/wails2.yml new file mode 100644 index 0000000..5c04ada --- /dev/null +++ b/.github/workflows/wails2.yml @@ -0,0 +1,120 @@ +name: Reusable Wails v2 Build + +on: + workflow_call: + inputs: + build: + type: string + default: 'true' + sign: + type: string + default: 'false' + package: + type: string + default: 'true' + nsis: + type: string + default: 'false' + build-name: + type: string + required: true + build-cache: + type: string + default: 'true' + build-platform: + type: string + default: 'darwin/universal' + build-tags: + type: string + default: 'false' + build-obfuscate: + type: string + default: 'false' + wails-version: + type: string + default: 'latest' + wails-build-webview2: + type: string + default: 'download' + go-version: + type: string + default: '1.23' + deno-build: + type: string + default: '' + app-working-directory: + type: string + default: '.' + deno-working-directory: + type: string + default: '.' + deno-version: + type: string + default: 'v1.20.x' + sign-macos-app-id: + type: string + default: '' + sign-macos-apple-password: + type: string + default: '' + sign-macos-app-cert: + type: string + default: '' + sign-macos-app-cert-password: + type: string + default: '' + sign-macos-installer-id: + type: string + default: '' + sign-macos-installer-cert: + type: string + default: '' + sign-macos-installer-cert-password: + type: string + default: '' + sign-windows-cert: + type: string + default: '' + sign-windows-cert-password: + type: string + default: '' + wails-dev-build: + type: string + default: 'false' + +jobs: + build: + runs-on: ${{ inputs.build-platform == 'windows/amd64' && 'windows-latest' || inputs.build-platform == 'linux/amd64' && 'ubuntu-latest' || 'macos-latest' }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Wails v2 build (wrapper) + uses: ./actions/build/wails2 + with: + build: ${{ inputs.build }} + sign: ${{ inputs.sign }} + package: ${{ inputs.package }} + nsis: ${{ inputs.nsis }} + build-name: ${{ inputs.build-name }} + build-cache: ${{ inputs.build-cache }} + build-platform: ${{ inputs.build-platform }} + build-tags: ${{ inputs.build-tags }} + build-obfuscate: ${{ inputs.build-obfuscate }} + wails-version: ${{ inputs.wails-version }} + wails-build-webview2: ${{ inputs.wails-build-webview2 }} + go-version: ${{ inputs.go-version }} + deno-build: ${{ inputs.deno-build }} + app-working-directory: tdd/wails2-root + deno-working-directory: ${{ inputs.deno-working-directory }} + deno-version: ${{ inputs.deno-version }} + sign-macos-app-id: ${{ inputs.sign-macos-app-id }} + sign-macos-apple-password: ${{ inputs.sign-macos-apple-password }} + sign-macos-app-cert: ${{ inputs.sign-macos-app-cert }} + sign-macos-app-cert-password: ${{ inputs.sign-macos-app-cert-password }} + sign-macos-installer-id: ${{ inputs.sign-macos-installer-id }} + sign-macos-installer-cert: ${{ inputs.sign-macos-installer-cert }} + sign-macos-installer-cert-password: ${{ inputs.sign-macos-installer-cert-password }} + sign-windows-cert: ${{ inputs.sign-windows-cert }} + sign-windows-cert-password: ${{ inputs.sign-windows-cert-password }} + wails-dev-build: ${{ inputs.wails-dev-build }} diff --git a/.gitignore b/.gitignore index fb7a30c..832d661 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .idea -build/bin -node_modules -frontend/dist +build/wails2/build/bin +build/wails2/node_modules +build/wails2/frontend/dist diff --git a/README.md b/README.md index 560f632..f0dc183 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,25 @@ -20/02/2025 - Wails Version 2.10.0 is problematic, please use `wails-version: "v2.9.0"` & report the bug if you get issues, tyvm <3 +# snider/build@v3 -07/02/2025 - Please use `dAppServer/wails-build-action@main` AND star the repo to get updated on V3, the readme refers to a future version +[![CI](https://github.com/snider/wails-build-action/actions/workflows/ci.yml/badge.svg)](https://github.com/snider/wails-build-action/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-EUPL-green.svg)](LICENSE) -# dAppServer/wails-build-action@v2 -GitHub action to build Wails.io: the action will install GoLang and NodeJS and run a build. -This will be used on a [Wails.io](https://wails.io) v2 project. +> [!NOTE] +> For comprehensive documentation, please visit the [docs](docs/) directory. -By default, the action will build and upload the results to Git Hub; on a tagged build, it will also upload to the release. + +> I help on lots of open source projects, im tired of doing the same thing over and over again.\ +> so, I'm going to put them all together in one place.\ +> Hopefully it will help you too. + +General build action (multi-stack). + +By default, the root action will best guess the builds you might want to run and delegate to the appropriate sub-action. You can also explicitly select a stack and enable/disable setup steps. + +you should write out an action that cherry-picks the parts you need; the auto-detected method works for me, based on the file structures in the tdd/* folders # Default build ```yaml -- uses: dAppServer/wails-build-action@v3 +- uses: snider/build@v3 with: build-name: wailsApp build-platform: linux/amd64 @@ -19,142 +28,168 @@ By default, the action will build and upload the results to Git Hub; on a tagged ## Build with No uploading ```yaml -- uses: dAppServer/wails-build-action@v3 +- uses: snider/build@v3 with: build-name: wailsApp build-platform: linux/amd64 package: false ``` -## GitHub Action Options - -| Name | Default | Description | -|--------------------------------------|----------------------|----------------------------------------------------| -| `build-name` | none, required input | The name of the binary | -| `build-obfuscate` | `false` | Obfuscate the binary | -| `build` | `true` | Runs `wails build` on your source | -| `nsis` | `true` | Runs `wails build` with or without -nsis | -| `sign` | `false` | After build, signs and creates signed installers | -| `package` | `true` | Upload workflow artifacts & publish release on tag | -| `build-platform` | `darwin/universal` | Platform to build for | -| `build-tags` | '' | Build tags to pass to Go compiler. Must be quoted. | -| `wails-version` | `latest` | Wails version to use | -| `wails-build-webview2` | `download` | Webview2 installing [download,embed,browser,error] | -| `go-version` | `1.18` | Version of Go to use | -| `node-version` | `16.x` | Node js version | -| `deno-build` | '' | Deno compile command | -| `deno-working-directory` | `.` | Working directory of your [Deno](https://deno.land/) server| -| `deno-version` | `v1.20.x` | Deno version to use | -| `sign-macos-app-id` | '' | ID of the app signing cert | -| `sign-macos-apple-password` | '' | MacOS Apple password | -| `sign-macos-app-cert` | '' | MacOS Application Certificate | -| `sign-macos-app-cert-password` | '' | MacOS Application Certificate Password | -| `sign-macos-installer-id` | '' | MacOS Installer Certificate id | -| `sign-macos-installer-cert` | '' | MacOS Installer Certificate | -| `sign-macos-installer-cert-password` | '' | MacOS Installer Certificate Password | -| `sign-windows-cert` | '' | Windows Signing Certificate | -| `sign-windows-cert-passowrd` | '' | Windows Signing Certificate Password | - - - -## Example Build +## Inputs (high level) -```yaml -name: Wails build +This repository is multi-stack. The root action currently runs the Wails v2 pipeline by default. For full Wails-specific inputs and examples, see `actions/build/wails2/README.md`. + +Common high-level inputs on the root action include: +- `build-name` — required; base name for outputs +- `build-platform` — target platform (e.g., `linux/amd64`, `windows/amd64`, `darwin/universal`) +- `build` — whether to build (default `true`) +- `package` — upload artifacts and (on tags) publish a release (default `true`) +- `sign` — enable platform signing when configured (default `false`) + +Stack-specific inputs (Wails flags, signing certs, etc.) are documented in the Wails v2 wrapper: `actions/wails2/README.md`. + + + +## Examples and stack-specific docs + +For Wails v2 end-to-end usage, examples, and advanced options, see: +- Wails v2 wrapper: `actions/build/wails2/README.md` +- Wails build sub-action: `actions/build/wails2/build/README.md` + +The root README focuses on multi-stack concepts. Stack-specific workflows are documented alongside each stack. -on: [push, pull_request] +## macOS code signing docs moved +The detailed macOS code signing and notarization guide (including `gon` JSON examples and `entitlements.plist`) now lives with the Wails v2 stack docs: +- See `actions/build/wails2/README.md` → “macOS Code Signing (Wails v2)” + + +## Configure Deno via environment variables (optional) + +Deno is not required. If you want to run a Deno build/asset step before Wails, you can configure it entirely via env vars — no `deno-*` inputs are needed. + +Precedence used by the action (inside `actions/setup`): +- Environment variables > action inputs > defaults. +- If nothing is provided, Deno is skipped. + +Supported variables: +- `DENO_ENABLE` — `true`/`1`/`yes`/`on` explicitly enables Deno even without a build command. +- `DENO_BUILD` — full command to run (e.g., `deno task build`, `deno run -A build.ts`). +- `DENO_VERSION` — e.g., `v1.44.x`. +- `DENO_WORKDIR` — working directory for the Deno command (default `.`). +- Pass-throughs (used by Deno if present): `DENO_AUTH_TOKEN`, `DENO_DIR`, `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, etc. + +Example (job-level env): +```yaml jobs: build: - strategy: - fail-fast: false - matrix: - build: [ - {name: wailsTest, platform: linux/amd64, os: ubuntu-latest}, - {name: wailsTest, platform: windows/amd64, os: windows-latest}, - {name: wailsTest, platform: darwin/universal, os: macos-latest} - ] - runs-on: ${{ matrix.build.os }} + runs-on: ubuntu-latest + env: + DENO_ENABLE: 'true' + DENO_VERSION: 'v1.44.x' + DENO_WORKDIR: 'frontend' + DENO_BUILD: 'deno task build' steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - uses: dAppServer/wails-build-action@v3 + - uses: actions/checkout@v4 + - uses: snider/build@v3 with: - build-name: ${{ matrix.build.name }} - build-platform: ${{ matrix.build.platform }} - build-obfuscate: true + build-name: wailsApp + build-platform: linux/amd64 ``` -## MacOS Code Signing - -You need to make two gon configuration files, this is because we need to sign and notarize the .app before making an installer with it. - +Using `$GITHUB_ENV` in a prior step: ```yaml - - uses: dAppServer/wails-build-action@v3 - with: - build-name: wailsApp - sign: true - build-platform: darwin/universal - sign-macos-apple-password: ${{ secrets.APPLE_PASSWORD }} - sign-macos-app-id: ${{ secrets.MACOS_DEVELOPER_CERT_ID }} - sign-macos-app-cert: ${{ secrets.MACOS_DEVELOPER_CERT }} - sign-macos-app-cert-password: ${{ secrets.MACOS_DEVELOPER_CERT_PASSWORD }} - sign-macos-installer-id: ${{ secrets.MACOS_INSTALLER_CERT_ID }} - sign-macos-installer-cert: ${{ secrets.MACOS_INSTALLER_CERT }} - sign-macos-installer-cert-password: ${{ secrets.MACOS_INSTALLER_CERT_PASSWORD }} +- name: Configure Deno via $GITHUB_ENV + run: | + echo "DENO_ENABLE=true" >> "$GITHUB_ENV" + echo "DENO_VERSION=v1.44.x" >> "$GITHUB_ENV" + echo "DENO_WORKDIR=frontend" >> "$GITHUB_ENV" + echo "DENO_BUILD=deno task build" >> "$GITHUB_ENV" +- uses: snider/build@v3 + with: + build-name: wailsApp + build-platform: linux/amd64 ``` -`build/darwin/gon-sign.json` -```json -{ - "source" : ["./build/bin/wailsApp.app"], - "bundle_id" : "com.wails.app", - "apple_id": { - "username": "username", - "password": "@env:APPLE_PASSWORD" - }, - "sign" :{ - "application_identity" : "Developer ID Application: XXXXXXXX (XXXXXX)", - "entitlements_file": "./build/darwin/entitlements.plist" - }, - "dmg" :{ - "output_path": "./build/bin/wailsApp.dmg", - "volume_name": "Lethean" - } -} -``` -`build/darwin/gon-notarize.json` -```json -{ - "notarize": [{ - "path": "./build/bin/wailsApp.pkg", - "bundle_id": "com.wails.app", - "staple": true - },{ - "path": "./build/bin/wailsApp.app.zip", - "bundle_id": "com.wails.app", - "staple": false - }], - "apple_id": { - "username": "USER name", - "password": "@env:APPLE_PASSWORD" - } -} +Secrets example (private modules): +```yaml +env: + DENO_AUTH_TOKEN: ${{ secrets.DENO_AUTH_TOKEN }} ``` -`build/darwin/entitlements.plist` -```xml - - - - - com.apple.security.app-sandbox - - com.apple.security.network.client - - com.apple.security.network.server - - com.apple.security.files.user-selected.read-write - - - + + +## Sub-actions overview + +This repo is modular. You can call the root action, the Wails v2 wrapper, or any sub-action directly. + +- actions/discovery — detects OS/ARCH, Ubuntu version on Linux, and exposes repo/ref metadata. +- actions/options — computes `BUILD_OPTIONS` (adds `-tags webkit2_41` on Ubuntu 24.04 when appropriate). +- actions/setup — orchestrator that delegates to: + - actions/setup/go — Go, optional Garble, Wails CLI, and `gon` on macOS. + - actions/setup/npm — Node.js and npm install/ci in your app working directory. + - actions/setup/deno — optional; ENV-first Deno setup and command runner. + - actions/setup/conan — placeholder for future C++ builds. +- actions/build/wails2/build — runs `wails build` and fixes executable permissions per-OS. +- actions/sign — unified macOS and Windows signing; notarizes on tags. +- actions/package — uploads artifacts; on tags, publishes a GitHub Release. + +## Stacks + +- Available: + - wails2 — `uses: snider/build/actions/build/wails2@v3` (or just call the root action) +- Coming soon: + - wails3 — once upstream stabilizes + - cpp — via `setup/conan` and dedicated build/sign/pack steps + +## Setup orchestrator notes + +The `actions/setup` sub-action is a thin orchestrator that runs Go → npm → Deno (optional) → Conan (optional). It keeps Deno independent from Wails. Configure Deno via environment variables (ENV-first), or via inputs as a fallback. See the Deno section below and `actions/setup/deno/README.md` for details. + +## Orchestrator controls (root action) + +The root action can auto-detect your stack and auto-enable setup steps. This makes `snider/build@v3` “just work” for common layouts, while still allowing full control. + +- Inputs (root action): + - `AUTO_STACK` (default `true`) — auto-select a stack based on `actions/discovery` outputs. + - `AUTO_SETUP` (default `true`) — allow sub-setup enabling based on env toggles. + - `STACK` (optional) — force a stack (e.g., `wails2`). When set, it takes precedence over auto. +- Environment toggles (read when `AUTO_SETUP == true`): + - `ENABLE_GO`, `ENABLE_NPM`, `ENABLE_DENO`, `ENABLE_CONAN` — `true`/`1`/`yes`/`on` to explicitly enable those setups; otherwise defaults are used. +- Precedence and routing: + - If `STACK` is set, the root action routes to that stack wrapper directly. + - Else if `AUTO_STACK` is enabled, the root action uses `PRIMARY_STACK_SUGGESTION` from discovery and routes accordingly (currently `wails2`). + - You can fully opt out by setting `AUTO_STACK: 'false'` and `AUTO_SETUP: 'false'` and calling sub-actions directly in your workflow. +- Debug logs: + - Look for `[DEBUG_LOG] Auto stack=...` and `[DEBUG_LOG] npm-install resolved=...` in the logs to see decisions made. + +## Smarter artifact naming (package) + +Starting in v3, the `actions/package` sub-action composes a descriptive artifact name using discovery metadata: + +```text +___ ``` + +- On tag builds, the tag (e.g., `v1.2.3`) is used. +- On branch/PR builds, the short commit SHA is used. +- Example: `wailsApp_Ubuntu-22.04_amd64_ab12cd3` or `wailsApp_macos_arm64_v1.2.3`. + +When you call the root action or the `wails2` wrapper, discovery outputs are passed automatically to `actions/package`. + + +## CI validations and gating + +The repository includes self-tests to surface issues early and gate app builds behind fast sub-action checks: +- Sub-action tests (gating): `discovery`, `options`, `setup/*` (go, npm, deno, conan), `sign` diagnostics, and `package` run first. App build jobs depend on these via `needs:` and will not execute if any sub-test fails. +- Packaging smoke (Ubuntu): runs the root action locally with `package: true` on branch/PR builds and verifies artifact upload. No release is created on non-tag refs. Look for `[DEBUG_LOG] ARTIFACT_NAME=...` in logs. +- Matrix builds with packaging: root action and the `wails2` wrapper run on Ubuntu/macOS/Windows with `package: true` on branches/PRs to confirm cross-OS uploads. Signing remains disabled. +- Signing diagnostics (dry-run): + - macOS: prints `gon --version` if available or guidance if not; always green. + - Windows: searches common Windows SDK locations for `signtool.exe` and logs the result; always green. + +These checks run on `push`/`pull_request` to branches and are safe on forks (no secrets required). On tag refs, real releases are only created when your workflow explicitly runs and `refs/tags/*` is detected. + +### Extending CI for new stacks (wails3/cpp) +- Mirror the pattern: create stack-specific sub-action tests (e.g., `setup/wails3`, `setup/conan`, stack-specific build options) that are fast and deterministic. +- Add the new test jobs to the app build job `needs:` so stack builds only run after sub-tests pass. +- Prefer dummy artifacts with the `actions/package` sub-action for packaging checks; keep releases tag-gated. +- Keep tests secrets-free; add tool presence diagnostics (similar to `gon`/`signtool`) for platform-specific tools. diff --git a/action.yml b/action.yml index 1060d9a..a819a70 100644 --- a/action.yml +++ b/action.yml @@ -1,289 +1,86 @@ -name: "Wails Build Action" -description: "Creates a wails binary" +name: "Build Action (orchestrated)" +description: "General build action repo; root is minimal and delegates to directory orchestrator based on discovery/ENV" branding: icon: 'box' color: 'purple' inputs: build: - description: "Platform to build for" + description: "Whether to run the build" required: false default: "true" sign: - description: "Sign the build" + description: "Sign the build (delegated to stack’s signing flow)" required: false default: "false" package: - description: "Uploads workflow & uploads tag builds to a release" + description: "Upload artifacts and publish release on tags" required: false default: "true" - nsis: - description: "Build a Windows Installer" - required: false - default: "false" build-name: - description: "The name of the binary file" + description: "The name of the binary/app bundle" required: true - build-cache: - description: "Cache the build" - required: false - default: "true" build-platform: - description: "Platform to build for" + description: "Platform to build for (e.g., linux/amd64, windows/amd64, darwin/universal)" required: false default: "darwin/universal" - build-tags: - description: "Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated" - required: false - default: "false" - build-obfuscate: - description: "Obfuscate the build" - required: false - default: "false" - wails-version: - description: "Wails version to use" - required: false - default: "latest" - wails-build-webview2: - description: "Webview2 installer method [download,embed,browser,error]" - required: false - default: "download" - go-version: - description: "Version of Go to use" - required: false - default: "1.23" - node-version: - description: "Node js version" - required: false - default: "18.x" - deno-build: - description: "This gets run into bash, use the full command" - required: false - default: "" app-working-directory: - description: "This gets run into bash, use the full command" - required: false - default: "." - deno-working-directory: - description: "This gets run into bash, use the full command" + description: "Root of the app being built" required: false default: "." - deno-version: - description: "Deno version to use" - required: false - default: "v1.20.x" - sign-macos-app-id: - description: "MacOS Application Certificate id" - required: false - default: '' - sign-macos-apple-password: - description: "MacOS Apple password" - required: false - default: '' - sign-macos-app-cert: - description: "MacOS Application Certificate" - required: false - default: '' - sign-macos-app-cert-password: - description: "MacOS Application Certificate Password" - required: false - default: '' - sign-macos-installer-id: - description: "MacOS Installer Certificate id" - required: false - default: '' - sign-macos-installer-cert: - description: "MacOS Installer Certificate" - required: false - default: '' - sign-macos-installer-cert-password: - description: "MacOS Installer Certificate Password" - required: false - default: '' - sign-windows-cert: - description: "Windows Signing Certificate" + # Orchestrator controls (stack-agnostic) + AUTO_STACK: + description: "Allow root action to auto-select a stack based on discovery" required: false - default: '' - sign-windows-cert-password: - description: "Windows Signing Certificate Password" + default: "true" + AUTO_SETUP: + description: "Allow orchestrators to auto-enable setup tools based on env toggles" required: false - default: '' - wails-dev-build: - description: "Use provided wails" + default: "true" + STACK: + description: "Explicit stack override (e.g., wails2)" required: false - default: "false" + default: "" runs: using: "composite" steps: - - name: Linux Discovery - if: runner.os == 'Linux' - id: linux_discovery - run: | - sudo apt-get -yq update - DISTRO=$(lsb_release -rs) # Get the distribution version (e.g., "22.04", "24.04") - if [[ "$DISTRO" == "20.04" ]]; then - sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.0-dev gcc-aarch64-linux-gnu - elif [[ "$DISTRO" == "22.04" ]]; then - sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.0-dev gcc-aarch64-linux-gnu - elif [[ "$DISTRO" == "24.04" ]]; then - sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.1-dev gcc-aarch64-linux-gnu - else - echo "Unsupported Linux distribution: $DISTRO" - exit 1 # Fail the workflow if the distribution is not supported - fi - echo "DISTRO=$DISTRO" >> "$GITHUB_OUTPUT" - shell: bash - - name: Setup Build Options - id: build_options - shell: bash - env: - DISTRO: ${{ steps.linux_discovery.outputs.DISTRO }} - run: | - build_options="" - if ${{ inputs.build-obfuscate == 'true' }}; then - build_options+=' -obfuscated' - fi - if [[ "${{ inputs.build-tags }}" != "false" ]]; then - tags_string="${{ inputs.build-tags }}" - if [[ "$DISTRO" == '24.04' ]]; then - tags_string+=" webkit2_41" - fi - build_options+=" -tags $tags_string" - elif [[ "${{ inputs.build-tags }}" == "false" && "$DISTRO" == '24.04' ]]; then - build_options+=" -tags webkit2_41" - fi - if ${{ inputs.nsis == 'true' }}; then - build_options+=' -nsis' - fi - echo "BUILD_OPTIONS=$build_options" >> "$GITHUB_OUTPUT" - # Setup and configure GoLang - - name: Setup GoLang - uses: actions/setup-go@v5 - if: inputs.wails-dev-build == 'false' + - name: Discovery + id: discovery + uses: ./actions/discovery with: - check-latest: true - cache: ${{ inputs.build-cache }} - cache-dependency-path: 'go.sum' - go-version: ${{ inputs.go-version }} - - name: Install Garble - if: inputs.build-obfuscate == 'true' - run: go install mvdan.cc/garble@latest - shell: bash - - run: go version - shell: bash - # (Optional) Setup and configure Deno - - name: Setup Deno - uses: denoland/setup-deno@v2 - if: inputs.deno-build != '' - with: - deno-version: ${{inputs.deno-version}} - - name: Run Deno Command - if: inputs.deno-build != '' - shell: bash - working-directory: ${{inputs.deno-working-directory}} - run: ${{inputs.deno-build}} - # install wails - - name: Install Wails - if: inputs.build == 'true' && inputs.wails-dev-build == 'false' - run: go install github.com/wailsapp/wails/v2/cmd/wails@${{inputs.wails-version}} - shell: bash - - name: Install macOS Wails deps - if: runner.os == 'macOS' - run: brew install mitchellh/gon/gon - shell: bash - # Building step - - name: Build App - if: inputs.build == 'true' - env: - BUILD_OPTIONS: ${{ steps.build_options.outputs.BUILD_OPTIONS }} - working-directory: ${{ inputs.app-working-directory }} - run: wails build --platform ${{inputs.build-platform}} -webview2 ${{inputs.wails-build-webview2}} -o ${{inputs.build-name}} $BUILD_OPTIONS - shell: bash - - name: Add macOS perms - if: inputs.build == 'true' && runner.os == 'macOS' - working-directory: ${{ inputs.app-working-directory }} - run: chmod +x build/bin/*/Contents/MacOS/* - shell: bash - - name: Add Linux perms - if: inputs.build == 'true' && runner.os == 'Linux' - working-directory: ${{ inputs.app-working-directory }} - run: chmod +x build/bin/* - shell: bash - # Package and Sign MacOS - - name: Import Code-Signing Certificates for macOS - if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') - uses: Apple-Actions/import-codesign-certs@v1 - with: - keychain-password: ${{ inputs.sign-macos-apple-password }} - p12-file-base64: ${{ inputs.sign-macos-app-cert }} - p12-password: ${{ inputs.sign-macos-app-cert-password }} - - name: Import Code-Signing Certificates for macOS Installer - if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') - uses: Apple-Actions/import-codesign-certs@v1 + working-directory: ${{ inputs.app-working-directory }} + + - name: Delegate to directory orchestrator + id: dir_orch + uses: ./actions with: - keychain-password: ${{ inputs.sign-macos-apple-password }} - p12-file-base64: ${{ inputs.sign-macos-installer-cert }} - p12-password: ${{ inputs.sign-macos-installer-cert-password }} - create-keychain: false - - name: Sign our macOS binary - if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') - shell: bash - working-directory: ${{ inputs.app-working-directory }} - env: - APPLE_PASSWORD: ${{ inputs.sign-macos-apple-password }} - run: | - echo "Signing Package" - gon -log-level=info ./build/darwin/gon-sign.json - - name: Build .app zip file - if: runner.os == 'macOS' - working-directory: ${{ inputs.app-working-directory }} - shell: bash - run: | - ditto -c -k --keepParent ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.app ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.app.zip - - name: Building Installer - if: runner.os == 'macOS' && inputs.sign != 'false' && inputs.sign-macos-installer-id != '' && startsWith(github.ref, 'refs/tags/') - shell: bash - working-directory: ${{ inputs.app-working-directory }} - run: | - productbuild --sign '${{inputs.sign-macos-installer-id}}' --component ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.app /Applications ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.pkg - - name: Building Installer - if: runner.os == 'macOS' && inputs.sign-macos-installer-id == '' && startsWith(github.ref, 'refs/tags/') - shell: bash - working-directory: ${{ inputs.app-working-directory }} - run: | - productbuild --component ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.app /Applications ${{ inputs.app-working-directory }}/build/bin/${{inputs.build-name}}.pkg - - name: Notarising Installer and zip - if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') + build: ${{ inputs.build }} + sign: ${{ inputs.sign }} + package: ${{ inputs.package }} + build-name: ${{ inputs.build-name }} + build-platform: ${{ inputs.build-platform }} + app-working-directory: ${{ inputs.app-working-directory }} + AUTO_STACK: ${{ inputs.AUTO_STACK }} + AUTO_SETUP: ${{ inputs.AUTO_SETUP }} + STACK: ${{ inputs.STACK }} + # Pass suggestion from discovery so orchestrator can skip re-scanning if it wants + PRIMARY_STACK_SUGGESTION: ${{ steps.discovery.outputs.PRIMARY_STACK_SUGGESTION }} + + - name: Debug selected stack shell: bash - working-directory: ${{ inputs.app-working-directory }} - env: - APPLE_PASSWORD: ${{ inputs.sign-macos-apple-password }} - run: | - gon -log-level=info ${{ inputs.app-working-directory }}/build/darwin/gon-notarize.json - # Windows signing - - name: Sign Windows binaries - shell: powershell - if: runner.os == 'Windows' && inputs.sign != 'false' && inputs.sign-windows-cert != '' - working-directory: ${{ inputs.app-working-directory }} - run: | - echo "Creating certificate file" - New-Item -ItemType directory -Path certificate - Set-Content -Path certificate\certificate.txt -Value '${{ inputs.sign-windows-cert }}' - certutil -decode certificate\certificate.txt certificate\certificate.pfx - echo "Signing our binaries" - & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ inputs.sign-windows-cert-password }}' .\build\bin\${{inputs.build-name}}.exe - echo "Signing Installer" & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ inputs.sign-windows-cert-password }}' .\build\bin\${{inputs.build-name}}-amd64-installer.exe + run: echo "[DEBUG_LOG] (root) Orchestrator selected stack=${{ steps.dir_orch.outputs.SELECTED_STACK }}" - # Upload build assets - - uses: actions/upload-artifact@v4 - if: inputs.package == 'true' - with: - name: Wails Build ${{runner.os}} ${{inputs.build-name}} - path: | - */bin/ - *\bin\* - - name: Release - uses: softprops/action-gh-release@v1 - if: inputs.package == 'true' && startsWith(github.ref, 'refs/tags/') + - name: Package & release + uses: ./actions/package with: - files: | - */bin/* + package: ${{ inputs.package }} + build-name: ${{ inputs.build-name }} + os: ${{ steps.discovery.outputs.OS }} + arch: ${{ steps.discovery.outputs.ARCH }} + tag: ${{ steps.discovery.outputs.TAG }} + is-tag: ${{ steps.discovery.outputs.IS_TAG }} + short-sha: ${{ steps.discovery.outputs.SHORT_SHA }} + ref: ${{ steps.discovery.outputs.REF }} +outputs: + SELECTED_STACK: + description: "Stack selected by the orchestrator (via directory orchestrator)" + value: ${{ steps.dir_orch.outputs.SELECTED_STACK }} diff --git a/actions/README.md b/actions/README.md new file mode 100644 index 0000000..82d41c1 --- /dev/null +++ b/actions/README.md @@ -0,0 +1,23 @@ +# actions/ index + +This directory contains modular composite actions that you can call directly from your workflows, or via the root orchestrator. + +Sub-actions overview +- discovery — Detect OS/ARCH, Ubuntu distro (on Linux), repo/ref metadata, and project markers. Suggests a primary stack. +- options — Compute `BUILD_OPTIONS` string for Wails v2 builds (adds `-tags webkit2_41` on Ubuntu 24.04 when appropriate). +- setup — Orchestrator for toolchains (Go → npm → optional Deno → optional Conan). + - setup/go — Installs Go, optional Garble (when obfuscating), Wails CLI, and `gon` on macOS. + - setup/npm — Installs Node.js and optionally runs `npm ci`/`npm install` in your app directory (auto-detects `frontend/`). + - setup/deno — ENV-first Deno setup and command runner (`DENO_*` envs). + - setup/conan — Installs Conan via pip (placeholder for future C++ builds). +- sign — Unified signing for macOS and Windows; notarizes on tag builds (macOS). +- package — Upload artifacts and (on tags) publish a GitHub Release; includes smarter artifact naming and optional `artifact_meta.json`. + +Stacks under actions/build/ +- build/wails2 — Full Wails v2 pipeline wrapper (discovery → options → setup → build → sign → package). + - build/wails2/build — Runs `wails build` for the chosen platform and fixes executable permissions. + +Notes +- In composite actions (inside this repo), reference other sub-actions via relative paths like `uses: ./actions/discovery`. +- In workflows within this repo, reference local actions with `uses: ./actions/` (or the repo root with `uses: ./`). +- For consumers of this repo, use the fully qualified path, for example: `uses: snider/build/actions/discovery@v3`. diff --git a/actions/action.yml b/actions/action.yml new file mode 100644 index 0000000..261d0fb --- /dev/null +++ b/actions/action.yml @@ -0,0 +1,86 @@ +name: "Directory Orchestrator" +description: "Selects and delegates to a stack wrapper based on discovery outputs and ENV" +inputs: + build: + required: false + default: "true" + description: "" + sign: + required: false + default: "false" + description: "" + package: + required: false + default: "true" + description: "" + build-name: + required: true + description: "" + build-platform: + required: false + default: "darwin/universal" + description: "" + app-working-directory: + required: false + default: "." + description: "" + # Orchestrator controls + AUTO_STACK: + required: false + default: "true" + description: "" + AUTO_SETUP: + required: false + default: "true" + description: "" + STACK: + required: false + default: "" + description: "" + # Optional hint from a prior discovery step + PRIMARY_STACK_SUGGESTION: + required: false + default: "" + description: "" +runs: + using: "composite" + steps: + - name: Resolve stack selection + id: sel + shell: bash + env: + AUTO_STACK: ${{ inputs.AUTO_STACK }} + FORCED_STACK: ${{ inputs.STACK }} + HINT: ${{ inputs.PRIMARY_STACK_SUGGESTION }} + run: | + set -euo pipefail + sel_stack="wails2" + if [ -n "${FORCED_STACK:-}" ]; then + sel_stack="$FORCED_STACK" + echo "[DEBUG_LOG] (orchestrator) Forced stack via input STACK=$sel_stack" + elif [ "${AUTO_STACK:-true}" = "true" ] || [ "${AUTO_STACK:-true}" = "1" ]; then + if [ -n "${HINT:-}" ] && [ "$HINT" != "unknown" ]; then + sel_stack="$HINT" + echo "[DEBUG_LOG] (orchestrator) Auto stack=${sel_stack} (from discovery hint)" + else + echo "[DEBUG_LOG] (orchestrator) No hint; defaulting to wails2" + fi + else + echo "[DEBUG_LOG] (orchestrator) AUTO_STACK disabled; defaulting to wails2" + fi + echo "SELECTED_STACK=$sel_stack" >> "$GITHUB_OUTPUT" + + - name: Call Wails v2 wrapper + if: steps.sel.outputs.SELECTED_STACK == 'wails2' + uses: ./actions/build/wails2 + with: + build: ${{ inputs.build }} + sign: ${{ inputs.sign }} + package: ${{ inputs.package }} + build-name: ${{ inputs.build-name }} + build-platform: ${{ inputs.build-platform }} + app-working-directory: ${{ inputs.app-working-directory }} +outputs: + SELECTED_STACK: + description: "Stack selected by the orchestrator" + value: ${{ steps.sel.outputs.SELECTED_STACK }} diff --git a/actions/build/README.md b/actions/build/README.md new file mode 100644 index 0000000..6dd4b8c --- /dev/null +++ b/actions/build/README.md @@ -0,0 +1,29 @@ +# actions/build/ index + +Stack wrappers live here. Each wrapper owns its stack-specific inputs and wiring and can be called directly or via the root orchestrator. + +Available stacks +- wails2 — Full Wails v2 pipeline wrapper at `actions/build/wails2`. + +Coming soon +- wails3 — Alpha once upstream stabilizes. +- cpp — C++ toolchain via `setup/conan` plus dedicated build/sign/package steps. + +Usage examples +- Wrapper (local in this repo): + ```yaml + - uses: ./actions/build/wails2 + with: + build-name: myApp + build-platform: linux/amd64 + ``` +- From another repo: + ```yaml + - uses: snider/build/actions/build/wails2@v3 + with: + build-name: myApp + build-platform: linux/amd64 + ``` + +Notes +- The root orchestrator decides which stack to call using `actions/discovery` and env flags. Set `STACK` to force a stack or disable auto-selection with `AUTO_STACK: 'false'`. diff --git a/actions/build/wails2/README.md b/actions/build/wails2/README.md new file mode 100644 index 0000000..973f923 --- /dev/null +++ b/actions/build/wails2/README.md @@ -0,0 +1,134 @@ +# Wails v2 (full pipeline) + +Important +- 20/02/2025 — Wails v2.10.0 is reported problematic. Prefer `wails-version: "v2.9.0"` until upstream fixes land. + +Purpose +- Run the entire Wails v2 build pipeline in one step: discovery → options → setup (Go/npm/Deno/Wails) → build → optional signing → packaging. + +Usage (recommended) +```yaml +- name: Build Wails v2 + uses: snider/build/actions/build/wails2@v3 + with: + build-name: wailsApp + build-platform: linux/amd64 # or windows/amd64, darwin/universal + # Optional features + build-obfuscate: 'false' + nsis: 'false' + sign: 'false' + package: 'true' + wails-version: 'latest' +``` + +Matrix example +```yaml +name: Wails v2 build (matrix) + +on: [push, pull_request] + +jobs: + build: + strategy: + fail-fast: false + matrix: + build: [ + {name: wailsTest, platform: linux/amd64, os: ubuntu-latest}, + {name: wailsTest, platform: windows/amd64, os: windows-latest}, + {name: wailsTest, platform: darwin/universal, os: macos-latest} + ] + runs-on: ${{ matrix.build.os }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: snider/build@v3 + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + build-obfuscate: 'true' +``` + +macOS Code Signing (Wails v2) + +You need two `gon` configuration files to sign and notarize the `.app` before building the installer pkg. + +Workflow snippet +```yaml +- uses: snider/build@v3 + with: + build-name: wailsApp + sign: true + build-platform: darwin/universal + sign-macos-apple-password: ${{ secrets.APPLE_PASSWORD }} + sign-macos-app-id: ${{ secrets.MACOS_DEVELOPER_CERT_ID }} + sign-macos-app-cert: ${{ secrets.MACOS_DEVELOPER_CERT }} + sign-macos-app-cert-password: ${{ secrets.MACOS_DEVELOPER_CERT_PASSWORD }} + sign-macos-installer-id: ${{ secrets.MACOS_INSTALLER_CERT_ID }} + sign-macos-installer-cert: ${{ secrets.MACOS_INSTALLER_CERT }} + sign-macos-installer-cert-password: ${{ secrets.MACOS_INSTALLER_CERT_PASSWORD }} +``` + +`build/darwin/gon-sign.json` +```json +{ + "source" : ["./build/bin/wailsApp.app"], + "bundle_id" : "com.wails.app", + "apple_id": { + "username": "username", + "password": "@env:APPLE_PASSWORD" + }, + "sign" :{ + "application_identity" : "Developer ID Application: XXXXXXXX (XXXXXX)", + "entitlements_file": "./build/darwin/entitlements.plist" + }, + "dmg" :{ + "output_path": "./build/bin/wailsApp.dmg", + "volume_name": "Lethean" + } +} +``` + +`build/darwin/gon-notarize.json` +```json +{ + "notarize": [{ + "path": "./build/bin/wailsApp.pkg", + "bundle_id": "com.wails.app", + "staple": true + },{ + "path": "./build/bin/wailsApp.app.zip", + "bundle_id": "com.wails.app", + "staple": false + }], + "apple_id": { + "username": "USER name", + "password": "@env:APPLE_PASSWORD" + } +} +``` + +`build/darwin/entitlements.plist` +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + + +``` + +Notes +- Deno is optional and can be configured via environment variables (ENV-first): `DENO_ENABLE`, `DENO_BUILD`, `DENO_VERSION`, `DENO_WORKDIR`. +- NPM extras (Wails-only): set `NPM_ENABLE` to `true`/`1`/`yes`/`on` and provide `NPM_PACKAGES` (space-separated) to install extra global packages needed by CI before the build. If `NPM_PACKAGES` is empty, the step is skipped. +- On Linux, the action detects Ubuntu 20.04/22.04/24.04 and installs matching WebKitGTK packages; Ubuntu 24.04 implies `-tags webkit2_41` when appropriate. +- macOS signing and notarization only occur on tag builds when certs/passwords are provided. +- This sub-action is a convenience wrapper that delegates to the underlying sub-actions in this repository. diff --git a/actions/build/wails2/action.yml b/actions/build/wails2/action.yml new file mode 100644 index 0000000..1bae14f --- /dev/null +++ b/actions/build/wails2/action.yml @@ -0,0 +1,292 @@ +name: "Wails v2 (full pipeline)" +description: "Runs the full Wails v2 build pipeline: discovery, options, setup (Go/Deno/Wails), build, sign, and package" +inputs: + build: + description: "Whether to run the build" + required: false + default: "true" + sign: + description: "Sign the build (macOS/Windows)" + required: false + default: "false" + package: + description: "Upload artifacts and release on tag" + required: false + default: "true" + nsis: + description: "Build a Windows Installer" + required: false + default: "false" + build-name: + description: "The name of the binary/app bundle" + required: true + build-cache: + description: "Enable Go cache" + required: false + default: "true" + build-platform: + description: "Platform to build for (e.g., linux/amd64, windows/amd64, darwin/universal)" + required: false + default: "darwin/universal" + build-tags: + description: "Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated" + required: false + default: "false" + build-obfuscate: + description: "Obfuscate (garble) the build" + required: false + default: "false" + wails-version: + description: "Wails version to use" + required: false + default: "latest" + wails-build-webview2: + description: "WebView2 installer method [download,embed,browser,error]" + required: false + default: "download" + go-version: + description: "Go version" + required: false + default: "1.23" + node-version: + description: "Node js version (unused by pipeline but kept for compatibility)" + required: false + default: "18.x" + deno-build: + description: "Deno command to run (optional, ENV-first)" + required: false + default: "" + app-working-directory: + description: "App working directory" + required: false + default: "." + deno-working-directory: + description: "Deno working directory" + required: false + default: "." + deno-version: + description: "Deno version" + required: false + default: "v1.20.x" + sign-macos-app-id: + required: false + default: '' + description: "" + sign-macos-apple-password: + required: false + default: '' + description: "" + sign-macos-app-cert: + required: false + default: '' + description: "" + sign-macos-app-cert-password: + required: false + default: '' + description: "" + sign-macos-installer-id: + required: false + default: '' + description: "" + sign-macos-installer-cert: + required: false + default: '' + description: "" + sign-macos-installer-cert-password: + required: false + default: '' + description: "" + sign-windows-cert: + required: false + default: '' + description: "" + sign-windows-cert-password: + required: false + default: '' + description: "" + wails-dev-build: + description: "Use provided wails binary instead of installing" + required: false + default: "false" +runs: + using: "composite" + steps: + - name: Resolve Wails configuration (inputs > env > defaults) + id: wcfg + shell: bash + env: + IN_BUILD_TAGS: ${{ inputs.build-tags }} + IN_OBFUSCATE: ${{ inputs.build-obfuscate }} + IN_NSIS: ${{ inputs.nsis }} + IN_WV2: ${{ inputs.wails-build-webview2 }} + IN_WAILS_VER: ${{ inputs.wails-version }} + IN_GO_VER: ${{ inputs.go-version }} + IN_NODE_VER: ${{ inputs.node-version }} + IN_DENO_VER: ${{ inputs.deno-version }} + # Env alternatives + EV_BUILD_TAGS: ${{ env.WAILS_BUILD_TAGS }} + EV_OBFUSCATE: ${{ env.WAILS_OBFUSCATE }} + EV_NSIS: ${{ env.WAILS_NSIS }} + EV_WV2: ${{ env.WAILS_WEBVIEW2 }} + EV_WAILS_VER: ${{ env.WAILS_VERSION }} + EV_GO_VER: ${{ env.WAILS_GO_VERSION }} + EV_NODE_VER: ${{ env.WAILS_NODE_VERSION }} + EV_DENO_VER: ${{ env.WAILS_DENO_VERSION }} + # Signing envs + EV_MAC_PW: ${{ env.SIGN_MACOS_APPLE_PASSWORD }} + EV_MAC_ID: ${{ env.SIGN_MACOS_APP_ID }} + EV_MAC_CERT: ${{ env.SIGN_MACOS_APP_CERT }} + EV_MAC_CERT_PW: ${{ env.SIGN_MACOS_APP_CERT_PASSWORD }} + EV_MAC_INS_ID: ${{ env.SIGN_MACOS_INSTALLER_ID }} + EV_MAC_INS_CERT: ${{ env.SIGN_MACOS_INSTALLER_CERT }} + EV_MAC_INS_CERT_PW: ${{ env.SIGN_MACOS_INSTALLER_CERT_PASSWORD }} + EV_WIN_CERT: ${{ env.SIGN_WINDOWS_CERT }} + EV_WIN_CERT_PW: ${{ env.SIGN_WINDOWS_CERT_PASSWORD }} + run: | + set -euo pipefail + # helper to pick first non-empty + pick() { if [ -n "$1" ] && [ "$1" != "false" ]; then echo "$1"; else echo "$2"; fi } + # booleans normalize + tobool() { case "${1,,}" in true|1|yes|on) echo "true";; *) echo "false";; esac } + BUILD_TAGS=$(pick "${IN_BUILD_TAGS:-}" "${EV_BUILD_TAGS:-}") + OBFUSCATE=$(tobool "$(pick "${IN_OBFUSCATE:-}" "${EV_OBFUSCATE:-}")") + NSIS=$(tobool "$(pick "${IN_NSIS:-}" "${EV_NSIS:-}")") + WV2=$(pick "${IN_WV2:-}" "${EV_WV2:-}") + WAILS_VER=$(pick "${IN_WAILS_VER:-}" "${EV_WAILS_VER:-}") + GO_VER=$(pick "${IN_GO_VER:-}" "${EV_GO_VER:-}") + NODE_VER=$(pick "${IN_NODE_VER:-}" "${EV_NODE_VER:-}") + DENO_VER=$(pick "${IN_DENO_VER:-}" "${EV_DENO_VER:-}") + # Signing + MAC_PW="${EV_MAC_PW:-}"; MAC_ID="${EV_MAC_ID:-}"; MAC_CERT="${EV_MAC_CERT:-}"; MAC_CERT_PW="${EV_MAC_CERT_PW:-}" + MAC_INS_ID="${EV_MAC_INS_ID:-}"; MAC_INS_CERT="${EV_MAC_INS_CERT:-}"; MAC_INS_CERT_PW="${EV_MAC_INS_CERT_PW:-}" + WIN_CERT="${EV_WIN_CERT:-}"; WIN_CERT_PW="${EV_WIN_CERT_PW:-}" + echo "BUILD_TAGS=$BUILD_TAGS" >> "$GITHUB_OUTPUT" + echo "OBFUSCATE=$OBFUSCATE" >> "$GITHUB_OUTPUT" + echo "NSIS=$NSIS" >> "$GITHUB_OUTPUT" + echo "WV2=$WV2" >> "$GITHUB_OUTPUT" + echo "WAILS_VER=$WAILS_VER" >> "$GITHUB_OUTPUT" + echo "GO_VER=$GO_VER" >> "$GITHUB_OUTPUT" + echo "NODE_VER=$NODE_VER" >> "$GITHUB_OUTPUT" + echo "DENO_VER=$DENO_VER" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_APPLE_PASSWORD=$MAC_PW" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_APP_ID=$MAC_ID" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_APP_CERT=$MAC_CERT" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_APP_CERT_PASSWORD=$MAC_CERT_PW" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_INSTALLER_ID=$MAC_INS_ID" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_INSTALLER_CERT=$MAC_INS_CERT" >> "$GITHUB_OUTPUT" + echo "SIGN_MACOS_INSTALLER_CERT_PASSWORD=$MAC_INS_CERT_PW" >> "$GITHUB_OUTPUT" + echo "SIGN_WINDOWS_CERT=$WIN_CERT" >> "$GITHUB_OUTPUT" + echo "SIGN_WINDOWS_CERT_PASSWORD=$WIN_CERT_PW" >> "$GITHUB_OUTPUT" + echo "[DEBUG_LOG] Wails2 resolve: tags='${BUILD_TAGS:-}' obf=${OBFUSCATE} nsis=${NSIS} wv2='${WV2:-default}' wails='${WAILS_VER:-default}' go='${GO_VER:-default}' node='${NODE_VER:-default}' deno='${DENO_VER:-default}'" + + - name: Discovery + id: discovery + uses: ./actions/discovery + with: + working-directory: ${{ inputs.app-working-directory }} + + - name: Compute Build Options + id: build_options + uses: ./actions/options + with: + build-obfuscate: ${{ steps.wcfg.outputs.OBFUSCATE }} + build-tags: ${{ steps.wcfg.outputs.BUILD_TAGS }} + nsis: ${{ steps.wcfg.outputs.NSIS }} + distro: ${{ steps.discovery.outputs.DISTRO }} + + - name: Setup toolchains (Go/Node/Deno/Wails) + uses: ./actions/setup + with: + go-version: ${{ steps.wcfg.outputs.GO_VER }} + build-cache: ${{ inputs.build-cache }} + build-obfuscate: ${{ steps.wcfg.outputs.OBFUSCATE }} + wails-version: ${{ steps.wcfg.outputs.WAILS_VER }} + wails-dev-build: ${{ inputs.wails-dev-build }} + node-version: ${{ steps.wcfg.outputs.NODE_VER }} + npm-working-directory: ${{ inputs.app-working-directory }} + npm-install: 'true' + deno-build: ${{ inputs.deno-build }} + deno-version: ${{ steps.wcfg.outputs.DENO_VER }} + deno-working-directory: ${{ inputs.deno-working-directory }} + + - name: Wails2 npm extras (env-first) + shell: bash + run: | + set -euo pipefail + npm_enable="${NPM_ENABLE:-}" + npm_packages="${NPM_PACKAGES:-}" + case "${npm_enable,,}" in + true|1|yes|on) enable=1;; + *) enable=0;; + esac + echo "[DEBUG_LOG] Wails2 npm extras: NPM_ENABLE=${npm_enable:-} NPM_PACKAGES=${npm_packages:-}" + if [ -z "$npm_packages" ] && [ "$enable" -ne 1 ]; then + echo "[DEBUG_LOG] NPM extras not enabled (set NPM_ENABLE or NPM_PACKAGES). Skipping." + exit 0 + fi + if [ -z "$npm_packages" ]; then + echo "[DEBUG_LOG] NPM_ENABLE set but NPM_PACKAGES is empty; nothing to install. Skipping." + exit 0 + fi + echo "[DEBUG_LOG] Installing extra npm packages globally: $npm_packages" + npm install -g $npm_packages + + - name: Build Wails app + uses: ./actions/build/wails2/build + with: + build: ${{ inputs.build }} + app-working-directory: ${{ inputs.app-working-directory }} + build-platform: ${{ inputs.build-platform }} + build-name: ${{ inputs.build-name }} + wails-build-webview2: ${{ steps.wcfg.outputs.WV2 }} + build-options: ${{ steps.build_options.outputs.BUILD_OPTIONS }} + + - name: Sign artifacts (OS-conditional) + uses: ./actions/sign + with: + sign: ${{ inputs.sign }} + app-working-directory: ${{ inputs.app-working-directory }} + build-name: ${{ inputs.build-name }} + sign-macos-apple-password: ${{ steps.wcfg.outputs.SIGN_MACOS_APPLE_PASSWORD }} + sign-macos-app-id: ${{ steps.wcfg.outputs.SIGN_MACOS_APP_ID }} + sign-macos-app-cert: ${{ steps.wcfg.outputs.SIGN_MACOS_APP_CERT }} + sign-macos-app-cert-password: ${{ steps.wcfg.outputs.SIGN_MACOS_APP_CERT_PASSWORD }} + sign-macos-installer-id: ${{ steps.wcfg.outputs.SIGN_MACOS_INSTALLER_ID }} + sign-macos-installer-cert: ${{ steps.wcfg.outputs.SIGN_MACOS_INSTALLER_CERT }} + sign-macos-installer-cert-password: ${{ steps.wcfg.outputs.SIGN_MACOS_INSTALLER_CERT_PASSWORD }} + sign-windows-cert: ${{ steps.wcfg.outputs.SIGN_WINDOWS_CERT }} + sign-windows-cert-password: ${{ steps.wcfg.outputs.SIGN_WINDOWS_CERT_PASSWORD }} + + - name: Package & release + uses: ./actions/package + with: + package: ${{ inputs.package }} + build-name: ${{ inputs.build-name }} + os: ${{ steps.discovery.outputs.OS }} + arch: ${{ steps.discovery.outputs.ARCH }} + tag: ${{ steps.discovery.outputs.TAG }} + is-tag: ${{ steps.discovery.outputs.IS_TAG }} + short-sha: ${{ steps.discovery.outputs.SHORT_SHA }} + ref: ${{ steps.discovery.outputs.REF }} +outputs: + BUILD_TAGS: + description: "Resolved build tags (after env/input precedence)" + value: ${{ steps.wcfg.outputs.BUILD_TAGS }} + OBFUSCATE: + description: "Resolved obfuscate flag" + value: ${{ steps.wcfg.outputs.OBFUSCATE }} + NSIS: + description: "Resolved nsis flag" + value: ${{ steps.wcfg.outputs.NSIS }} + WAILS_VERSION: + description: "Resolved Wails version" + value: ${{ steps.wcfg.outputs.WAILS_VER }} + GO_VERSION: + description: "Resolved Go version" + value: ${{ steps.wcfg.outputs.GO_VER }} + NODE_VERSION: + description: "Resolved Node version" + value: ${{ steps.wcfg.outputs.NODE_VER }} + DENO_VERSION: + description: "Resolved Deno version" + value: ${{ steps.wcfg.outputs.DENO_VER }} diff --git a/actions/build/wails2/build/README.md b/actions/build/wails2/build/README.md new file mode 100644 index 0000000..dfe3f38 --- /dev/null +++ b/actions/build/wails2/build/README.md @@ -0,0 +1,29 @@ +# Build Wails v2 App (sub-action) + +Purpose +- Runs `wails build` for the specified platform/name and fixes executable permissions by OS. + +Inputs +- `build` (default `true`) — set to `false` to skip. +- `app-working-directory` (default `.`) — where your Wails project resides. +- `build-platform` (required) — e.g., `linux/amd64`, `windows/amd64`, `darwin/universal`. +- `build-name` (required) — output name (binary or .app bundle name). +- `wails-build-webview2` (default `download`) — WebView2 mode on Windows. +- `build-options` (default `''`) — precomputed flags (from `actions/options`), e.g., `-obfuscated -tags webkit2_41`. + +Usage +```yaml +- name: Build Wails app + uses: snider/build/actions/build/wails2/build@v3 + with: + build: 'true' + app-working-directory: 'build/wails2' # or your project dir + build-platform: 'linux/amd64' + build-name: 'wailsApp' + wails-build-webview2: 'download' + build-options: ${{ steps.opts.outputs.BUILD_OPTIONS }} +``` + +Notes +- Ensure Wails CLI is installed beforehand (use the `actions/setup` orchestrator which calls `actions/setup/go`). +- On macOS and Linux, this action will `chmod +x` the built files to ensure they are executable. diff --git a/actions/build/wails2/build/action.yml b/actions/build/wails2/build/action.yml new file mode 100644 index 0000000..1dae36f --- /dev/null +++ b/actions/build/wails2/build/action.yml @@ -0,0 +1,41 @@ +name: "Build Wails App" +description: "Runs wails build and fixes executable permissions per OS" +inputs: + build: + description: "Whether to run the build" + required: false + default: "true" + app-working-directory: + required: false + default: "." + build-platform: + required: true + build-name: + required: true + wails-build-webview2: + required: false + default: "download" + build-options: + description: "Precomputed BUILD_OPTIONS string" + required: false + default: "" +runs: + using: "composite" + steps: + - name: Build App + if: inputs.build == 'true' + env: + BUILD_OPTIONS: ${{ inputs.build-options }} + working-directory: ${{ inputs.app-working-directory }} + run: wails build --platform ${{ inputs.build-platform }} -webview2 ${{ inputs.wails-build-webview2 }} -o ${{ inputs.build-name }} $BUILD_OPTIONS + shell: bash + - name: Add macOS perms + if: inputs.build == 'true' && runner.os == 'macOS' + working-directory: ${{ inputs.app-working-directory }} + run: chmod +x build/bin/*/Contents/MacOS/* + shell: bash + - name: Add Linux perms + if: inputs.build == 'true' && runner.os == 'Linux' + working-directory: ${{ inputs.app-working-directory }} + run: chmod +x build/bin/* + shell: bash diff --git a/actions/discovery/README.md b/actions/discovery/README.md new file mode 100644 index 0000000..8cc06e8 --- /dev/null +++ b/actions/discovery/README.md @@ -0,0 +1,57 @@ +# Discovery (sub-action) + +Purpose +- Detects OS and CPU architecture across all runners. +- On Linux, detects Ubuntu distro and installs required GTK/WebKit packages for Wails builds. +- Exposes useful repository/ref metadata (REF, BRANCH, TAG, IS_TAG, SHA, SHORT_SHA, REPO, OWNER) for later steps such as packaging. +- Scans your app working directory for common project markers to suggest a primary stack automatically. + +Inputs +- `working-directory` (default `.`) — directory to scan for project markers. + +Outputs +- Runner info: + - `OS` — `Linux`, `macOS`, or `Windows`. + - `ARCH` — CPU architecture normalized where possible (`amd64`, `arm64`, etc.). + - `DISTRO` — Ubuntu version string like `20.04`, `22.04`, or `24.04` (Linux only, empty otherwise). +- Repo/ref metadata: + - `REF` — Full Git ref (e.g., `refs/heads/main`, `refs/tags/v1.2.3`). + - `BRANCH` — Branch name when applicable; empty on tag refs. + - `TAG` — Tag name when on a tag ref; empty otherwise. + - `IS_TAG` — `1` if ref is a tag, else `0`. + - `SHA` — Full commit SHA. + - `SHORT_SHA` — First 7 characters of the commit SHA. + - `REPO` — `owner/repo`. + - `OWNER` — Repository owner. +- Project markers (scanned under `working-directory`): + - `HAS_ROOT_PACKAGE_JSON` — `1` if `package.json` at root. + - `HAS_FRONTEND_PACKAGE_JSON` — `1` if `frontend/package.json` exists. + - `HAS_ROOT_GO_MOD` — `1` if `go.mod` at root. + - `HAS_ROOT_MAIN_GO` — `1` if `main.go` at root. + - `HAS_ROOT_CMAKELISTS` — `1` if `CMakeLists.txt` at root. + - `HAS_ROOT_MKDOCS` — `1` if `mkdocs.yml` at root. + - `HAS_SUB_NPM` — `1` if any `package.json` found within depth 2 (excluding node_modules). + - `HAS_SUB_MKDOCS` — `1` if any `mkdocs.yml` found within depth 2. + - `FOUND_FILES` — comma-separated summary of notable files found. +- Stack suggestion: + - `PRIMARY_STACK_SUGGESTION` — `wails2`, `cpp`, or `unknown`. + +Usage +```yaml +- name: Discovery + id: disc + uses: snider/build/actions/discovery@v3 + with: + working-directory: build/wails2 # or your app dir +# Later examples: +# ${{ steps.disc.outputs.OS }} +# ${{ steps.disc.outputs.ARCH }} +# ${{ steps.disc.outputs.DISTRO }} +# ${{ steps.disc.outputs.TAG }} +# ${{ steps.disc.outputs.PRIMARY_STACK_SUGGESTION }} +``` + +Notes +- Runs on all OSes; only installs packages on Linux. +- Linux support currently covers Ubuntu 20.04, 22.04, and 24.04 (24.04 uses `libwebkit2gtk-4.1-dev`). +- Look for `[DEBUG_LOG]` lines in logs to see which markers were detected and which stack was suggested. \ No newline at end of file diff --git a/actions/discovery/action.yml b/actions/discovery/action.yml new file mode 100644 index 0000000..50a78b8 --- /dev/null +++ b/actions/discovery/action.yml @@ -0,0 +1,267 @@ +name: "Discovery" +description: "Detect OS/ARCH and (on Linux) distro; install required packages; expose repo/ref metadata; detect project markers (root and subtree)" +inputs: + working-directory: + description: "Directory to scan for project markers (root of the app)" + required: false + default: "." +runs: + using: "composite" + steps: + - name: Linux discovery and deps + if: runner.os == 'Linux' + id: linux + shell: bash + run: | + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + tries=0 + until sudo apt-get -yq update; do + tries=$((tries+1)) + if [ $tries -ge 3 ]; then echo "apt-get update failed after $tries attempts"; exit 1; fi + echo "Retrying apt-get update ($tries)"; sleep 2 + done + DISTRO=$(lsb_release -rs) + if [[ "$DISTRO" == "20.04" ]]; then + sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.0-dev gcc-aarch64-linux-gnu + elif [[ "$DISTRO" == "22.04" ]]; then + sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.0-dev gcc-aarch64-linux-gnu + elif [[ "$DISTRO" == "24.04" ]]; then + sudo apt-get -yq install libgtk-3-0 libwebkit2gtk-4.1-dev gcc-aarch64-linux-gnu + else + echo "Unsupported Linux distribution: $DISTRO" + exit 1 + fi + echo "DISTRO=$DISTRO" >> "$GITHUB_OUTPUT" + - name: Common metadata (bash) + if: runner.os != 'Windows' + id: meta_bash + shell: bash + run: | + set -euo pipefail + OS="${{ runner.os }}" + M="$(uname -m)" + case "$M" in + x86_64|amd64) ARCH="amd64";; + aarch64|arm64) ARCH="arm64";; + armv7l) ARCH="armv7";; + *) ARCH="$M";; + esac + REF="${{ github.ref }}" + BRANCH="" + if [[ "$REF" == refs/heads/* ]]; then + BRANCH="${REF#refs/heads/}" + fi + SHA="${{ github.sha }}" + SHORT_SHA="${SHA::7}" + REPO="${{ github.repository }}" + OWNER="${{ github.repository_owner }}" + TAG="" + IS_TAG=0 + if [[ "$REF" == refs/tags/* ]]; then + IS_TAG=1 + TAG="${REF#refs/tags/}" + fi + echo "OS=$OS" >> "$GITHUB_OUTPUT" + echo "ARCH=$ARCH" >> "$GITHUB_OUTPUT" + echo "REF=$REF" >> "$GITHUB_OUTPUT" + echo "BRANCH=$BRANCH" >> "$GITHUB_OUTPUT" + echo "SHA=$SHA" >> "$GITHUB_OUTPUT" + echo "SHORT_SHA=$SHORT_SHA" >> "$GITHUB_OUTPUT" + echo "REPO=$REPO" >> "$GITHUB_OUTPUT" + echo "OWNER=$OWNER" >> "$GITHUB_OUTPUT" + echo "TAG=$TAG" >> "$GITHUB_OUTPUT" + echo "IS_TAG=$IS_TAG" >> "$GITHUB_OUTPUT" + - name: Common metadata (powershell) + if: runner.os == 'Windows' + id: meta_pwsh + shell: powershell + run: | + $OS = "${{ runner.os }}" + $archEnv = $Env:PROCESSOR_ARCHITECTURE + if ($archEnv -eq "AMD64") { $ARCH = "amd64" } + elseif ($archEnv -eq "ARM64") { $ARCH = "arm64" } + else { $ARCH = $archEnv } + $REF = "${{ github.ref }}" + $BRANCH = "" + if ($REF.StartsWith("refs/heads/")) { $BRANCH = $REF.Substring(11) } + $SHA = "${{ github.sha }}" + $SHORT_SHA = $SHA.Substring(0,7) + $REPO = "${{ github.repository }}" + $OWNER = "${{ github.repository_owner }}" + $TAG = "" + $IS_TAG = 0 + if ($REF.StartsWith("refs/tags/")) { + $IS_TAG = 1 + $TAG = $REF.Substring(10) + } + "OS=$OS" >> $Env:GITHUB_OUTPUT + "ARCH=$ARCH" >> $Env:GITHUB_OUTPUT + "REF=$REF" >> $Env:GITHUB_OUTPUT + "BRANCH=$BRANCH" >> $Env:GITHUB_OUTPUT + "SHA=$SHA" >> $Env:GITHUB_OUTPUT + "SHORT_SHA=$SHORT_SHA" >> $Env:GITHUB_OUTPUT + "REPO=$REPO" >> $Env:GITHUB_OUTPUT + "OWNER=$OWNER" >> $Env:GITHUB_OUTPUT + "TAG=$TAG" >> $Env:GITHUB_OUTPUT + "IS_TAG=$IS_TAG" >> $Env:GITHUB_OUTPUT + - name: Project markers (bash) + if: runner.os != 'Windows' + id: proj_bash + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + set -euo pipefail + echo "[DEBUG_LOG] Discovery scanning working dir: $PWD" + has_root_pkg=0; has_frontend_pkg=0; has_go_mod=0; has_main_go=0; has_cmake=0; has_mkdocs=0 + has_sub_npm=0; has_sub_mkdocs=0 + found_files=() + # Root markers + if [ -f "package.json" ]; then has_root_pkg=1; found_files+=("package.json"); fi + if [ -f "go.mod" ]; then has_go_mod=1; found_files+=("go.mod"); fi + if [ -f "main.go" ]; then has_main_go=1; found_files+=("main.go"); fi + if [ -f "CMakeLists.txt" ]; then has_cmake=1; found_files+=("CMakeLists.txt"); fi + if [ -f "mkdocs.yml" ]; then has_mkdocs=1; found_files+=("mkdocs.yml"); fi + # Common subtree markers + if [ -f "frontend/package.json" ]; then has_frontend_pkg=1; found_files+=("frontend/package.json"); fi + # Light subtree search up to depth 2 for package.json and mkdocs.yml + if command -v find >/dev/null 2>&1; then + if find . -maxdepth 2 -mindepth 2 -name package.json | grep -q .; then has_sub_npm=1; fi + if find . -maxdepth 2 -mindepth 1 -name mkdocs.yml | grep -q .; then has_sub_mkdocs=1; fi + fi + # Suggest stack + suggestion="unknown" + if { [ "$has_go_mod" -eq 1 ] || [ "$has_main_go" -eq 1 ]; } && { [ "$has_root_pkg" -eq 1 ] || [ "$has_frontend_pkg" -eq 1 ] || [ "$has_sub_npm" -eq 1 ]; }; then + suggestion="wails2" + elif [ "$has_cmake" -eq 1 ]; then + suggestion="cpp" + fi + # Output and logs + echo "[DEBUG_LOG] HAS_ROOT_PACKAGE_JSON=$has_root_pkg" + echo "[DEBUG_LOG] HAS_FRONTEND_PACKAGE_JSON=$has_frontend_pkg" + echo "[DEBUG_LOG] HAS_ROOT_GO_MOD=$has_go_mod" + echo "[DEBUG_LOG] HAS_ROOT_MAIN_GO=$has_main_go" + echo "[DEBUG_LOG] HAS_ROOT_CMAKELISTS=$has_cmake" + echo "[DEBUG_LOG] HAS_ROOT_MKDOCS=$has_mkdocs" + echo "[DEBUG_LOG] HAS_SUB_NPM=$has_sub_npm" + echo "[DEBUG_LOG] HAS_SUB_MKDOCS=$has_sub_mkdocs" + echo "[DEBUG_LOG] PRIMARY_STACK_SUGGESTION=$suggestion" + echo "HAS_ROOT_PACKAGE_JSON=$has_root_pkg" >> "$GITHUB_OUTPUT" + echo "HAS_FRONTEND_PACKAGE_JSON=$has_frontend_pkg" >> "$GITHUB_OUTPUT" + echo "HAS_ROOT_GO_MOD=$has_go_mod" >> "$GITHUB_OUTPUT" + echo "HAS_ROOT_MAIN_GO=$has_main_go" >> "$GITHUB_OUTPUT" + echo "HAS_ROOT_CMAKELISTS=$has_cmake" >> "$GITHUB_OUTPUT" + echo "HAS_ROOT_MKDOCS=$has_mkdocs" >> "$GITHUB_OUTPUT" + echo "HAS_SUB_NPM=$has_sub_npm" >> "$GITHUB_OUTPUT" + echo "HAS_SUB_MKDOCS=$has_sub_mkdocs" >> "$GITHUB_OUTPUT" + echo "PRIMARY_STACK_SUGGESTION=$suggestion" >> "$GITHUB_OUTPUT" + if [ ${#found_files[@]} -gt 0 ]; then + IFS=,; echo "FOUND_FILES=${found_files[*]}" >> "$GITHUB_OUTPUT"; unset IFS + else + echo "FOUND_FILES=" >> "$GITHUB_OUTPUT" + fi + - name: Project markers (powershell) + if: runner.os == 'Windows' + id: proj_pwsh + shell: powershell + working-directory: ${{ inputs.working-directory }} + run: | + Write-Host "[DEBUG_LOG] Discovery scanning working dir: $PWD" + $has_root_pkg=0; $has_frontend_pkg=0; $has_go_mod=0; $has_main_go=0; $has_cmake=0; $has_mkdocs=0 + $has_sub_npm=0; $has_sub_mkdocs=0 + $found = @() + if (Test-Path package.json) { $has_root_pkg=1; $found+="package.json" } + if (Test-Path go.mod) { $has_go_mod=1; $found+="go.mod" } + if (Test-Path main.go) { $has_main_go=1; $found+="main.go" } + if (Test-Path CMakeLists.txt) { $has_cmake=1; $found+="CMakeLists.txt" } + if (Test-Path mkdocs.yml) { $has_mkdocs=1; $found+="mkdocs.yml" } + if (Test-Path frontend/package.json) { $has_frontend_pkg=1; $found+="frontend/package.json" } + # Limited subtree search (depth ~2) + Get-ChildItem -Recurse -Depth 2 -Filter package.json -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notlike "*node_modules*" } | ForEach-Object { $has_sub_npm=1 } + Get-ChildItem -Recurse -Depth 2 -Filter mkdocs.yml -ErrorAction SilentlyContinue | ForEach-Object { $has_sub_mkdocs=1 } + $suggestion = "unknown" + if ((($has_go_mod -eq 1) -or ($has_main_go -eq 1)) -and (($has_root_pkg -eq 1) -or ($has_frontend_pkg -eq 1) -or ($has_sub_npm -eq 1))) { $suggestion = "wails2" } + elseif ($has_cmake -eq 1) { $suggestion = "cpp" } + Write-Host "[DEBUG_LOG] HAS_ROOT_PACKAGE_JSON=$has_root_pkg" + Write-Host "[DEBUG_LOG] HAS_FRONTEND_PACKAGE_JSON=$has_frontend_pkg" + Write-Host "[DEBUG_LOG] HAS_ROOT_GO_MOD=$has_go_mod" + Write-Host "[DEBUG_LOG] HAS_ROOT_MAIN_GO=$has_main_go" + Write-Host "[DEBUG_LOG] HAS_ROOT_CMAKELISTS=$has_cmake" + Write-Host "[DEBUG_LOG] HAS_ROOT_MKDOCS=$has_mkdocs" + Write-Host "[DEBUG_LOG] HAS_SUB_NPM=$has_sub_npm" + Write-Host "[DEBUG_LOG] HAS_SUB_MKDOCS=$has_sub_mkdocs" + Write-Host "[DEBUG_LOG] PRIMARY_STACK_SUGGESTION=$suggestion" + "HAS_ROOT_PACKAGE_JSON=$has_root_pkg" >> $Env:GITHUB_OUTPUT + "HAS_FRONTEND_PACKAGE_JSON=$has_frontend_pkg" >> $Env:GITHUB_OUTPUT + "HAS_ROOT_GO_MOD=$has_go_mod" >> $Env:GITHUB_OUTPUT + "HAS_ROOT_MAIN_GO=$has_main_go" >> $Env:GITHUB_OUTPUT + "HAS_ROOT_CMAKELISTS=$has_cmake" >> $Env:GITHUB_OUTPUT + "HAS_ROOT_MKDOCS=$has_mkdocs" >> $Env:GITHUB_OUTPUT + "HAS_SUB_NPM=$has_sub_npm" >> $Env:GITHUB_OUTPUT + "HAS_SUB_MKDOCS=$has_sub_mkdocs" >> $Env:GITHUB_OUTPUT + "PRIMARY_STACK_SUGGESTION=$suggestion" >> $Env:GITHUB_OUTPUT + if ($found.Count -gt 0) { "FOUND_FILES=$($found -join ',')" >> $Env:GITHUB_OUTPUT } else { "FOUND_FILES=" >> $Env:GITHUB_OUTPUT } +outputs: + OS: + description: "Runner OS (Linux/macOS/Windows)" + value: ${{ steps.meta_bash.outputs.OS || steps.meta_pwsh.outputs.OS }} + ARCH: + description: "CPU architecture (e.g., x86_64/amd64/arm64)" + value: ${{ steps.meta_bash.outputs.ARCH || steps.meta_pwsh.outputs.ARCH }} + DISTRO: + description: "Linux distro version when on Linux (e.g., 20.04/22.04/24.04); empty otherwise" + value: ${{ steps.linux.outputs.DISTRO }} + REF: + description: "The full Git ref" + value: ${{ steps.meta_bash.outputs.REF || steps.meta_pwsh.outputs.REF }} + BRANCH: + description: "Branch name when on branch refs; empty on tags" + value: ${{ steps.meta_bash.outputs.BRANCH || steps.meta_pwsh.outputs.BRANCH }} + TAG: + description: "Tag name when running on a tag ref; empty otherwise" + value: ${{ steps.meta_bash.outputs.TAG || steps.meta_pwsh.outputs.TAG }} + IS_TAG: + description: "1 if running on tag ref; 0 otherwise" + value: ${{ steps.meta_bash.outputs.IS_TAG || steps.meta_pwsh.outputs.IS_TAG }} + SHA: + description: "Full commit SHA" + value: ${{ steps.meta_bash.outputs.SHA || steps.meta_pwsh.outputs.SHA }} + SHORT_SHA: + description: "Short commit SHA (7 chars)" + value: ${{ steps.meta_bash.outputs.SHORT_SHA || steps.meta_pwsh.outputs.SHORT_SHA }} + REPO: + description: "owner/repo" + value: ${{ steps.meta_bash.outputs.REPO || steps.meta_pwsh.outputs.REPO }} + OWNER: + description: "Repository owner" + value: ${{ steps.meta_bash.outputs.OWNER || steps.meta_pwsh.outputs.OWNER }} + HAS_ROOT_PACKAGE_JSON: + description: "1 if package.json at root of working-directory" + value: ${{ steps.proj_bash.outputs.HAS_ROOT_PACKAGE_JSON || steps.proj_pwsh.outputs.HAS_ROOT_PACKAGE_JSON }} + HAS_FRONTEND_PACKAGE_JSON: + description: "1 if frontend/package.json under working-directory" + value: ${{ steps.proj_bash.outputs.HAS_FRONTEND_PACKAGE_JSON || steps.proj_pwsh.outputs.HAS_FRONTEND_PACKAGE_JSON }} + HAS_ROOT_GO_MOD: + description: "1 if go.mod at root of working-directory" + value: ${{ steps.proj_bash.outputs.HAS_ROOT_GO_MOD || steps.proj_pwsh.outputs.HAS_ROOT_GO_MOD }} + HAS_ROOT_MAIN_GO: + description: "1 if main.go at root of working-directory" + value: ${{ steps.proj_bash.outputs.HAS_ROOT_MAIN_GO || steps.proj_pwsh.outputs.HAS_ROOT_MAIN_GO }} + HAS_ROOT_CMAKELISTS: + description: "1 if CMakeLists.txt at root of working-directory" + value: ${{ steps.proj_bash.outputs.HAS_ROOT_CMAKELISTS || steps.proj_pwsh.outputs.HAS_ROOT_CMAKELISTS }} + HAS_ROOT_MKDOCS: + description: "1 if mkdocs.yml at root of working-directory" + value: ${{ steps.proj_bash.outputs.HAS_ROOT_MKDOCS || steps.proj_pwsh.outputs.HAS_ROOT_MKDOCS }} + HAS_SUB_NPM: + description: "1 if a nested package.json was found within depth 2" + value: ${{ steps.proj_bash.outputs.HAS_SUB_NPM || steps.proj_pwsh.outputs.HAS_SUB_NPM }} + HAS_SUB_MKDOCS: + description: "1 if a nested mkdocs.yml was found within depth 2" + value: ${{ steps.proj_bash.outputs.HAS_SUB_MKDOCS || steps.proj_pwsh.outputs.HAS_SUB_MKDOCS }} + PRIMARY_STACK_SUGGESTION: + description: "Computed primary stack suggestion (wails2/cpp/unknown)" + value: ${{ steps.proj_bash.outputs.PRIMARY_STACK_SUGGESTION || steps.proj_pwsh.outputs.PRIMARY_STACK_SUGGESTION }} + FOUND_FILES: + description: "Comma-separated summary of notable files found" + value: ${{ steps.proj_bash.outputs.FOUND_FILES || steps.proj_pwsh.outputs.FOUND_FILES }} diff --git a/actions/options/README.md b/actions/options/README.md new file mode 100644 index 0000000..6fb6305 --- /dev/null +++ b/actions/options/README.md @@ -0,0 +1,35 @@ +# Options (sub-action) + +Purpose +- Computes a `BUILD_OPTIONS` string for `wails build` based on inputs and discovery outputs. +- On Ubuntu 24.04, it appends `webkit2_41` tag if not already provided. + +Inputs +- `build-obfuscate` (default `false`) — Adds `-obfuscated`. +- `build-tags` (default `false`) — Space or comma separated. When not `false`, adds `-tags "..."`. +- `nsis` (default `false`) — Adds `-nsis` flag for Windows installers. +- `distro` (optional) — Pass the distro output from discovery; enables Ubuntu 24.04 special case. + +Outputs +- `BUILD_OPTIONS` — The computed string to pass to `wails build`. + +Usage +```yaml +- name: Discovery + id: disc + uses: snider/build/actions/discovery@v3 + +- name: Compute Options + id: opts + uses: snider/build/actions/options@v3 + with: + build-obfuscate: 'true' + build-tags: 'release' + nsis: 'false' + distro: ${{ steps.disc.outputs.DISTRO }} +# Later: ${{ steps.opts.outputs.BUILD_OPTIONS }} +``` + +Notes +- If you already specify tags and you are on Ubuntu 24.04, `webkit2_41` will be appended. +- If `build-tags` is left as `false` and distro is `24.04`, the action injects `-tags webkit2_41` automatically. diff --git a/actions/options/action.yml b/actions/options/action.yml new file mode 100644 index 0000000..0e4c358 --- /dev/null +++ b/actions/options/action.yml @@ -0,0 +1,73 @@ +name: "Options" +description: "Compute BUILD_OPTIONS string for builds based on inputs and discovery outputs" +inputs: + build-obfuscate: + description: "Obfuscate the build" + required: false + default: "false" + build-tags: + description: "Build tags to pass to Go compiler. Space and/or comma separated." + required: false + default: "false" + nsis: + description: "Include -nsis flag" + required: false + default: "false" + distro: + description: "Linux distro version (e.g., 24.04). Optional; if 24.04 and no explicit webkit tag provided, add webkit2_41" + required: false + default: "" + disable-webkit-auto-tag: + description: "When true, do not auto-append webkit2_41 for Ubuntu 24.04" + required: false + default: "false" +outputs: + BUILD_OPTIONS: + description: "Computed build options" + value: ${{ steps.compute.outputs.BUILD_OPTIONS }} +runs: + using: "composite" + steps: + - id: compute + name: Compute build options + shell: bash + env: + DISTRO: ${{ inputs.distro }} + DISABLE_WEBKIT: ${{ inputs.disable-webkit-auto-tag }} + run: | + set -euo pipefail + build_options="" + # Obfuscation + if ${{ inputs.build-obfuscate == 'true' }}; then + build_options+=" -obfuscated" + fi + # Normalize tags: accept commas and/or spaces, trim, de-duplicate + norm_tags="" + if [[ "${{ inputs.build-tags }}" != "false" ]]; then + raw="${{ inputs.build-tags }}" + raw="${raw//,/ }" + # collapse multiple spaces + raw=$(echo "$raw" | tr -s ' ') + declare -A seen=() + for t in $raw; do + if [[ -n "$t" && -z "${seen[$t]:-}" ]]; then + seen[$t]=1 + norm_tags+=" $t" + fi + done + fi + # Ubuntu 24.04 webkit auto-tag unless disabled or already present + if [[ "$DISTRO" == '24.04' && "${DISABLE_WEBKIT}" != 'true' ]]; then + case " $norm_tags " in + *" webkit2_41 "*) : ;; # already present + *) norm_tags+=" webkit2_41" ;; + esac + fi + if [[ -n "$norm_tags" ]]; then + build_options+=" -tags${norm_tags}" + fi + # NSIS + if ${{ inputs.nsis == 'true' }}; then + build_options+=" -nsis" + fi + echo "BUILD_OPTIONS=$build_options" >> "$GITHUB_OUTPUT" diff --git a/actions/package/README.md b/actions/package/README.md new file mode 100644 index 0000000..6ae4bce --- /dev/null +++ b/actions/package/README.md @@ -0,0 +1,37 @@ +# Package & Release (sub-action) + +Purpose +- Uploads build artifacts from standard Wails output directories and publishes a GitHub Release on tag builds. + +What it does +- Uses `actions/upload-artifact@v4` to upload files from `*/bin/` (Linux/macOS) and `*\\bin\\*` (Windows). +- If the workflow is running on a tag (`refs/tags/*`) and packaging is enabled, it attaches all `*/bin/*` files to a GitHub Release using `softprops/action-gh-release@v1`. +- Composes a descriptive artifact name using discovery metadata: `___`. +- Optionally writes a small `artifact_meta.json` (enabled by default) alongside the uploaded artifacts with discovery info for downstream automation. + +Inputs +- `package` (default `true`) — enable/disable uploads and release publishing. +- `build-name` (required) — base name used in the artifact label. +- Optional (auto-filled when using the root action/wrapper): `os`, `arch`, `tag`, `short-sha`, `ref`. +- `include-meta` (default `true`) — when `true`, writes `artifact_meta.json` containing `{ build_name, os, arch, ref, branch, tag, short_sha }` and includes it in both artifact uploads and releases. + +Usage +```yaml +- name: Package & Release + uses: snider/build/actions/package@v3 + with: + package: 'true' + build-name: 'wailsApp' + # When calling directly from a workflow, you may pass discovery data (optional) + os: ${{ steps.discovery.outputs.OS }} + arch: ${{ steps.discovery.outputs.ARCH }} + tag: ${{ steps.discovery.outputs.TAG }} + short-sha: ${{ steps.discovery.outputs.SHORT_SHA }} +``` + +Notes +- Artifact name examples: + - Branch build: `wailsApp_Ubuntu-22.04_amd64_ab12cd3` + - Tag build: `wailsApp_macos_arm64_v1.2.3` +- To publish a release, push a tag (e.g., `v1.2.3`). On non-tag builds, only artifacts are uploaded. +- Adjust paths in your own workflow if your build layout differs from `*/bin/*`. diff --git a/actions/package/action.yml b/actions/package/action.yml new file mode 100644 index 0000000..cbb47de --- /dev/null +++ b/actions/package/action.yml @@ -0,0 +1,157 @@ +name: "Package & Release" +description: "Uploads build artifacts and publishes GitHub Release on tag if enabled" +inputs: + package: + required: false + default: "true" + build-name: + required: true + os: + description: "OS name (optional, from discovery). Defaults to runner.os" + required: false + default: "" + arch: + description: "Architecture (optional, from discovery). Defaults to detected arch" + required: false + default: "" + tag: + description: "Git tag (optional, from discovery)." + required: false + default: "" + is-tag: + description: "Whether the ref is a tag (optional, from discovery)." + required: false + default: "" + short-sha: + description: "Short commit SHA (optional, from discovery)." + required: false + default: "" + ref: + description: "Git ref (optional, from discovery)." + required: false + default: "" + include-meta: + description: "Include artifact_meta.json with discovery metadata in the uploaded artifact" + required: false + default: "true" +runs: + using: "composite" + steps: + - name: Compute artifact name + id: meta + shell: bash + run: | + set -euo pipefail + OS_IN="${{ inputs.os }}" + ARCH_IN="${{ inputs.arch }}" + TAG_IN="${{ inputs.tag }}" + SHORT_SHA_IN="${{ inputs.short-sha }}" + # Resolve OS + if [ -z "$OS_IN" ]; then + OS_IN="${{ runner.os }}" + fi + # Resolve ARCH (prefer input) + if [ -z "$ARCH_IN" ]; then + # Try uname -m; fallback to envs on Windows if needed + if command -v uname >/dev/null 2>&1; then + M=$(uname -m || echo unknown) + else + M="$PROCESSOR_ARCHITECTURE" + fi + case "$M" in + x86_64|amd64) ARCH_IN="amd64";; + aarch64|arm64) ARCH_IN="arm64";; + armv7l) ARCH_IN="armv7";; + *) ARCH_IN="$M";; + esac + fi + # Resolve revision label (prefer tag) + if [ -n "$TAG_IN" ]; then + REV="$TAG_IN" + else + if [ -z "$SHORT_SHA_IN" ]; then + GHS="${GITHUB_SHA:-}" + SHORT_SHA_IN="${GHS:0:7}" + fi + REV="$SHORT_SHA_IN" + fi + NAME="${{ inputs.build-name }}_${OS_IN}_${ARCH_IN}_${REV}" + echo "ARTIFACT_NAME=$NAME" >> "$GITHUB_OUTPUT" + - name: Debug echo artifact name + shell: bash + run: | + echo "[DEBUG_LOG] ARTIFACT_NAME=${{ steps.meta.outputs.ARTIFACT_NAME }}" + - name: Write artifact_meta.json + if: inputs.package == 'true' && inputs.include-meta == 'true' + shell: bash + env: + IN_BUILD_NAME: ${{ inputs.build-name }} + IN_OS: ${{ inputs.os }} + IN_ARCH: ${{ inputs.arch }} + IN_REF: ${{ inputs.ref }} + IN_TAG: ${{ inputs.tag }} + IN_SHORT_SHA: ${{ inputs.short-sha }} + run: | + set -euo pipefail + build_name="$IN_BUILD_NAME" + os_val="$IN_OS" + arch_val="$IN_ARCH" + ref_val="$IN_REF" + tag_val="$IN_TAG" + short_sha="$IN_SHORT_SHA" + # Resolve OS from runner if not provided + if [ -z "$os_val" ]; then os_val="${RUNNER_OS:-}"; fi + # Resolve ARCH if not provided (best-effort) + if [ -z "$arch_val" ]; then + if command -v uname >/dev/null 2>&1; then + m=$(uname -m || echo unknown) + case "$m" in + x86_64|amd64) arch_val="amd64";; + aarch64|arm64) arch_val="arm64";; + armv7l) arch_val="armv7";; + *) arch_val="$m";; + esac + else + arch_val="${PROCESSOR_ARCHITECTURE:-}" + fi + fi + # Resolve REF/BRANCH + if [ -z "$ref_val" ]; then ref_val="${GITHUB_REF:-}"; fi + branch_val="" + case "$ref_val" in + refs/heads/*) branch_val="${ref_val#refs/heads/}" ;; + esac + # Resolve SHORT SHA + if [ -z "$short_sha" ]; then + ghsha="${GITHUB_SHA:-}" + short_sha="${ghsha:0:7}" + fi + cat > artifact_meta.json < inputs > defaults. +- Supported envs: + - `DENO_ENABLE` — `true`/`1`/`yes`/`on` explicitly enables Deno + - `DENO_BUILD` — full command to run (e.g., `deno task build`) + - `DENO_VERSION` — e.g., `v1.44.x` + - `DENO_WORKDIR` — working directory for Deno (default `.`) + - Pass-through: `DENO_AUTH_TOKEN`, `DENO_DIR`, proxies, etc. + +Behavior +- Calls sub-actions in order: `setup/go`, `setup/npm`, `setup/deno`, and optionally `setup/conan`. +- Resolves Deno configuration and sets up Deno only when enabled; runs the command when provided. + +Usage +```yaml +- name: Setup toolchains + uses: snider/build/actions/setup@v3 + with: + go-version: '1.23' + build-cache: 'true' + build-obfuscate: 'false' + wails-version: 'latest' + node-version: '18.x' + npm-working-directory: 'build/wails2' + npm-install: 'true' + env: + # Optional Deno via env + DENO_ENABLE: 'true' + DENO_VERSION: 'v1.44.x' + DENO_WORKDIR: 'frontend' + DENO_BUILD: 'deno task build' +``` + +Notes +- On macOS, `gon` is installed for later signing steps. No-op on other OSes. +- If you do not need Deno, leave envs and inputs empty — it will be skipped. +- If `wails-dev-build` is `true`, ensure `wails` is already available on PATH. diff --git a/actions/setup/action.yml b/actions/setup/action.yml new file mode 100644 index 0000000..0da2adf --- /dev/null +++ b/actions/setup/action.yml @@ -0,0 +1,69 @@ +name: "Setup toolchains" +description: "Orchestrates language/tool setup by delegating to sub-actions: setup/go, setup/npm, setup/deno, setup/conan" +inputs: + # Go/Wails + go-version: + required: false + default: "1.23" + build-cache: + required: false + default: "true" + build-obfuscate: + required: false + default: "false" + wails-version: + required: false + default: "latest" + wails-dev-build: + required: false + default: "false" + # Node/npm + node-version: + required: false + default: "18.x" + npm-working-directory: + required: false + default: "." + npm-install: + required: false + default: "true" + # Deno + deno-build: + required: false + default: "" + deno-version: + required: false + default: "v1.20.x" + deno-working-directory: + required: false + default: "." + # Conan (placeholder) + conan-enable: + required: false + default: "false" +runs: + using: "composite" + steps: + - name: Setup Go + uses: ./actions/setup/go + with: + go-version: ${{ inputs.go-version }} + build-cache: ${{ inputs.build-cache }} + build-obfuscate: ${{ inputs.build-obfuscate }} + wails-version: ${{ inputs.wails-version }} + wails-dev-build: ${{ inputs.wails-dev-build }} + - name: Setup Node/npm + uses: ./actions/setup/npm + with: + node-version: ${{ inputs.node-version }} + working-directory: ${{ inputs.npm-working-directory }} + install: ${{ inputs.npm-install }} + - name: Setup Deno (optional) + uses: ./actions/setup/deno + with: + deno-build: ${{ inputs.deno-build }} + deno-version: ${{ inputs.deno-version }} + deno-working-directory: ${{ inputs.deno-working-directory }} + - name: Setup Conan (optional) + if: inputs.conan-enable == 'true' + uses: ./actions/setup/conan diff --git a/actions/setup/conan/action.yml b/actions/setup/conan/action.yml new file mode 100644 index 0000000..fbaf542 --- /dev/null +++ b/actions/setup/conan/action.yml @@ -0,0 +1,25 @@ +name: "Setup Conan (placeholder)" +description: "Installs Conan package manager for C/C++ projects (future use)" +inputs: + version: + required: false + default: "latest" +runs: + using: "composite" + steps: + - name: Install Python (for pip) + if: runner.os == 'Windows' + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install Conan via pip + shell: bash + run: | + set -euo pipefail + if command -v pip3 >/dev/null 2>&1; then PIP=pip3; elif command -v pip >/dev/null 2>&1; then PIP=pip; else echo "pip not found" && exit 1; fi + if [ "${{ inputs.version }}" = "latest" ]; then + $PIP install --user conan + else + $PIP install --user conan=="${{ inputs.version }}" + fi + echo "Conan installed. Add ~/.local/bin to PATH if needed." diff --git a/actions/setup/deno/README.md b/actions/setup/deno/README.md new file mode 100644 index 0000000..ae2685a --- /dev/null +++ b/actions/setup/deno/README.md @@ -0,0 +1,50 @@ +# Setup Deno (sub-action) + +Purpose +- Optional Deno setup and command runner with ENV-first configuration. +- Can be used independently or via the `actions/setup` orchestrator. + +Behavior +- Resolves configuration from environment variables first, then falls back to inputs. +- Installs the requested Deno version on Linux/macOS/Windows. +- Runs the provided Deno command in the specified working directory when present. + +ENV-first precedence +- Environment variables > inputs > defaults. +- Supported envs: + - `DENO_ENABLE` — `true`/`1`/`yes`/`on` to explicitly enable Deno setup. + - `DENO_BUILD` — full command to run (e.g., `deno task build`, `deno run -A build.ts`). + - `DENO_VERSION` — e.g., `v1.44.x`. + - `DENO_WORKDIR` — working directory for Deno (default `.`). +- Pass-through (if set in your workflow env): `DENO_AUTH_TOKEN`, `DENO_DIR`, `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, etc. + +Inputs (fallbacks) +- `deno-build` (default `''`) +- `deno-version` (default `v1.20.x`) +- `deno-working-directory` (default `.`) + +Usage (direct) +```yaml +- name: Setup Deno (direct) + uses: snider/build/actions/setup/deno@v3 + with: + deno-version: 'v1.44.x' + deno-working-directory: 'frontend' + deno-build: 'deno task build' +``` + +Usage (ENV-first; recommended) +```yaml +- name: Configure Deno via env + run: | + echo "DENO_ENABLE=true" >> "$GITHUB_ENV" + echo "DENO_VERSION=v1.44.x" >> "$GITHUB_ENV" + echo "DENO_WORKDIR=frontend" >> "$GITHUB_ENV" + echo "DENO_BUILD=deno task build" >> "$GITHUB_ENV" +- name: Setup toolchains (orchestrator) + uses: snider/build/actions/setup@v3 +``` + +Notes +- If you do not set any of the envs or inputs, this action is a no-op. +- This sub-action is stack-agnostic and can be used for non-Wails projects as well. diff --git a/actions/setup/deno/action.yml b/actions/setup/deno/action.yml new file mode 100644 index 0000000..cdfd5d8 --- /dev/null +++ b/actions/setup/deno/action.yml @@ -0,0 +1,51 @@ +name: "Setup Deno (ENV-first)" +description: "Sets up Deno and optionally runs a Deno command; configuration comes from env first, then inputs" +inputs: + deno-build: + required: false + default: "" + deno-version: + required: false + default: "v1.20.x" + deno-working-directory: + required: false + default: "." +runs: + using: "composite" + steps: + - name: Resolve Deno configuration + id: deno_cfg + shell: bash + env: + INPUT_DENO_BUILD: ${{ inputs.deno-build }} + INPUT_DENO_VERSION: ${{ inputs.deno-version }} + INPUT_DENO_WORKDIR: ${{ inputs.deno-working-directory }} + run: | + set -euo pipefail + deno_enable="${DENO_ENABLE:-}" + deno_build="${DENO_BUILD:-}" + deno_version="${DENO_VERSION:-}" + deno_workdir="${DENO_WORKDIR:-}" + # Fallback to inputs if env not set + if [ -z "$deno_build" ]; then deno_build="$INPUT_DENO_BUILD"; fi + if [ -z "$deno_version" ]; then deno_version="$INPUT_DENO_VERSION"; fi + if [ -z "$deno_workdir" ]; then deno_workdir="$INPUT_DENO_WORKDIR"; fi + enabled=0 + case "${deno_enable,,}" in + true|1|yes|on) enabled=1;; + esac + if [ -n "$deno_build" ]; then enabled=1; fi + echo "ENABLED=$enabled" >> "$GITHUB_OUTPUT" + echo "BUILD=$deno_build" >> "$GITHUB_OUTPUT" + echo "VERSION=$deno_version" >> "$GITHUB_OUTPUT" + echo "WORKDIR=${deno_workdir:-.}" >> "$GITHUB_OUTPUT" + - name: Setup Deno + uses: denoland/setup-deno@v2 + if: steps.deno_cfg.outputs.ENABLED == '1' + with: + deno-version: ${{ steps.deno_cfg.outputs.VERSION }} + - name: Run Deno Command + if: steps.deno_cfg.outputs.BUILD != '' + shell: bash + working-directory: ${{ steps.deno_cfg.outputs.WORKDIR }} + run: ${{ steps.deno_cfg.outputs.BUILD }} diff --git a/actions/setup/go/action.yml b/actions/setup/go/action.yml new file mode 100644 index 0000000..dc4c8dc --- /dev/null +++ b/actions/setup/go/action.yml @@ -0,0 +1,43 @@ +name: "Setup Go (and Wails)" +description: "Sets up Go (with optional cache), installs Garble when obfuscating, installs Wails CLI unless wails-dev-build is true; installs gon on macOS" +inputs: + go-version: + required: false + default: "1.23" + build-cache: + required: false + default: "true" + build-obfuscate: + required: false + default: "false" + wails-version: + required: false + default: "latest" + wails-dev-build: + required: false + default: "false" +runs: + using: "composite" + steps: + - name: Setup GoLang + uses: actions/setup-go@v5 + if: inputs.wails-dev-build == 'false' + with: + check-latest: true + cache: ${{ inputs.build-cache }} + cache-dependency-path: 'go.sum' + go-version: ${{ inputs.go-version }} + - name: Install Garble + if: inputs.build-obfuscate == 'true' + run: go install mvdan.cc/garble@latest + shell: bash + - run: go version + shell: bash + - name: Install Wails + if: inputs.wails-dev-build == 'false' + run: go install github.com/wailsapp/wails/v2/cmd/wails@${{ inputs.wails-version }} + shell: bash + - name: Install macOS deps (gon) + if: runner.os == 'macOS' + run: brew install mitchellh/gon/gon + shell: bash diff --git a/actions/setup/npm/README.md b/actions/setup/npm/README.md new file mode 100644 index 0000000..896748b --- /dev/null +++ b/actions/setup/npm/README.md @@ -0,0 +1,24 @@ +# Setup Node and npm (sub-action) + +Purpose +- Installs Node.js and optionally installs dependencies with npm. +- Auto-detects where to install: current `working-directory` or `frontend/` fallback. + +Inputs +- `node-version` (default `18.x`) — Node.js version to install. +- `working-directory` (default `.`) — base path to check for `package.json`. +- `install` (default `true`) — when `true`, runs `npm ci` (falls back to `npm install`). + +Usage +```yaml +- name: Setup Node/npm + uses: snider/build/actions/setup/npm@v3 + with: + node-version: '20.x' + working-directory: 'build/wails2' # or '.' + install: 'true' +``` + +Notes +- If no `package.json` exists in the working dir, the action will try `frontend/`. +- Disable installs with `install: 'false'` if you manage dependencies yourself. diff --git a/actions/setup/npm/action.yml b/actions/setup/npm/action.yml new file mode 100644 index 0000000..28cad84 --- /dev/null +++ b/actions/setup/npm/action.yml @@ -0,0 +1,42 @@ +name: "Setup Node and npm" +description: "Installs Node.js and optionally installs dependencies (npm ci) in a detected project directory" +inputs: + node-version: + required: false + default: "18.x" + working-directory: + required: false + default: "." + install: + required: false + default: "true" +runs: + using: "composite" + steps: + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + check-latest: true + - name: Show node and npm versions + shell: bash + run: | + node -v + npm -v + - name: Install npm dependencies (auto-detect path) + if: inputs.install == 'true' + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + set -euo pipefail + install_dir="${{ inputs.working-directory }}" + if [ -f "package.json" ]; then + echo "Installing npm deps in $PWD" + npm ci || npm install + elif [ -f "frontend/package.json" ]; then + echo "Installing npm deps in frontend/" + cd frontend + npm ci || npm install + else + echo "No package.json found in working-directory or frontend/. Skipping npm install." + fi diff --git a/actions/sign/README.md b/actions/sign/README.md new file mode 100644 index 0000000..91c8b89 --- /dev/null +++ b/actions/sign/README.md @@ -0,0 +1,56 @@ +# Sign (sub-action) + +Purpose +- Unified signing step for macOS and Windows. +- macOS: imports certificates, signs the `.app` with `gon`, zips the `.app`, builds a `.pkg` (signed or unsigned), and notarizes on tag builds. +- Windows: signs the `.exe` and the NSIS installer using a provided PFX (base64) and password. + +When it runs +- macOS: meaningful on `macOS` runners. Most operations only run when `sign != 'false'` AND the ref is a tag (`refs/tags/*`). +- Windows: meaningful on `Windows` runners. Runs when `sign != 'false'` AND `sign-windows-cert` is provided. + +Inputs (union of previous per-OS signers) +- `sign` (default `false`) — enable/disable signing. +- `app-working-directory` (default `.`) +- `build-name` (required) +- macOS: + - `sign-macos-apple-password` — app-specific password for Apple ID (`gon` uses this) + - `sign-macos-app-id` — Developer ID Application subject + - `sign-macos-app-cert` — Base64-encoded `.p12` + - `sign-macos-app-cert-password` — Password for the Application certificate + - `sign-macos-installer-id` — Developer ID Installer subject (optional) + - `sign-macos-installer-cert` — Base64-encoded `.p12` (Installer) + - `sign-macos-installer-cert-password` — Password for the Installer certificate +- Windows: + - `sign-windows-cert` — Base64-encoded PFX contents + - `sign-windows-cert-password` — Password for the PFX + +Required project files (macOS) +- `build/darwin/gon-sign.json` — config for signing the `.app` +- `build/darwin/gon-notarize.json` — config for notarizing `.pkg` and `.app.zip` + +Usage +```yaml +- name: Sign artifacts + uses: snider/build/actions/sign@v3 + with: + sign: 'true' + app-working-directory: '.' + build-name: 'wailsApp' + # macOS + sign-macos-apple-password: ${{ secrets.APPLE_PASSWORD }} + sign-macos-app-id: ${{ secrets.MACOS_DEVELOPER_CERT_ID }} + sign-macos-app-cert: ${{ secrets.MACOS_DEVELOPER_CERT }} + sign-macos-app-cert-password: ${{ secrets.MACOS_DEVELOPER_CERT_PASSWORD }} + sign-macos-installer-id: ${{ secrets.MACOS_INSTALLER_CERT_ID }} + sign-macos-installer-cert: ${{ secrets.MACOS_INSTALLER_CERT }} + sign-macos-installer-cert-password: ${{ secrets.MACOS_INSTALLER_CERT_PASSWORD }} + # Windows + sign-windows-cert: ${{ secrets.WIN_CERT_PFX_BASE64 }} + sign-windows-cert-password: ${{ secrets.WIN_CERT_PASSWORD }} +``` + +Notes +- On macOS, `gon` must be installed (`actions/setup/go` installs it automatically on macOS). +- The `.app` zip is produced regardless of signing to ease distribution. +- Installer `.pkg` is signed when `sign == 'true'` and an installer ID is provided; otherwise an unsigned pkg is built on tags. diff --git a/actions/sign/action.yml b/actions/sign/action.yml new file mode 100644 index 0000000..213cf3e --- /dev/null +++ b/actions/sign/action.yml @@ -0,0 +1,109 @@ +name: "Sign" +description: "Unified signing for macOS and Windows (conditional by OS); notarizes on tags for macOS" +inputs: + sign: + required: false + default: "false" + app-working-directory: + required: false + default: "." + build-name: + required: true + # macOS + sign-macos-apple-password: + required: false + default: '' + sign-macos-app-id: + required: false + default: '' + sign-macos-app-cert: + required: false + default: '' + sign-macos-app-cert-password: + required: false + default: '' + sign-macos-installer-id: + required: false + default: '' + sign-macos-installer-cert: + required: false + default: '' + sign-macos-installer-cert-password: + required: false + default: '' + # Windows + sign-windows-cert: + required: false + default: '' + sign-windows-cert-password: + required: false + default: '' +runs: + using: "composite" + steps: + # macOS signing flow + - name: Import Code-Signing Certificates for macOS + if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') + uses: Apple-Actions/import-codesign-certs@v1 + with: + keychain-password: ${{ inputs.sign-macos-apple-password }} + p12-file-base64: ${{ inputs.sign-macos-app-cert }} + p12-password: ${{ inputs.sign-macos-app-cert-password }} + - name: Import Code-Signing Certificates for macOS Installer + if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') + uses: Apple-Actions/import-codesign-certs@v1 + with: + keychain-password: ${{ inputs.sign-macos-apple-password }} + p12-file-base64: ${{ inputs.sign-macos-installer-cert }} + p12-password: ${{ inputs.sign-macos-installer-cert-password }} + create-keychain: false + - name: Sign macOS .app with gon + if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') + shell: bash + working-directory: ${{ inputs.app-working-directory }} + env: + APPLE_PASSWORD: ${{ inputs.sign-macos-apple-password }} + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Build .app zip file + if: runner.os == 'macOS' + working-directory: ${{ inputs.app-working-directory }} + shell: bash + run: | + ditto -c -k --keepParent ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.app ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.app.zip + - name: Build Installer (signed) + if: runner.os == 'macOS' && inputs.sign != 'false' && inputs.sign-macos-installer-id != '' && startsWith(github.ref, 'refs/tags/') + shell: bash + working-directory: ${{ inputs.app-working-directory }} + run: | + productbuild --sign '${{ inputs.sign-macos-installer-id }}' --component ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.app /Applications ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.pkg + - name: Build Installer (unsigned) + if: runner.os == 'macOS' && inputs.sign-macos-installer-id == '' && startsWith(github.ref, 'refs/tags/') + shell: bash + working-directory: ${{ inputs.app-working-directory }} + run: | + productbuild --component ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.app /Applications ${{ inputs.app-working-directory }}/build/bin/${{ inputs.build-name }}.pkg + - name: Notarize Installer and zip with gon + if: runner.os == 'macOS' && inputs.sign != 'false' && startsWith(github.ref, 'refs/tags/') + shell: bash + working-directory: ${{ inputs.app-working-directory }} + env: + APPLE_PASSWORD: ${{ inputs.sign-macos-apple-password }} + run: | + gon -log-level=info ${{ inputs.app-working-directory }}/build/darwin/gon-notarize.json + + # Windows signing flow + - name: Sign Windows binaries + shell: powershell + if: runner.os == 'Windows' && inputs.sign != 'false' && inputs.sign-windows-cert != '' + working-directory: ${{ inputs.app-working-directory }} + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ inputs.sign-windows-cert }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ inputs.sign-windows-cert-password }}' .\build\bin\${{ inputs.build-name }}.exe + echo "Signing Installer" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ inputs.sign-windows-cert-password }}' .\build\bin\${{ inputs.build-name }}-amd64-installer.exe diff --git a/docs/GOLANG_BUILDER_PLAN.md b/docs/GOLANG_BUILDER_PLAN.md new file mode 100644 index 0000000..748c8f3 --- /dev/null +++ b/docs/GOLANG_BUILDER_PLAN.md @@ -0,0 +1,560 @@ +# GoLang Binary Builder Plan + +## Overview + +This document outlines a plan to refactor the build action to use **GoTask (go-task/task)** as the build orchestrator instead of inline shell scripts in GitHub Actions. This approach provides: + +- **Cross-platform consistency**: Taskfiles work identically on Linux, macOS, and Windows +- **Local development parity**: Developers can run the same tasks locally that run in CI +- **Cleaner separation**: GitHub Actions handle CI concerns (checkout, caching, artifacts); GoTask handles build logic +- **Extensibility**: Easy to add new stacks (Wails3, pure Go CLI, Docker, etc.) + +## Primary Goals + +1. **Wails 2 builds** - Full support (current functionality preserved) +2. **Wails 3 builds** - New support for Wails v3 architecture + +## Stretch Goals + +3. Pure Go CLI/binary builds (no Wails) +4. Docker image builds +5. C++ builds (via Conan/CMake) +6. PHP builds (Composer-based) + +--- + +## Architecture + +### Current v3 Architecture (Shell-based) + +``` +action.yml (root) +├── actions/discovery/action.yml # Detect OS/ARCH/project-type +├── actions/action.yml # Directory orchestrator (stack router) +│ └── actions/build/wails2/action.yml # Wails2 full pipeline +│ ├── actions/options/action.yml # Compute build flags +│ ├── actions/setup/action.yml # Install toolchains +│ ├── actions/build/wails2/build/ # Run wails build +│ └── actions/sign/action.yml # Code signing +└── actions/package/action.yml # Artifacts & releases +``` + +### Proposed GoTask Architecture + +``` +action.yml (root) +├── actions/discovery/action.yml # Keep: Detect OS/ARCH/project-type +├── actions/setup/gotask/action.yml # NEW: Install go-task +├── actions/action.yml # Orchestrator runs: task build:$STACK +│ └── Taskfile.yml # Master taskfile includes stack taskfiles +│ ├── tasks/wails2.yml # Wails 2 build tasks +│ ├── tasks/wails3.yml # Wails 3 build tasks +│ ├── tasks/go-cli.yml # Pure Go CLI builds +│ └── tasks/common.yml # Shared tasks (setup, sign, package) +└── actions/package/action.yml # Keep: Artifacts & releases +``` + +--- + +## Taskfile Structure + +### Root Taskfile.yml + +```yaml +version: '3' + +includes: + common: ./tasks/common.yml + wails2: ./tasks/wails2.yml + wails3: ./tasks/wails3.yml + go: ./tasks/go-cli.yml + +vars: + BUILD_NAME: '{{.BUILD_NAME | default "app"}}' + BUILD_PLATFORM: '{{.BUILD_PLATFORM | default "linux/amd64"}}' + BUILD_OUTPUT: '{{.BUILD_OUTPUT | default "build/bin"}}' + +tasks: + default: + desc: "Show available tasks" + cmds: + - task --list + + build: + desc: "Auto-detect stack and build" + cmds: + - task: "build:{{.STACK | default \"wails2\"}}" + vars: + STACK: + sh: | + if [ -f "wails.json" ]; then + if grep -q '"wailsVersion": "v3' wails.json 2>/dev/null; then + echo "wails3" + else + echo "wails2" + fi + elif [ -f "go.mod" ] && [ -f "main.go" ]; then + echo "go" + else + echo "wails2" + fi + + build:wails2: + desc: "Build Wails 2 application" + cmds: + - task: wails2:build + + build:wails3: + desc: "Build Wails 3 application" + cmds: + - task: wails3:build + + build:go: + desc: "Build Go CLI/binary" + cmds: + - task: go:build +``` + +### tasks/wails2.yml + +```yaml +version: '3' + +vars: + WAILS_VERSION: '{{.WAILS_VERSION | default "latest"}}' + WEBVIEW2: '{{.WEBVIEW2 | default "download"}}' + BUILD_TAGS: '{{.BUILD_TAGS | default ""}}' + OBFUSCATE: '{{.OBFUSCATE | default "false"}}' + NSIS: '{{.NSIS | default "false"}}' + +tasks: + setup: + desc: "Install Wails v2 CLI" + cmds: + - go install github.com/wailsapp/wails/v2/cmd/wails@{{.WAILS_VERSION}} + status: + - which wails + + setup:garble: + desc: "Install Garble for obfuscation" + cmds: + - go install mvdan.cc/garble@latest + status: + - which garble + + build: + desc: "Build Wails 2 application" + deps: [setup] + cmds: + - | + BUILD_OPTS="" + {{if eq .OBFUSCATE "true"}}BUILD_OPTS="$BUILD_OPTS -obfuscated"{{end}} + {{if .BUILD_TAGS}}BUILD_OPTS="$BUILD_OPTS -tags {{.BUILD_TAGS}}"{{end}} + {{if eq .NSIS "true"}}BUILD_OPTS="$BUILD_OPTS -nsis"{{end}} + wails build --platform {{.BUILD_PLATFORM}} -webview2 {{.WEBVIEW2}} -o {{.BUILD_NAME}} $BUILD_OPTS + generates: + - "{{.BUILD_OUTPUT}}/*" + + build:all: + desc: "Build for all platforms" + cmds: + - task: build + vars: { BUILD_PLATFORM: "linux/amd64" } + - task: build + vars: { BUILD_PLATFORM: "windows/amd64" } + - task: build + vars: { BUILD_PLATFORM: "darwin/universal" } +``` + +### tasks/wails3.yml + +```yaml +version: '3' + +vars: + WAILS3_VERSION: '{{.WAILS3_VERSION | default "latest"}}' + +tasks: + setup: + desc: "Install Wails v3 CLI" + cmds: + - go install github.com/wailsapp/wails/v3/cmd/wails3@{{.WAILS3_VERSION}} + status: + - which wails3 + + build: + desc: "Build Wails 3 application" + deps: [setup] + cmds: + - | + # Wails 3 uses a different build command structure + # Platform is specified differently in v3 + GOOS={{.GOOS}} GOARCH={{.GOARCH}} wails3 build -o {{.BUILD_NAME}} + vars: + GOOS: + sh: echo "{{.BUILD_PLATFORM}}" | cut -d'/' -f1 | sed 's/darwin/darwin/;s/linux/linux/;s/windows/windows/' + GOARCH: + sh: echo "{{.BUILD_PLATFORM}}" | cut -d'/' -f2 + generates: + - "{{.BUILD_OUTPUT}}/*" + + dev: + desc: "Run Wails 3 in dev mode" + deps: [setup] + cmds: + - wails3 dev +``` + +### tasks/common.yml + +```yaml +version: '3' + +tasks: + setup:go: + desc: "Verify Go installation" + cmds: + - go version + preconditions: + - sh: which go + msg: "Go is not installed" + + setup:node: + desc: "Install frontend dependencies" + dir: "{{.FRONTEND_DIR | default \"frontend\"}}" + cmds: + - npm ci --prefer-offline + sources: + - package-lock.json + generates: + - node_modules/**/* + status: + - test -d node_modules + + clean: + desc: "Clean build artifacts" + cmds: + - rm -rf build/bin/* + - rm -rf dist/* + ignore_error: true + + lint: + desc: "Run linters" + cmds: + - go vet ./... + - | + if which golangci-lint >/dev/null 2>&1; then + golangci-lint run + fi + + test: + desc: "Run tests" + cmds: + - go test -v ./... + + sign:macos: + desc: "Sign macOS application" + platforms: [darwin] + cmds: + - | + if [ -n "$SIGN_MACOS_APP_ID" ]; then + codesign --deep --force --options runtime \ + --sign "$SIGN_MACOS_APP_ID" \ + "{{.BUILD_OUTPUT}}/{{.BUILD_NAME}}.app" + else + echo "Skipping signing: SIGN_MACOS_APP_ID not set" + fi + + sign:windows: + desc: "Sign Windows executable" + platforms: [windows] + cmds: + - | + if [ -n "$SIGN_WINDOWS_CERT" ]; then + # Windows signing via signtool + echo "Windows signing configured" + else + echo "Skipping signing: SIGN_WINDOWS_CERT not set" + fi + + package: + desc: "Create distributable package" + cmds: + - | + OS=$(echo "{{.BUILD_PLATFORM}}" | cut -d'/' -f1) + ARCH=$(echo "{{.BUILD_PLATFORM}}" | cut -d'/' -f2) + ARTIFACT_NAME="{{.BUILD_NAME}}_${OS}_${ARCH}" + + mkdir -p dist + case $OS in + darwin) + ditto -c -k --keepParent "{{.BUILD_OUTPUT}}/{{.BUILD_NAME}}.app" "dist/${ARTIFACT_NAME}.zip" + ;; + windows) + zip -r "dist/${ARTIFACT_NAME}.zip" "{{.BUILD_OUTPUT}}/{{.BUILD_NAME}}.exe" + ;; + linux) + tar -czvf "dist/${ARTIFACT_NAME}.tar.gz" -C "{{.BUILD_OUTPUT}}" "{{.BUILD_NAME}}" + ;; + esac +``` + +--- + +## GitHub Action Integration + +### actions/setup/gotask/action.yml + +```yaml +name: "Setup GoTask" +description: "Install go-task/task CLI" +inputs: + version: + description: "Task version to install" + required: false + default: "latest" +runs: + using: "composite" + steps: + - name: Install Task (Linux/macOS) + if: runner.os != 'Windows' + shell: bash + run: | + sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Install Task (Windows) + if: runner.os == 'Windows' + shell: powershell + run: | + choco install go-task -y + + - name: Verify Task installation + shell: bash + run: task --version +``` + +### Modified actions/action.yml (Orchestrator) + +```yaml +name: "Directory Orchestrator" +description: "Runs GoTask with detected stack" +inputs: + build: + required: false + default: "true" + build-name: + required: true + build-platform: + required: false + default: "darwin/universal" + app-working-directory: + required: false + default: "." + STACK: + required: false + default: "" + +runs: + using: "composite" + steps: + - name: Setup GoTask + uses: ./actions/setup/gotask + + - name: Determine stack + id: stack + shell: bash + working-directory: ${{ inputs.app-working-directory }} + run: | + if [ -n "${{ inputs.STACK }}" ]; then + echo "STACK=${{ inputs.STACK }}" >> "$GITHUB_OUTPUT" + elif [ -f "wails.json" ]; then + if grep -q '"wailsVersion": "v3' wails.json 2>/dev/null; then + echo "STACK=wails3" >> "$GITHUB_OUTPUT" + else + echo "STACK=wails2" >> "$GITHUB_OUTPUT" + fi + elif [ -f "go.mod" ]; then + echo "STACK=go" >> "$GITHUB_OUTPUT" + else + echo "STACK=wails2" >> "$GITHUB_OUTPUT" + fi + + - name: Run build task + if: inputs.build == 'true' + shell: bash + working-directory: ${{ inputs.app-working-directory }} + env: + BUILD_NAME: ${{ inputs.build-name }} + BUILD_PLATFORM: ${{ inputs.build-platform }} + run: | + task build:${{ steps.stack.outputs.STACK }} + +outputs: + SELECTED_STACK: + description: "Stack that was built" + value: ${{ steps.stack.outputs.STACK }} +``` + +--- + +## Wails 2 vs Wails 3 Detection + +The system will auto-detect Wails version by examining `wails.json`: + +| Indicator | Wails 2 | Wails 3 | +|-----------|---------|---------| +| `wails.json` schema | Has `name`, `frontend:install` | Has `wailsVersion: "v3..."` | +| CLI command | `wails build` | `wails3 build` | +| Output structure | `build/bin/{name}.app` | Different structure | +| Go module | `github.com/wailsapp/wails/v2` | `github.com/wailsapp/wails/v3` | + +### Detection Logic + +```bash +# In Taskfile or action +if [ -f "wails.json" ]; then + if grep -q '"wailsVersion":\s*"v3' wails.json; then + STACK="wails3" + else + STACK="wails2" + fi +elif grep -q 'github.com/wailsapp/wails/v3' go.mod 2>/dev/null; then + STACK="wails3" +elif grep -q 'github.com/wailsapp/wails/v2' go.mod 2>/dev/null; then + STACK="wails2" +else + STACK="go" # fallback to pure Go +fi +``` + +--- + +## Implementation Phases + +### Phase 1: Foundation (Primary Goal) + +1. **Add GoTask setup action** (`actions/setup/gotask/action.yml`) +2. **Create root Taskfile.yml** with basic structure +3. **Migrate Wails 2 build logic** to `tasks/wails2.yml` +4. **Update orchestrator** to call `task build:wails2` +5. **Preserve all existing inputs/outputs** for backward compatibility + +### Phase 2: Wails 3 Support (Primary Goal) + +1. **Create `tasks/wails3.yml`** with Wails 3 build commands +2. **Add Wails 3 detection** to discovery and Taskfile +3. **Create TDD fixture** for Wails 3 (`tdd/wails3-root/`) +4. **Add CI tests** for Wails 3 builds + +### Phase 3: Refactor Remaining Shell Logic + +1. **Move signing logic** to `tasks/common.yml` (sign:macos, sign:windows) +2. **Move npm setup** to common tasks +3. **Simplify GitHub Actions** to thin wrappers around `task` commands + +### Phase 4: Stretch Goals + +1. **Pure Go CLI** (`tasks/go-cli.yml`) +2. **Docker builds** (`tasks/docker.yml`) +3. **C++ builds** (`tasks/cpp.yml`) +4. **PHP builds** (`tasks/php.yml`) + +--- + +## File Changes Summary + +### New Files + +| File | Description | +|------|-------------| +| `Taskfile.yml` | Root taskfile with includes | +| `tasks/common.yml` | Shared tasks (setup, sign, package) | +| `tasks/wails2.yml` | Wails 2 build tasks | +| `tasks/wails3.yml` | Wails 3 build tasks | +| `tasks/go-cli.yml` | Pure Go CLI build tasks | +| `actions/setup/gotask/action.yml` | GoTask installation action | +| `tdd/wails3-root/` | Wails 3 test fixture | + +### Modified Files + +| File | Changes | +|------|---------| +| `actions/action.yml` | Add GoTask setup, call `task build:$STACK` | +| `actions/discovery/action.yml` | Add Wails 3 detection | +| `.github/workflows/ci.yml` | Add Wails 3 build tests | + +### Deprecated (Phase 3) + +| File | Status | +|------|--------| +| `actions/build/wails2/build/action.yml` | Replaced by `task wails2:build` | +| `actions/options/action.yml` | Logic moves to Taskfile vars | + +--- + +## Environment Variables + +All existing `WAILS_*` environment variables remain supported: + +| Variable | Taskfile Var | Default | +|----------|--------------|---------| +| `WAILS_VERSION` | `WAILS_VERSION` | `latest` | +| `WAILS_GO_VERSION` | N/A (Go setup) | `1.23` | +| `WAILS_BUILD_TAGS` | `BUILD_TAGS` | `""` | +| `WAILS_OBFUSCATE` | `OBFUSCATE` | `false` | +| `WAILS_NSIS` | `NSIS` | `false` | +| `WAILS_WEBVIEW2` | `WEBVIEW2` | `download` | + +New for Wails 3: + +| Variable | Taskfile Var | Default | +|----------|--------------|---------| +| `WAILS3_VERSION` | `WAILS3_VERSION` | `latest` | + +--- + +## Local Development Usage + +With GoTask, developers can run the same builds locally: + +```bash +# Install task (one-time) +brew install go-task # macOS +# or: sh -c "$(curl --location https://taskfile.dev/install.sh)" + +# Run builds +task build # Auto-detect stack +task build:wails2 # Explicit Wails 2 +task build:wails3 # Explicit Wails 3 +task wails2:build:all # Build all platforms + +# Other tasks +task clean # Clean build artifacts +task lint # Run linters +task test # Run tests +``` + +--- + +## Backward Compatibility + +The action maintains full backward compatibility: + +1. **Same inputs** - All existing action inputs work identically +2. **Same outputs** - Same artifacts, same naming conventions +3. **Same ENV mapping** - `WAILS_*` variables work as before +4. **Gradual migration** - Shell scripts coexist with Taskfiles during transition + +--- + +## Next Steps + +1. [ ] Create `actions/setup/gotask/action.yml` +2. [ ] Create `Taskfile.yml` and `tasks/` directory +3. [ ] Implement `tasks/wails2.yml` matching current behavior +4. [ ] Update orchestrator to use GoTask +5. [ ] Add Wails 3 detection and `tasks/wails3.yml` +6. [ ] Create Wails 3 TDD fixture +7. [ ] Update CI workflow with new tests +8. [ ] Document new local development workflow diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e376450 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,15 @@ +# Documentation + +Welcome to the documentation for `snider/build@v3`. This repository contains a modular build action for multi-stack projects, primarily focused on Wails v2 but designed to be extensible. + +## Contents + +- [Getting Started](getting-started.md) - Learn how to use the action in your workflows. +- [Configuration](configuration.md) - Detailed reference for inputs and environment variables. +- [Architecture](architecture.md) - Understand the modular design and sub-actions. +- [Stacks](stacks.md) - Specific information about supported stacks (Wails v2, Deno, etc.). + +## Quick Links + +- [Root README](../README.md) +- [Action Definition](../action.yml) diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..373764d --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,32 @@ +# Architecture + +`snider/build@v3` is designed as a modular, multi-stack build system. + +## Overview + +The root action acts as a gateway. It performs discovery and then delegates the heavy lifting to specialized sub-actions. + +1. **Discovery**: Scans the repository to identify the OS, architecture, and project type (stack). +2. **Orchestration**: Decides which specific build pipeline (stack) to run. +3. **Setup**: Installs dependencies (Go, Node, Deno, etc.) based on the selected stack or configuration. +4. **Build**: Compiles the application. +5. **Sign**: Signs the binaries (if configured). +6. **Package**: Archives the output and uploads it as an artifact (and release asset on tags). + +## Directory Structure + +- `actions/` + - `discovery/`: Detects environment and project metadata. + - `options/`: Computes build options (e.g., tags). + - `setup/`: Orchestrates dependency installation. + - `go/`, `npm/`, `deno/`, `conan/`: Specific setup actions. + - `build/`: Contains stack-specific build logic. + - `wails2/`: Logic for Wails v2 builds. + - `sign/`: Unified signing for macOS and Windows. + - `package/`: Handles artifact upload and releases. + +## Design Principles + +- **Modular**: Each step is a separate composite action. You can use them individually if needed. +- **Smart Defaults**: The system tries to guess the right thing to do (Auto-Stack, Auto-Setup) but allows full override. +- **CI Gating**: The repository includes self-tests that run sub-actions to ensure stability. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..83d1c39 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,58 @@ +# Configuration + +This document covers the inputs and configuration options for the `snider/build@v3` action. + +## Action Inputs + +These inputs are defined in `action.yml` and are passed to the `with` block in your workflow. + +| Input | Description | Required | Default | +| :--- | :--- | :--- | :--- | +| `build-name` | The name of the binary or app bundle. | **Yes** | - | +| `build-platform` | Target platform (e.g., `linux/amd64`, `windows/amd64`, `darwin/universal`). | No | `darwin/universal` | +| `build` | Whether to run the build step. | No | `true` | +| `package` | Upload artifacts and publish release on tags. | No | `true` | +| `sign` | Enable platform signing (if configured). | No | `false` | +| `app-working-directory` | Root directory of the app being built. | No | `.` | +| `AUTO_STACK` | Allow auto-selection of stack based on discovery. | No | `true` | +| `AUTO_SETUP` | Allow sub-setup enabling based on env toggles. | No | `true` | +| `STACK` | Explicitly override the stack (e.g., `wails2`). | No | `""` | + +## Environment Variables + +The action uses environment variables for certain configurations, particularly for sub-actions like Deno setup. + +### Deno Configuration + +You can configure Deno usage via environment variables. These take precedence over inputs in the setup phase. + +| Variable | Description | Example | +| :--- | :--- | :--- | +| `DENO_ENABLE` | Explicitly enable Deno setup. | `true`, `1`, `on` | +| `DENO_BUILD` | Full command to run for Deno build. | `deno task build` | +| `DENO_VERSION` | Version of Deno to install. | `v1.44.x` | +| `DENO_WORKDIR` | Working directory for Deno command. | `frontend` | + +### Example with Environment Variables + +```yaml +steps: + - uses: actions/checkout@v4 + - uses: snider/build@v3 + env: + DENO_ENABLE: 'true' + DENO_VERSION: 'v1.44.x' + DENO_WORKDIR: 'frontend' + DENO_BUILD: 'deno task build' + with: + build-name: wailsApp + build-platform: linux/amd64 +``` + +## Orchestration Control + +You can control how the action delegates tasks. + +- **Auto-Stack**: By default (`AUTO_STACK: true`), the action tries to detect if you are building a Wails v2 app, etc., and uses the appropriate sub-action. +- **Auto-Setup**: By default (`AUTO_SETUP: true`), the orchestrator looks at environment variables to decide if it should set up Go, Node, Deno, etc. +- **Manual Stack**: Set `STACK: wails2` to force the Wails v2 pipeline, ignoring auto-detection. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..6a02d81 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,60 @@ +# Getting Started + +This guide will help you get started with the `snider/build@v3` action. + +## Basic Usage + +The simplest way to use this action is to let it auto-detect your project type. + +```yaml +steps: + - uses: actions/checkout@v4 + - uses: snider/build@v3 + with: + build-name: myApp + build-platform: linux/amd64 +``` + +This configuration will: +1. Detect your project stack (e.g., Wails v2). +2. Set up the necessary environment (Go, Node.js, etc.). +3. Build your application. +4. Package the artifacts. +5. Upload artifacts (and publish release on tags). + +## Common Examples + +### Build Only (No Packaging) + +If you only want to verify the build without uploading artifacts: + +```yaml +- uses: snider/build@v3 + with: + build-name: myApp + build-platform: linux/amd64 + package: false +``` + +### macOS Build + +```yaml +- uses: snider/build@v3 + with: + build-name: myApp + build-platform: darwin/universal +``` + +### Windows Build + +```yaml +- uses: snider/build@v3 + with: + build-name: myApp + build-platform: windows/amd64 +``` + +## Next Steps + +- Check [Configuration](configuration.md) for more advanced options. +- Read about [Stacks](stacks.md) for specific stack details. diff --git a/docs/stacks.md b/docs/stacks.md new file mode 100644 index 0000000..fc94cff --- /dev/null +++ b/docs/stacks.md @@ -0,0 +1,34 @@ +# Stacks + +This action supports multiple stacks, with Wails v2 being the primary one currently. + +## Wails v2 + +This is the default stack. It handles the complete lifecycle of a Wails v2 application. + +- **Detection**: Automatically detected if `wails.json` is present (logic in `discovery`). +- **Setup**: Installs Go, Node.js, and the Wails CLI. +- **Build**: Runs `wails build` with appropriate flags for the target platform. +- **Signing**: Supports macOS code signing and notarization (requires secrets) and Windows signing. + +For detailed documentation on Wails v2 inputs and usage, refer to: +- [Wails v2 Wrapper README](../actions/build/wails2/README.md) +- [Wails Build Sub-action README](../actions/build/wails2/build/README.md) + +### macOS Code Signing + +Detailed instructions for setting up macOS code signing (Certificate, Notarization) can be found in the [Wails v2 README](../actions/build/wails2/README.md). + +## Deno + +Deno support is integrated into the setup phase and can be used alongside other stacks or independently. + +- **Enable**: Set `DENO_ENABLE: true` or define `DENO_BUILD`. +- **Usage**: Useful for running frontend build steps before the main application build. + +For more details, see [Deno Setup README](../actions/setup/deno/README.md). + +## Future Stacks + +- **Wails v3**: Planned support once upstream stabilizes. +- **C++**: Placeholder support exists via `conan` setup action. diff --git a/tdd/cpp-root/CMakeLists.txt b/tdd/cpp-root/CMakeLists.txt new file mode 100644 index 0000000..c91b06a --- /dev/null +++ b/tdd/cpp-root/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) +project(CppRootFixture) + +add_executable(dummy main.cpp) diff --git a/tdd/docs/mkdocs.yml b/tdd/docs/mkdocs.yml new file mode 100644 index 0000000..55a6dd0 --- /dev/null +++ b/tdd/docs/mkdocs.yml @@ -0,0 +1,3 @@ +site_name: Docs Fixture +nav: + - Home: index.md diff --git a/tdd/node-only/package.json b/tdd/node-only/package.json new file mode 100644 index 0000000..04770db --- /dev/null +++ b/tdd/node-only/package.json @@ -0,0 +1,5 @@ +{ + "name": "node-only-fixture", + "version": "0.0.1", + "private": true +} diff --git a/tdd/wails2-root/README.md b/tdd/wails2-root/README.md new file mode 100644 index 0000000..1ae2f67 --- /dev/null +++ b/tdd/wails2-root/README.md @@ -0,0 +1,35 @@ +# Build Directory + +The build directory is used to house all the build files and assets for your application. + +The structure is: + +* bin - Output directory +* darwin - macOS specific files +* windows - Windows specific files + +## Mac + +The `darwin` directory holds files specific to Mac builds. +These may be customised and used as part of the build. To return these files to the default state, simply delete them +and +build with `wails build`. + +The directory contains the following files: + +- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`. +- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`. + +## Windows + +The `windows` directory contains the manifest and rc files used when building with `wails build`. +These may be customised for your application. To return these files to the default state, simply delete them and +build with `wails build`. + +- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to + use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file + will be created using the `appicon.png` file in the build directory. +- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`. +- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer, + as well as the application itself (right click the exe -> properties -> details) +- `wails.exe.manifest` - The main application manifest file. \ No newline at end of file diff --git a/tdd/wails2-root/app.go b/tdd/wails2-root/app.go new file mode 100644 index 0000000..af53038 --- /dev/null +++ b/tdd/wails2-root/app.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "fmt" +) + +// App struct +type App struct { + ctx context.Context +} + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} diff --git a/tdd/wails2-root/appicon.png b/tdd/wails2-root/appicon.png new file mode 100644 index 0000000..63617fe Binary files /dev/null and b/tdd/wails2-root/appicon.png differ diff --git a/tdd/wails2-root/build/darwin/Info.dev.plist b/tdd/wails2-root/build/darwin/Info.dev.plist new file mode 100644 index 0000000..04727c2 --- /dev/null +++ b/tdd/wails2-root/build/darwin/Info.dev.plist @@ -0,0 +1,68 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.Name}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + {{if .Info.FileAssociations}} + CFBundleDocumentTypes + + {{range .Info.FileAssociations}} + + CFBundleTypeExtensions + + {{.Ext}} + + CFBundleTypeName + {{.Name}} + CFBundleTypeRole + {{.Role}} + CFBundleTypeIconFile + {{.IconName}} + + {{end}} + + {{end}} + {{if .Info.Protocols}} + CFBundleURLTypes + + {{range .Info.Protocols}} + + CFBundleURLName + com.wails.{{.Scheme}} + CFBundleURLSchemes + + {{.Scheme}} + + CFBundleTypeRole + {{.Role}} + + {{end}} + + {{end}} + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + diff --git a/tdd/wails2-root/build/darwin/Info.plist b/tdd/wails2-root/build/darwin/Info.plist new file mode 100644 index 0000000..19cc937 --- /dev/null +++ b/tdd/wails2-root/build/darwin/Info.plist @@ -0,0 +1,63 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.Name}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + {{if .Info.FileAssociations}} + CFBundleDocumentTypes + + {{range .Info.FileAssociations}} + + CFBundleTypeExtensions + + {{.Ext}} + + CFBundleTypeName + {{.Name}} + CFBundleTypeRole + {{.Role}} + CFBundleTypeIconFile + {{.IconName}} + + {{end}} + + {{end}} + {{if .Info.Protocols}} + CFBundleURLTypes + + {{range .Info.Protocols}} + + CFBundleURLName + com.wails.{{.Scheme}} + CFBundleURLSchemes + + {{.Scheme}} + + CFBundleTypeRole + {{.Role}} + + {{end}} + + {{end}} + + diff --git a/tdd/wails2-root/build/windows/icon.ico b/tdd/wails2-root/build/windows/icon.ico new file mode 100644 index 0000000..f334798 Binary files /dev/null and b/tdd/wails2-root/build/windows/icon.ico differ diff --git a/tdd/wails2-root/build/windows/info.json b/tdd/wails2-root/build/windows/info.json new file mode 100644 index 0000000..9727946 --- /dev/null +++ b/tdd/wails2-root/build/windows/info.json @@ -0,0 +1,15 @@ +{ + "fixed": { + "file_version": "{{.Info.ProductVersion}}" + }, + "info": { + "0000": { + "ProductVersion": "{{.Info.ProductVersion}}", + "CompanyName": "{{.Info.CompanyName}}", + "FileDescription": "{{.Info.ProductName}}", + "LegalCopyright": "{{.Info.Copyright}}", + "ProductName": "{{.Info.ProductName}}", + "Comments": "{{.Info.Comments}}" + } + } +} \ No newline at end of file diff --git a/tdd/wails2-root/build/windows/installer/project.nsi b/tdd/wails2-root/build/windows/installer/project.nsi new file mode 100644 index 0000000..654ae2e --- /dev/null +++ b/tdd/wails2-root/build/windows/installer/project.nsi @@ -0,0 +1,114 @@ +Unicode true + +#### +## Please note: Template replacements don't work in this file. They are provided with default defines like +## mentioned underneath. +## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo. +## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually +## from outside of Wails for debugging and development of the installer. +## +## For development first make a wails nsis build to populate the "wails_tools.nsh": +## > wails build --target windows/amd64 --nsis +## Then you can call makensis on this file with specifying the path to your binary: +## For a AMD64 only installer: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe +## For a ARM64 only installer: +## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe +## For a installer with both architectures: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe +#### +## The following information is taken from the ProjectInfo file, but they can be overwritten here. +#### +## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}" +## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}" +## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}" +## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}" +## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}" +### +## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" +## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +#### +## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html +#### +## Include the wails tools +#### +!include "wails_tools.nsh" + +# The version information for this two must consist of 4 parts +VIProductVersion "${INFO_PRODUCTVERSION}.0" +VIFileVersion "${INFO_PRODUCTVERSION}.0" + +VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" +VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" +VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" +VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" + +# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware +ManifestDPIAware true + +!include "MUI.nsh" + +!define MUI_ICON "..\icon.ico" +!define MUI_UNICON "..\icon.ico" +# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 +!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps +!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. + +!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. +# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer +!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. +!insertmacro MUI_PAGE_INSTFILES # Installing page. +!insertmacro MUI_PAGE_FINISH # Finished installation page. + +!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page + +!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer + +## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 +#!uninstfinalize 'signtool --file "%1"' +#!finalize 'signtool --file "%1"' + +Name "${INFO_PRODUCTNAME}" +OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. +InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). +ShowInstDetails show # This will always show the installation details. + +Function .onInit + !insertmacro wails.checkArchitecture +FunctionEnd + +Section + !insertmacro wails.setShellContext + + !insertmacro wails.webview2runtime + + SetOutPath $INSTDIR + + !insertmacro wails.files + + CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + + !insertmacro wails.associateFiles + !insertmacro wails.associateCustomProtocols + + !insertmacro wails.writeUninstaller +SectionEnd + +Section "uninstall" + !insertmacro wails.setShellContext + + RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath + + RMDir /r $INSTDIR + + Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" + Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" + + !insertmacro wails.unassociateFiles + !insertmacro wails.unassociateCustomProtocols + + !insertmacro wails.deleteUninstaller +SectionEnd diff --git a/tdd/wails2-root/build/windows/installer/wails_tools.nsh b/tdd/wails2-root/build/windows/installer/wails_tools.nsh new file mode 100644 index 0000000..f9c0f88 --- /dev/null +++ b/tdd/wails2-root/build/windows/installer/wails_tools.nsh @@ -0,0 +1,249 @@ +# DO NOT EDIT - Generated automatically by `wails build` + +!include "x64.nsh" +!include "WinVer.nsh" +!include "FileFunc.nsh" + +!ifndef INFO_PROJECTNAME + !define INFO_PROJECTNAME "{{.Name}}" +!endif +!ifndef INFO_COMPANYNAME + !define INFO_COMPANYNAME "{{.Info.CompanyName}}" +!endif +!ifndef INFO_PRODUCTNAME + !define INFO_PRODUCTNAME "{{.Info.ProductName}}" +!endif +!ifndef INFO_PRODUCTVERSION + !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}" +!endif +!ifndef INFO_COPYRIGHT + !define INFO_COPYRIGHT "{{.Info.Copyright}}" +!endif +!ifndef PRODUCT_EXECUTABLE + !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" +!endif +!ifndef UNINST_KEY_NAME + !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +!endif +!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" + +!ifndef REQUEST_EXECUTION_LEVEL + !define REQUEST_EXECUTION_LEVEL "admin" +!endif + +RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" + +!ifdef ARG_WAILS_AMD64_BINARY + !define SUPPORTS_AMD64 +!endif + +!ifdef ARG_WAILS_ARM64_BINARY + !define SUPPORTS_ARM64 +!endif + +!ifdef SUPPORTS_AMD64 + !ifdef SUPPORTS_ARM64 + !define ARCH "amd64_arm64" + !else + !define ARCH "amd64" + !endif +!else + !ifdef SUPPORTS_ARM64 + !define ARCH "arm64" + !else + !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" + !endif +!endif + +!macro wails.checkArchitecture + !ifndef WAILS_WIN10_REQUIRED + !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." + !endif + + !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED + !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" + !endif + + ${If} ${AtLeastWin10} + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + Goto ok + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + Goto ok + ${EndIf} + !endif + + IfSilent silentArch notSilentArch + silentArch: + SetErrorLevel 65 + Abort + notSilentArch: + MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" + Quit + ${else} + IfSilent silentWin notSilentWin + silentWin: + SetErrorLevel 64 + Abort + notSilentWin: + MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" + Quit + ${EndIf} + + ok: +!macroend + +!macro wails.files + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" + ${EndIf} + !endif +!macroend + +!macro wails.writeUninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + SetRegView 64 + WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" + WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" +!macroend + +!macro wails.deleteUninstaller + Delete "$INSTDIR\uninstall.exe" + + SetRegView 64 + DeleteRegKey HKLM "${UNINST_KEY}" +!macroend + +!macro wails.setShellContext + ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" + SetShellVarContext all + ${else} + SetShellVarContext current + ${EndIf} +!macroend + +# Install webview2 by launching the bootstrapper +# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment +!macro wails.webview2runtime + !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT + !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" + !endif + + SetRegView 64 + # If the admin key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + + ${If} ${REQUEST_EXECUTION_LEVEL} == "user" + # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + ${EndIf} + + SetDetailsPrint both + DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" + SetDetailsPrint listonly + + InitPluginsDir + CreateDirectory "$pluginsdir\webview2bootstrapper" + SetOutPath "$pluginsdir\webview2bootstrapper" + File "tmp\MicrosoftEdgeWebview2Setup.exe" + ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' + + SetDetailsPrint both + ok: +!macroend + +# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b +!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" + + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" + + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` +!macroend + +!macro APP_UNASSOCIATE EXT FILECLASS + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" + + DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` +!macroend + +!macro wails.associateFiles + ; Create file associations + {{range .Info.FileAssociations}} + !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" + + File "..\{{.IconName}}.ico" + {{end}} +!macroend + +!macro wails.unassociateFiles + ; Delete app associations + {{range .Info.FileAssociations}} + !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}" + + Delete "$INSTDIR\{{.IconName}}.ico" + {{end}} +!macroend + +!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND + DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}" +!macroend + +!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL + DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" +!macroend + +!macro wails.associateCustomProtocols + ; Create custom protocols associations + {{range .Info.Protocols}} + !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" + + {{end}} +!macroend + +!macro wails.unassociateCustomProtocols + ; Delete app custom protocol associations + {{range .Info.Protocols}} + !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}" + {{end}} +!macroend diff --git a/tdd/wails2-root/build/windows/wails.exe.manifest b/tdd/wails2-root/build/windows/wails.exe.manifest new file mode 100644 index 0000000..17e1a23 --- /dev/null +++ b/tdd/wails2-root/build/windows/wails.exe.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + \ No newline at end of file diff --git a/tdd/wails2-root/frontend/index.html b/tdd/wails2-root/frontend/index.html new file mode 100644 index 0000000..bc06d9e --- /dev/null +++ b/tdd/wails2-root/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + wails + + +
+ + + diff --git a/tdd/wails2-root/frontend/package-lock.json b/tdd/wails2-root/frontend/package-lock.json new file mode 100644 index 0000000..dc4c123 --- /dev/null +++ b/tdd/wails2-root/frontend/package-lock.json @@ -0,0 +1,653 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "devDependencies": { + "vite": "^3.0.7" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/vite": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz", + "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.15.9", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } +} diff --git a/tdd/wails2-root/frontend/package.json b/tdd/wails2-root/frontend/package.json new file mode 100644 index 0000000..a1b6f8e --- /dev/null +++ b/tdd/wails2-root/frontend/package.json @@ -0,0 +1,13 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "vite": "^3.0.7" + } +} \ No newline at end of file diff --git a/tdd/wails2-root/frontend/package.json.md5 b/tdd/wails2-root/frontend/package.json.md5 new file mode 100644 index 0000000..d4671a1 --- /dev/null +++ b/tdd/wails2-root/frontend/package.json.md5 @@ -0,0 +1 @@ +5fbf12469d224a93954efecb5886e8a6 \ No newline at end of file diff --git a/tdd/wails2-root/frontend/src/app.css b/tdd/wails2-root/frontend/src/app.css new file mode 100644 index 0000000..59d06f6 --- /dev/null +++ b/tdd/wails2-root/frontend/src/app.css @@ -0,0 +1,54 @@ +#logo { + display: block; + width: 50%; + height: 50%; + margin: auto; + padding: 10% 0 0; + background-position: center; + background-repeat: no-repeat; + background-size: 100% 100%; + background-origin: content-box; +} + +.result { + height: 20px; + line-height: 20px; + margin: 1.5rem auto; +} + +.input-box .btn { + width: 60px; + height: 30px; + line-height: 30px; + border-radius: 3px; + border: none; + margin: 0 0 0 20px; + padding: 0 8px; + cursor: pointer; +} + +.input-box .btn:hover { + background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); + color: #333333; +} + +.input-box .input { + border: none; + border-radius: 3px; + outline: none; + height: 30px; + line-height: 30px; + padding: 0 10px; + background-color: rgba(240, 240, 240, 1); + -webkit-font-smoothing: antialiased; +} + +.input-box .input:hover { + border: none; + background-color: rgba(255, 255, 255, 1); +} + +.input-box .input:focus { + border: none; + background-color: rgba(255, 255, 255, 1); +} \ No newline at end of file diff --git a/tdd/wails2-root/frontend/src/assets/fonts/OFL.txt b/tdd/wails2-root/frontend/src/assets/fonts/OFL.txt new file mode 100644 index 0000000..9cac04c --- /dev/null +++ b/tdd/wails2-root/frontend/src/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com), + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/tdd/wails2-root/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/tdd/wails2-root/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 new file mode 100644 index 0000000..2f9cc59 Binary files /dev/null and b/tdd/wails2-root/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ diff --git a/tdd/wails2-root/frontend/src/assets/images/logo-universal.png b/tdd/wails2-root/frontend/src/assets/images/logo-universal.png new file mode 100644 index 0000000..d63303b Binary files /dev/null and b/tdd/wails2-root/frontend/src/assets/images/logo-universal.png differ diff --git a/tdd/wails2-root/frontend/src/main.js b/tdd/wails2-root/frontend/src/main.js new file mode 100644 index 0000000..4ad5a2c --- /dev/null +++ b/tdd/wails2-root/frontend/src/main.js @@ -0,0 +1,43 @@ +import './style.css'; +import './app.css'; + +import logo from './assets/images/logo-universal.png'; +import {Greet} from '../wailsjs/go/main/App'; + +document.querySelector('#app').innerHTML = ` + +
Please enter your name below 👇
+
+ + +
+ +`; +document.getElementById('logo').src = logo; + +let nameElement = document.getElementById("name"); +nameElement.focus(); +let resultElement = document.getElementById("result"); + +// Setup the greet function +window.greet = function () { + // Get name + let name = nameElement.value; + + // Check if the input is empty + if (name === "") return; + + // Call App.Greet(name) + try { + Greet(name) + .then((result) => { + // Update result with data back from App.Greet() + resultElement.innerText = result; + }) + .catch((err) => { + console.error(err); + }); + } catch (err) { + console.error(err); + } +}; diff --git a/tdd/wails2-root/frontend/src/style.css b/tdd/wails2-root/frontend/src/style.css new file mode 100644 index 0000000..3940d6c --- /dev/null +++ b/tdd/wails2-root/frontend/src/style.css @@ -0,0 +1,26 @@ +html { + background-color: rgba(27, 38, 54, 1); + text-align: center; + color: white; +} + +body { + margin: 0; + color: white; + font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", + "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; +} + +@font-face { + font-family: "Nunito"; + font-style: normal; + font-weight: 400; + src: local(""), + url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2"); +} + +#app { + height: 100vh; + text-align: center; +} diff --git a/tdd/wails2-root/frontend/wailsjs/go/main/App.d.ts b/tdd/wails2-root/frontend/wailsjs/go/main/App.d.ts new file mode 100644 index 0000000..02a3bb9 --- /dev/null +++ b/tdd/wails2-root/frontend/wailsjs/go/main/App.d.ts @@ -0,0 +1,4 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +export function Greet(arg1:string):Promise; diff --git a/tdd/wails2-root/frontend/wailsjs/go/main/App.js b/tdd/wails2-root/frontend/wailsjs/go/main/App.js new file mode 100644 index 0000000..c71ae77 --- /dev/null +++ b/tdd/wails2-root/frontend/wailsjs/go/main/App.js @@ -0,0 +1,7 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +export function Greet(arg1) { + return window['go']['main']['App']['Greet'](arg1); +} diff --git a/tdd/wails2-root/frontend/wailsjs/runtime/package.json b/tdd/wails2-root/frontend/wailsjs/runtime/package.json new file mode 100644 index 0000000..1e7c8a5 --- /dev/null +++ b/tdd/wails2-root/frontend/wailsjs/runtime/package.json @@ -0,0 +1,24 @@ +{ + "name": "@wailsapp/runtime", + "version": "2.0.0", + "description": "Wails Javascript runtime library", + "main": "runtime.js", + "types": "runtime.d.ts", + "scripts": { + }, + "repository": { + "type": "git", + "url": "git+https://github.com/wailsapp/wails.git" + }, + "keywords": [ + "Wails", + "Javascript", + "Go" + ], + "author": "Lea Anthony ", + "license": "MIT", + "bugs": { + "url": "https://github.com/wailsapp/wails/issues" + }, + "homepage": "https://github.com/wailsapp/wails#readme" +} diff --git a/tdd/wails2-root/frontend/wailsjs/runtime/runtime.d.ts b/tdd/wails2-root/frontend/wailsjs/runtime/runtime.d.ts new file mode 100644 index 0000000..94778df --- /dev/null +++ b/tdd/wails2-root/frontend/wailsjs/runtime/runtime.d.ts @@ -0,0 +1,249 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +export interface Position { + x: number; + y: number; +} + +export interface Size { + w: number; + h: number; +} + +export interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} + +// Environment information such as platform, buildtype, ... +export interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} + +// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit) +// emits the given event. Optional data may be passed with the event. +// This will trigger any event listeners. +export function EventsEmit(eventName: string, ...data: any): void; + +// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name. +export function EventsOn(eventName: string, callback: (...data: any) => void): () => void; + +// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple) +// sets up a listener for the given event name, but will only trigger a given number times. +export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void; + +// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce) +// sets up a listener for the given event name, but will only trigger once. +export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void; + +// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff) +// unregisters the listener for the given event name. +export function EventsOff(eventName: string, ...additionalEventNames: string[]): void; + +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all listeners. +export function EventsOffAll(): void; + +// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) +// logs the given message as a raw message +export function LogPrint(message: string): void; + +// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace) +// logs the given message at the `trace` log level. +export function LogTrace(message: string): void; + +// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug) +// logs the given message at the `debug` log level. +export function LogDebug(message: string): void; + +// [LogError](https://wails.io/docs/reference/runtime/log#logerror) +// logs the given message at the `error` log level. +export function LogError(message: string): void; + +// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal) +// logs the given message at the `fatal` log level. +// The application will quit after calling this method. +export function LogFatal(message: string): void; + +// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo) +// logs the given message at the `info` log level. +export function LogInfo(message: string): void; + +// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning) +// logs the given message at the `warning` log level. +export function LogWarning(message: string): void; + +// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload) +// Forces a reload by the main application as well as connected browsers. +export function WindowReload(): void; + +// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp) +// Reloads the application frontend. +export function WindowReloadApp(): void; + +// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop) +// Sets the window AlwaysOnTop or not on top. +export function WindowSetAlwaysOnTop(b: boolean): void; + +// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme) +// *Windows only* +// Sets window theme to system default (dark/light). +export function WindowSetSystemDefaultTheme(): void; + +// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme) +// *Windows only* +// Sets window to light theme. +export function WindowSetLightTheme(): void; + +// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme) +// *Windows only* +// Sets window to dark theme. +export function WindowSetDarkTheme(): void; + +// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter) +// Centers the window on the monitor the window is currently on. +export function WindowCenter(): void; + +// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle) +// Sets the text in the window title bar. +export function WindowSetTitle(title: string): void; + +// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen) +// Makes the window full screen. +export function WindowFullscreen(): void; + +// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen) +// Restores the previous window dimensions and position prior to full screen. +export function WindowUnfullscreen(): void; + +// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen) +// Returns the state of the window, i.e. whether the window is in full screen mode or not. +export function WindowIsFullscreen(): Promise; + +// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) +// Sets the width and height of the window. +export function WindowSetSize(width: number, height: number): Promise; + +// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) +// Gets the width and height of the window. +export function WindowGetSize(): Promise; + +// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize) +// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions. +// Setting a size of 0,0 will disable this constraint. +export function WindowSetMaxSize(width: number, height: number): void; + +// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize) +// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions. +// Setting a size of 0,0 will disable this constraint. +export function WindowSetMinSize(width: number, height: number): void; + +// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition) +// Sets the window position relative to the monitor the window is currently on. +export function WindowSetPosition(x: number, y: number): void; + +// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition) +// Gets the window position relative to the monitor the window is currently on. +export function WindowGetPosition(): Promise; + +// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide) +// Hides the window. +export function WindowHide(): void; + +// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow) +// Shows the window, if it is currently hidden. +export function WindowShow(): void; + +// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise) +// Maximises the window to fill the screen. +export function WindowMaximise(): void; + +// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise) +// Toggles between Maximised and UnMaximised. +export function WindowToggleMaximise(): void; + +// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise) +// Restores the window to the dimensions and position prior to maximising. +export function WindowUnmaximise(): void; + +// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised) +// Returns the state of the window, i.e. whether the window is maximised or not. +export function WindowIsMaximised(): Promise; + +// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise) +// Minimises the window. +export function WindowMinimise(): void; + +// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise) +// Restores the window to the dimensions and position prior to minimising. +export function WindowUnminimise(): void; + +// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised) +// Returns the state of the window, i.e. whether the window is minimised or not. +export function WindowIsMinimised(): Promise; + +// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal) +// Returns the state of the window, i.e. whether the window is normal or not. +export function WindowIsNormal(): Promise; + +// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour) +// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels. +export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void; + +// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall) +// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system. +export function ScreenGetAll(): Promise; + +// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl) +// Opens the given URL in the system browser. +export function BrowserOpenURL(url: string): void; + +// [Environment](https://wails.io/docs/reference/runtime/intro#environment) +// Returns information about the environment +export function Environment(): Promise; + +// [Quit](https://wails.io/docs/reference/runtime/intro#quit) +// Quits the application. +export function Quit(): void; + +// [Hide](https://wails.io/docs/reference/runtime/intro#hide) +// Hides the application. +export function Hide(): void; + +// [Show](https://wails.io/docs/reference/runtime/intro#show) +// Shows the application. +export function Show(): void; + +// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext) +// Returns the current text stored on clipboard +export function ClipboardGetText(): Promise; + +// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext) +// Sets a text on the clipboard +export function ClipboardSetText(text: string): Promise; + +// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop) +// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. +export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void + +// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff) +// OnFileDropOff removes the drag and drop listeners and handlers. +export function OnFileDropOff() :void + +// Check if the file path resolver is available +export function CanResolveFilePaths(): boolean; + +// Resolves file paths for an array of files +export function ResolveFilePaths(files: File[]): void \ No newline at end of file diff --git a/tdd/wails2-root/frontend/wailsjs/runtime/runtime.js b/tdd/wails2-root/frontend/wailsjs/runtime/runtime.js new file mode 100644 index 0000000..623397b --- /dev/null +++ b/tdd/wails2-root/frontend/wailsjs/runtime/runtime.js @@ -0,0 +1,238 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +export function LogPrint(message) { + window.runtime.LogPrint(message); +} + +export function LogTrace(message) { + window.runtime.LogTrace(message); +} + +export function LogDebug(message) { + window.runtime.LogDebug(message); +} + +export function LogInfo(message) { + window.runtime.LogInfo(message); +} + +export function LogWarning(message) { + window.runtime.LogWarning(message); +} + +export function LogError(message) { + window.runtime.LogError(message); +} + +export function LogFatal(message) { + window.runtime.LogFatal(message); +} + +export function EventsOnMultiple(eventName, callback, maxCallbacks) { + return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks); +} + +export function EventsOn(eventName, callback) { + return EventsOnMultiple(eventName, callback, -1); +} + +export function EventsOff(eventName, ...additionalEventNames) { + return window.runtime.EventsOff(eventName, ...additionalEventNames); +} + +export function EventsOnce(eventName, callback) { + return EventsOnMultiple(eventName, callback, 1); +} + +export function EventsEmit(eventName) { + let args = [eventName].slice.call(arguments); + return window.runtime.EventsEmit.apply(null, args); +} + +export function WindowReload() { + window.runtime.WindowReload(); +} + +export function WindowReloadApp() { + window.runtime.WindowReloadApp(); +} + +export function WindowSetAlwaysOnTop(b) { + window.runtime.WindowSetAlwaysOnTop(b); +} + +export function WindowSetSystemDefaultTheme() { + window.runtime.WindowSetSystemDefaultTheme(); +} + +export function WindowSetLightTheme() { + window.runtime.WindowSetLightTheme(); +} + +export function WindowSetDarkTheme() { + window.runtime.WindowSetDarkTheme(); +} + +export function WindowCenter() { + window.runtime.WindowCenter(); +} + +export function WindowSetTitle(title) { + window.runtime.WindowSetTitle(title); +} + +export function WindowFullscreen() { + window.runtime.WindowFullscreen(); +} + +export function WindowUnfullscreen() { + window.runtime.WindowUnfullscreen(); +} + +export function WindowIsFullscreen() { + return window.runtime.WindowIsFullscreen(); +} + +export function WindowGetSize() { + return window.runtime.WindowGetSize(); +} + +export function WindowSetSize(width, height) { + window.runtime.WindowSetSize(width, height); +} + +export function WindowSetMaxSize(width, height) { + window.runtime.WindowSetMaxSize(width, height); +} + +export function WindowSetMinSize(width, height) { + window.runtime.WindowSetMinSize(width, height); +} + +export function WindowSetPosition(x, y) { + window.runtime.WindowSetPosition(x, y); +} + +export function WindowGetPosition() { + return window.runtime.WindowGetPosition(); +} + +export function WindowHide() { + window.runtime.WindowHide(); +} + +export function WindowShow() { + window.runtime.WindowShow(); +} + +export function WindowMaximise() { + window.runtime.WindowMaximise(); +} + +export function WindowToggleMaximise() { + window.runtime.WindowToggleMaximise(); +} + +export function WindowUnmaximise() { + window.runtime.WindowUnmaximise(); +} + +export function WindowIsMaximised() { + return window.runtime.WindowIsMaximised(); +} + +export function WindowMinimise() { + window.runtime.WindowMinimise(); +} + +export function WindowUnminimise() { + window.runtime.WindowUnminimise(); +} + +export function WindowSetBackgroundColour(R, G, B, A) { + window.runtime.WindowSetBackgroundColour(R, G, B, A); +} + +export function ScreenGetAll() { + return window.runtime.ScreenGetAll(); +} + +export function WindowIsMinimised() { + return window.runtime.WindowIsMinimised(); +} + +export function WindowIsNormal() { + return window.runtime.WindowIsNormal(); +} + +export function BrowserOpenURL(url) { + window.runtime.BrowserOpenURL(url); +} + +export function Environment() { + return window.runtime.Environment(); +} + +export function Quit() { + window.runtime.Quit(); +} + +export function Hide() { + window.runtime.Hide(); +} + +export function Show() { + window.runtime.Show(); +} + +export function ClipboardGetText() { + return window.runtime.ClipboardGetText(); +} + +export function ClipboardSetText(text) { + return window.runtime.ClipboardSetText(text); +} + +/** + * Callback for OnFileDrop returns a slice of file path strings when a drop is finished. + * + * @export + * @callback OnFileDropCallback + * @param {number} x - x coordinate of the drop + * @param {number} y - y coordinate of the drop + * @param {string[]} paths - A list of file paths. + */ + +/** + * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. + * + * @export + * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished. + * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target) + */ +export function OnFileDrop(callback, useDropTarget) { + return window.runtime.OnFileDrop(callback, useDropTarget); +} + +/** + * OnFileDropOff removes the drag and drop listeners and handlers. + */ +export function OnFileDropOff() { + return window.runtime.OnFileDropOff(); +} + +export function CanResolveFilePaths() { + return window.runtime.CanResolveFilePaths(); +} + +export function ResolveFilePaths(files) { + return window.runtime.ResolveFilePaths(files); +} \ No newline at end of file diff --git a/tdd/wails2-root/go.mod b/tdd/wails2-root/go.mod new file mode 100644 index 0000000..9c4d3a9 --- /dev/null +++ b/tdd/wails2-root/go.mod @@ -0,0 +1,39 @@ +module wails + +go 1.23 + +toolchain go1.23.5 + +require github.com/wailsapp/wails/v2 v2.9.2 + +require ( + github.com/bep/debounce v1.2.1 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/labstack/echo/v4 v4.10.2 // indirect + github.com/labstack/gommon v0.4.0 // indirect + github.com/leaanthony/go-ansi-parser v1.6.0 // indirect + github.com/leaanthony/gosod v1.0.3 // indirect + github.com/leaanthony/slicer v1.6.0 // indirect + github.com/leaanthony/u v1.1.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/samber/lo v1.38.1 // indirect + github.com/tkrajina/go-reflector v0.5.6 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + github.com/wailsapp/go-webview2 v1.0.16 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect +) + +// replace github.com/wailsapp/wails/v2 v2.9.2 => C:\Users\snide\go\pkg\mod diff --git a/tdd/wails2-root/go.sum b/tdd/wails2-root/go.sum new file mode 100644 index 0000000..6ed0576 --- /dev/null +++ b/tdd/wails2-root/go.sum @@ -0,0 +1,94 @@ +github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= +github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= +github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= +github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= +github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= +github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg= +github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= +github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= +github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= +github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= +github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= +github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= +github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= +github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE= +github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/wailsapp/go-webview2 v1.0.16 h1:wffnvnkkLvhRex/aOrA3R7FP7rkvOqL/bir1br7BekU= +github.com/wailsapp/go-webview2 v1.0.16/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= +github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= +github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= +github.com/wailsapp/wails/v2 v2.9.2 h1:Xb5YRTos1w5N7DTMyYegWaGukCP2fIaX9WF21kPPF2k= +github.com/wailsapp/wails/v2 v2.9.2/go.mod h1:uehvlCwJSFcBq7rMCGfk4rxca67QQGsbg5Nm4m9UnBs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tdd/wails2-root/main.go b/tdd/wails2-root/main.go new file mode 100644 index 0000000..7a4f495 --- /dev/null +++ b/tdd/wails2-root/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} diff --git a/tdd/wails2-root/wails.json b/tdd/wails2-root/wails.json new file mode 100644 index 0000000..6174bbb --- /dev/null +++ b/tdd/wails2-root/wails.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://wails.io/schemas/config.v2.json", + "name": "wails", + "outputfilename": "wails", + "frontend:install": "npm install", + "frontend:build": "npm run build", + "frontend:dev:watcher": "npm run dev", + "frontend:dev:serverUrl": "auto", + "author": { + "name": "Snider", + "email": "snider@lt.hn" + } +}