Upgrade to Go 1.27 and enhance AxonHTA features (#118) #74
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # AxonASP Server - Build Packages Workflow | |
| # | |
| # Copyright (C) 2026 G3pix Ltda. All rights reserved. | |
| # | |
| # Developed by Lucas Guimarães - G3pix Ltda | |
| # Contact: https://g3pix.com.br | |
| # Project URL: https://g3pix.com.br/axonasp | |
| # | |
| # This Source Code Form is subject to the terms of the Mozilla Public | |
| # License, v. 2.0. If a copy of the MPL was not distributed with this | |
| # file, You can obtain one at https://mozilla.org/MPL/2.0/. | |
| # | |
| # Attribution Notice: | |
| # If this software is used in other projects, the name "AxonASP Server" | |
| # must be cited in the documentation or "About" section. | |
| # | |
| # Contribution Policy: | |
| # Modifications to the core source code of AxonASP Server must be | |
| # made available under this same license terms. | |
| # This code was contributed largely by @jeffreyheping | |
| # (https://github.com/jeffreyheping) | |
| # | |
| # Triggers: | |
| # - Push of v* tag → publishes :v1.2.3 + :1.2 + :1 | |
| # - Workflow dispatch → allows manual triggering of the workflow | |
| name: Build OS Packages | |
| on: | |
| push: | |
| tags: | |
| - "v*.*.*" | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| prepare: | |
| name: Prepare Version | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.value }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Compute version string | |
| id: version | |
| run: | | |
| if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then | |
| VERSION_CLEAN=${GITHUB_REF_NAME#v} | |
| echo "value=${VERSION_CLEAN}" >> "$GITHUB_OUTPUT" | |
| else | |
| PATCH=$(git rev-list --count HEAD 2>/dev/null || echo "0") | |
| REVISION=$(git rev-parse --short HEAD 2>/dev/null || echo "0") | |
| echo "value=2.3.${PATCH}.${REVISION}" >> "$GITHUB_OUTPUT" | |
| fi | |
| build: | |
| name: Build ${{ matrix.goos }}/${{ matrix.goarch }} | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { goos: linux, goarch: amd64 } | |
| - { goos: darwin, goarch: arm64 } | |
| - { goos: windows, goarch: amd64 } | |
| - { goos: freebsd, goarch: amd64 } | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Install goversioninfo | |
| if: matrix.goos == 'windows' | |
| run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest | |
| - name: Generate Windows resources | |
| if: matrix.goos == 'windows' | |
| run: | | |
| export PATH=$PATH:$(go env GOPATH)/bin | |
| go generate ./... | |
| - name: Build binaries | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: "0" | |
| FULL_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| set -e | |
| LDFLAGS="-s -w -X main.Version=${FULL_VERSION}" | |
| HTA_LDFLAGS="${LDFLAGS}" | |
| EXT="" | |
| if [ "${GOOS}" = "windows" ]; then | |
| EXT=".exe" | |
| HTA_LDFLAGS="-s -w -H windowsgui -X main.Version=${FULL_VERSION}" | |
| fi | |
| build_one() { go build -trimpath -ldflags "${LDFLAGS}" -o "$1" "./$2"; } | |
| build_one "axonasp-http$EXT" server | |
| build_one "axonasp-fastcgi$EXT" fastcgi | |
| build_one "axonasp-cli$EXT" cli | |
| build_one "axonasp-mcp$EXT" mcp | |
| build_one "axonasp-admin$EXT" admin | |
| build_one "axonasp-service$EXT" service | |
| build_one "axonasp-testsuite$EXT" testsuite | |
| # Build axonhta — output to .tmp first to avoid Go placing the | |
| # binary inside the ./axonhta/ source directory, then remove the | |
| # stale directory before renaming so mv doesn't descend into it. | |
| go build -trimpath -ldflags "${HTA_LDFLAGS}" -o "axonhta${EXT}.tmp" ./axonhta | |
| rm -rf "axonhta${EXT}" 2>/dev/null || true | |
| mv "axonhta${EXT}.tmp" "axonhta${EXT}" | |
| if [ "${GOOS}" != "windows" ]; then build_one "axonasp-fpm" fpm; fi | |
| - name: Install xcaddy | |
| if: matrix.goos == 'linux' || matrix.goos == 'darwin' || matrix.goos == 'windows' | |
| run: go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest | |
| - name: Build AxonASP Caddy executable | |
| if: matrix.goos == 'linux' || matrix.goos == 'darwin' || matrix.goos == 'windows' | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| run: | | |
| set -e | |
| export PATH="$(go env GOPATH)/bin:${PATH}" | |
| pushd caddy | |
| rm -f caddy caddy.exe | |
| xcaddy build \ | |
| --with g3pix.com.br/axonasp/v2/caddy=. \ | |
| --replace "g3pix.com.br/axonasp/v2=${GITHUB_WORKSPACE}" \ | |
| --replace "github.com/google/cel-go=github.com/google/cel-go@v0.20.1" | |
| popd | |
| - name: Stage AxonASP Caddy package | |
| if: matrix.goos == 'linux' || matrix.goos == 'darwin' || matrix.goos == 'windows' | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| run: | | |
| set -e | |
| CADDY_OS="${GOOS}" | |
| [ "${CADDY_OS}" = "darwin" ] && CADDY_OS="macos" | |
| CADDY_STAGE="axonasp-caddy-${CADDY_OS}-${GOARCH}" | |
| mkdir -p "${CADDY_STAGE}" | |
| CADDY_BIN="caddy" | |
| [ "${GOOS}" = "windows" ] && CADDY_BIN="caddy.exe" | |
| cp "caddy/${CADDY_BIN}" "${CADDY_STAGE}/${CADDY_BIN}" | |
| cp -r config "${CADDY_STAGE}/config" | |
| cp -r www "${CADDY_STAGE}/www" | |
| rm -rf "${CADDY_STAGE}/www/tests" | |
| cp LICENSE.txt "${CADDY_STAGE}/LICENSE.txt" | |
| cat > "${CADDY_STAGE}/Caddyfile" <<'CADDYFILE' | |
| :8801 { | |
| root * ./www | |
| route { | |
| axonasp { | |
| site_name axonasp | |
| global_asa_path ./www/global.asa | |
| } | |
| file_server | |
| } | |
| } | |
| CADDYFILE | |
| - name: Create AxonASP Caddy archive | |
| if: matrix.goos == 'linux' || matrix.goos == 'darwin' || matrix.goos == 'windows' | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: ${{ matrix.goarch }} | |
| run: | | |
| set -e | |
| CADDY_OS="${GOOS}" | |
| [ "${CADDY_OS}" = "darwin" ] && CADDY_OS="macos" | |
| CADDY_STAGE="axonasp-caddy-${CADDY_OS}-${ARCH}" | |
| if [ "${GOOS}" = "windows" ]; then | |
| zip -r "axonasp-caddy-${CADDY_OS}-${VERSION}-${ARCH}.zip" "${CADDY_STAGE}/" | |
| else | |
| tar -czf "axonasp-caddy-${CADDY_OS}-${VERSION}-${ARCH}.tar.gz" "${CADDY_STAGE}/" | |
| fi | |
| - name: Remove test directory from www | |
| run: rm -rf ./www/test/ || true | |
| - name: Remove resources/website directory from www | |
| run: | | |
| rm -rf ./resources/website/ || true | |
| rm -rf ./resources/web/ || true | |
| rm -rf ./resources/old/ || true | |
| # ────────────────────────────────────────────────────────────── | |
| # Linux: DEB / RPM / Alpine APK / Archlinux packages (x64 only) | |
| # ────────────────────────────────────────────────────────────── | |
| - name: Install nFPM | |
| if: matrix.goos == 'linux' | |
| run: | | |
| echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list | |
| sudo apt-get update | |
| sudo apt-get install -y nfpm | |
| - name: Build Linux packages | |
| if: matrix.goos == 'linux' | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| # If axonhta is a directory (build collision) remove it so nFPM | |
| # doesn't choke trying to treat it as a binary file. | |
| if [ -d axonhta ] && [ ! -f axonhta ]; then rm -rf axonhta; fi | |
| for packager in deb rpm apk archlinux; do | |
| nfpm package --packager "${packager}" --target . | |
| done | |
| - name: Build Linux Caddy packages | |
| if: matrix.goos == 'linux' | |
| env: | |
| GOARCH: ${{ matrix.goarch }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| set -e | |
| CADDY_STAGE="axonasp-caddy-linux-${GOARCH}" | |
| cp nfpm-caddy.yaml "${CADDY_STAGE}/nfpm-caddy.yaml" | |
| pushd "${CADDY_STAGE}" | |
| for packager in deb rpm apk; do | |
| nfpm package --config nfpm-caddy.yaml --packager "${packager}" --target . | |
| done | |
| # Move packages to workspace root so upload-artifact globs find them | |
| mv ./*.deb ./*.rpm ./*.apk ../ | |
| popd | |
| # ────────────────────────────────────────────────────────────── | |
| # Windows: portable zip (x64 only) | |
| # ────────────────────────────────────────────────────────────── | |
| - name: Create Windows portable zip | |
| if: matrix.goos == 'windows' | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: ${{ matrix.goarch }} | |
| run: | | |
| STAGE="axonasp-windows-${ARCH}" | |
| mkdir -p "${STAGE}" | |
| cp *.exe "${STAGE}/" | |
| cp -r www config fpm/fpm.d mcp resources LICENSE.txt \ | |
| LEGAL-DISCLAIMER.md global.asa index.hta \ | |
| iis-http.cmd install-service.ps1 uninstall-service.ps1 "${STAGE}/" | |
| zip -r "axonasp-windows-${VERSION}-${ARCH}.zip" "${STAGE}/" | |
| # ────────────────────────────────────────────────────────────── | |
| # macOS: portable zip (arm64 only) | |
| # ────────────────────────────────────────────────────────────── | |
| - name: Create macOS portable zip | |
| if: matrix.goos == 'darwin' | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: ${{ matrix.goarch }} | |
| run: | | |
| STAGE="axonasp-macos-${ARCH}" | |
| mkdir -p "${STAGE}" | |
| cp axonasp-http axonasp-fastcgi axonasp-cli axonasp-mcp \ | |
| axonasp-admin axonasp-service axonasp-testsuite axonasp-fpm "${STAGE}/" | |
| [ -f axonhta ] && cp axonhta "${STAGE}/" | |
| cp -r www fpm/fpm.d config mcp resources LICENSE.txt \ | |
| LEGAL-DISCLAIMER.md global.asa index.hta "${STAGE}/" | |
| zip -r "axonasp-macos-${VERSION}-${ARCH}.zip" "${STAGE}/" | |
| # ────────────────────────────────────────────────────────────── | |
| # FreeBSD: portable tarball (.tar.xz) (x64 only) | |
| # ────────────────────────────────────────────────────────────── | |
| - name: Create FreeBSD portable tarball | |
| if: matrix.goos == 'freebsd' | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: ${{ matrix.goarch }} | |
| run: | | |
| STAGE="axonasp-freebsd-${ARCH}" | |
| mkdir -p "${STAGE}" | |
| cp axonasp-http axonasp-fastcgi axonasp-cli axonasp-mcp \ | |
| axonasp-admin axonasp-service axonasp-testsuite axonasp-fpm "${STAGE}/" | |
| [ -f axonhta ] && cp axonhta "${STAGE}/" | |
| cp -r www config fpm/fpm.d resources mcp LICENSE.txt LEGAL-DISCLAIMER.md global.asa index.hta "${STAGE}/" | |
| tar -cJf "axonasp-freebsd-${VERSION}-${ARCH}.tar.xz" "${STAGE}/" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: axonasp-${{ matrix.goos }}-${{ matrix.goarch }} | |
| path: | | |
| *.deb | |
| *.rpm | |
| *.apk | |
| *.pkg.tar.zst | |
| *.zip | |
| *.tar.gz | |
| *.tar.xz | |
| if-no-files-found: error | |
| build-wasm: | |
| name: Build js/wasm | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Build WASM | |
| env: | |
| GOOS: js | |
| GOARCH: wasm | |
| CGO_ENABLED: "0" | |
| FULL_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| set -e | |
| go build -trimpath -ldflags "-s -w -X main.Version=${FULL_VERSION}" -o wasm/axonasp.wasm ./wasm/main.go | |
| cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" wasm/ | |
| - name: Create WASM zip | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| STAGE="axonasp-wasm" | |
| mkdir -p "${STAGE}" | |
| cp wasm/axonasp.wasm wasm/wasm_exec.js wasm/index.htm wasm/axonasp.css "${STAGE}/" | |
| zip -r "axonasp-wasm-${VERSION}.zip" "${STAGE}/" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: axonasp-wasm | |
| path: "*.zip" | |
| if-no-files-found: error | |
| build-windows-installer: | |
| name: Build Windows installer amd64 | |
| needs: [prepare, build] | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Download Windows binaries from build job | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: axonasp-windows-amd64 | |
| path: . | |
| - name: Extract Windows zip | |
| run: | | |
| $zip = Get-ChildItem axonasp-windows-*.zip | Select-Object -First 1 | |
| Expand-Archive -Path $zip.Name -DestinationPath . -Force | |
| $subdir = Get-ChildItem -Directory | Where-Object { $_.Name -like "axonasp-windows-*" } | Select-Object -First 1 | |
| if ($subdir) { | |
| Rename-Item -Path $subdir.FullName -NewName "installer-src" | |
| } | |
| # Copy innosetup.iss and resources into the source directory | |
| Copy-Item resources\innosetup.iss installer-src\ -Force | |
| Copy-Item -Recurse resources installer-src\resources -Force | |
| shell: pwsh | |
| - name: Build installer with Inno Setup | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: amd64 | |
| run: | | |
| cd installer-src | |
| $verInfo = ($env:VERSION -split '\.')[0..2] -join '.' | |
| & "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" /DMyAppVersion="$env:VERSION" /DMyArchSuffix="$env:ARCH" /DMyVersionInfoVersion="$verInfo" innosetup.iss | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| shell: pwsh | |
| - name: Upload installer artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: axonasp-installer-amd64 | |
| path: installer-src\Output\*.exe | |
| if-no-files-found: error | |
| build-macos-installer: | |
| name: Build macOS pkg arm64 | |
| needs: [prepare, build] | |
| runs-on: macos-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Download macOS binaries from build job | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: axonasp-darwin-arm64 | |
| path: . | |
| - name: Extract macOS zip | |
| run: | | |
| zip=$(ls axonasp-macos-*.zip | head -n1) | |
| unzip -q "$zip" | |
| - name: Build .pkg installer | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| ARCH: arm64 | |
| run: | | |
| set -e | |
| STAGE="axonasp-macos-${ARCH}" | |
| PKGROOT="pkgroot" | |
| mkdir -p "${PKGROOT}/opt/axonasp" | |
| cp -R "${STAGE}/"* "${PKGROOT}/opt/axonasp/" | |
| mkdir -p scripts | |
| cat > scripts/postinstall <<'SCRIPT' | |
| #!/bin/bash | |
| set -e | |
| for bin in axonasp-http axonasp-fastcgi axonasp-cli axonasp-mcp axonasp-admin axonasp-service axonasp-testsuite axonasp-fpm; do | |
| if [ -f "/opt/axonasp/$bin" ]; then | |
| ln -sf "/opt/axonasp/$bin" "/usr/local/bin/$bin" | |
| fi | |
| done | |
| mkdir -p /etc/axonasp | |
| if [ -f /opt/axonasp/config/axonasp.toml ]; then | |
| ln -sf /opt/axonasp/config/axonasp.toml /etc/axonasp/axonasp.toml | |
| fi | |
| SCRIPT | |
| chmod +x scripts/postinstall | |
| pkgbuild \ | |
| --root "${PKGROOT}" \ | |
| --identifier com.g3pix.axonasp \ | |
| --version "${VERSION}" \ | |
| --scripts scripts \ | |
| --install-location / \ | |
| "axonasp-macos-${VERSION}-${ARCH}.pkg" | |
| if [ -f "/resources/icon.icns" ]; then | |
| echo ">>> Apply custom icon to the .pkg file" | |
| swift -e "import Cocoa; NSWorkspace.shared.setIcon(NSImage(contentsOfFile: \"/resources/icon.icns\"), forFile: \"axonasp-macos-${VERSION}-${ARCH}.pkg\", options: [])" | |
| else | |
| echo ">>> File ./resources/icon.icns not found to apply to the package." | |
| fi | |
| - name: Upload pkg artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: axonasp-macos-pkg-arm64 | |
| path: "*.pkg" | |
| if-no-files-found: error | |
| release: | |
| name: Publish to GitHub Releases | |
| needs: [prepare, build, build-wasm, build-windows-installer, build-macos-installer] | |
| if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts | |
| - name: Flatten artifacts for release | |
| run: | | |
| mkdir -p release-assets | |
| find artifacts -type f \( -name "*.deb" -o -name "*.rpm" -o -name "*.apk" -o -name "*.pkg.tar.zst" -o -name "*.zip" -o -name "*.tar.gz" -o -name "*.tar.xz" -o -name "*.pkg" -o -name "*.exe" \) -exec cp {} release-assets/ \; | |
| - name: Publish to GitHub Releases | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| files: release-assets/* |