Skip to content

feat: support Android quickstart init #245

feat: support Android quickstart init

feat: support Android quickstart init #245

Workflow file for this run

name: CI
on:
push:
branches:
- "**"
tags-ignore:
- "v*"
pull_request:
permissions:
contents: read
jobs:
test-and-build:
name: Test and build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v7
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache: true
- name: Run tests
# -count=1 disables Go's test result cache so flaky CI nodes never
# surface a stale "PASS" from an earlier run on the same content.
run: go test -count=1 ./...
- name: Check Go formatting
if: runner.os != 'Windows'
shell: bash
run: |
files="$(gofmt -l .)"
if [ -n "$files" ]; then
echo "$files"
exit 1
fi
- name: Audit error code coverage
if: runner.os != 'Windows'
shell: bash
run: ./scripts/check-error-codes.sh
- name: Check docs/commands.md is up to date
if: runner.os == 'Linux'
shell: bash
run: |
# Generated reference must track the cobra tree. If this fails,
# run `make docs-commands` locally and commit the result.
go run ./cmd/gendocs -check
# Prebuilt golangci-lint binaries may be compiled with an older Go than
# go.mod; loading .golangci.yml then fails ("Go language version used to
# build golangci-lint is lower than the targeted Go version"). Building
# from source with setup-go matches the project's toolchain.
- name: golangci-lint
if: runner.os == 'Linux'
uses: golangci/golangci-lint-action@v6
with:
version: v1.64.8
install-mode: goinstall
args: --timeout=5m
- name: Build CLI
shell: bash
run: |
mkdir -p dist
ext=""
if [ "${{ runner.os }}" = "Windows" ]; then
ext=".exe"
fi
go build -trimpath -o "dist/agora${ext}" .
- name: Check Unix installer syntax
if: runner.os != 'Windows'
shell: bash
run: sh -n install.sh
- name: Smoke test installer messages
if: runner.os != 'Windows'
shell: bash
run: sh scripts/test-installer-messages.sh
- name: Unit test installer fallback logic
if: runner.os == 'Linux'
shell: bash
run: sh scripts/test-installer-fallback.sh
- name: Check PowerShell installer syntax
if: runner.os == 'Windows'
shell: pwsh
run: |
$tokens = $null
$errors = $null
[void][System.Management.Automation.Language.Parser]::ParseFile(
(Join-Path $PWD 'install.ps1'),
[ref]$tokens,
[ref]$errors
)
if ($errors.Count -gt 0) {
$errors | ForEach-Object { Write-Error $_.Message }
exit 1
}
- name: Smoke test POSIX installer on Windows
if: runner.os == 'Windows'
shell: bash
run: |
set -euo pipefail
VERSION="0.0.0-ci" \
INSTALL_DIR="$PWD/.tmp/install-bin-sh" \
sh ./install.sh --dry-run --force
- name: Smoke test Unix installer
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
version="0.0.0-ci"
goos="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$(uname -m)" in
x86_64|amd64) goarch="amd64" ;;
aarch64|arm64) goarch="arm64" ;;
*) echo "Unsupported CI arch: $(uname -m)" >&2; exit 1 ;;
esac
fixture_root="$PWD/.tmp/install-fixture"
download_dir="$fixture_root/download/v${version}"
install_dir="$PWD/.tmp/install-bin"
bad_install_dir="$PWD/.tmp/install-bin-bad"
archive="agora-cli_v${version}_${goos}_${goarch}.tar.gz"
rm -rf "$fixture_root" "$install_dir" "$bad_install_dir"
mkdir -p "$download_dir"
tar -C dist -czf "$download_dir/$archive" agora
if command -v sha256sum >/dev/null 2>&1; then
(cd "$download_dir" && sha256sum "$archive" > checksums.txt)
else
(cd "$download_dir" && shasum -a 256 "$archive" > checksums.txt)
fi
# Fixed-port fixture server (matches the S3 fallback steps below).
# Avoids the ephemeral-port + port-file write race that intermittently
# hung before writing its port on macOS runners.
server_log="$fixture_root/http-server.log"
server_url="http://127.0.0.1:18080"
archive_url="${server_url}/download/v${version}/${archive}"
python3 -m http.server 18080 --directory "$fixture_root" >"$server_log" 2>&1 &
server_pid=$!
trap 'kill "$server_pid" 2>/dev/null || true' EXIT
server_ready=0
for attempt in $(seq 1 120); do
if ! kill -0 "$server_pid" 2>/dev/null; then
echo "Fixture HTTP server exited before serving the test archive." >&2
sed 's/^/ /' "$server_log" >&2 || true
exit 1
fi
if curl -fsS --head --connect-timeout 2 "$archive_url" >/dev/null 2>&1; then
server_ready=1
break
fi
sleep 0.25
done
if [ "$server_ready" != "1" ]; then
echo "Fixture HTTP server did not serve $archive_url." >&2
sed 's/^/ /' "$server_log" >&2 || true
exit 1
fi
# The installer enforces --proto =https in production. The smoke test
# serves the fixture from a local HTTP server, so we relax the proto
# restriction (test only).
export INSTALLER_CURL_PROTO_OPTS="--proto =http,https"
# Pin the source to github so this test only exercises the fixture
# (RELEASES_DOWNLOAD_BASE_URL) path; auto mode would fast-fail a
# transient fixture hiccup and divert to the real dl.agora.io mirror.
# github mode also uses the retry profile, restoring pre-fallback
# resilience.
VERSION="$version" \
AGORA_INSTALL_SOURCE=github \
RELEASES_DOWNLOAD_BASE_URL="${server_url}/download" \
RELEASES_PAGE_URL="$server_url" \
INSTALL_DIR="$install_dir" \
sh ./install.sh --force
"$install_dir/agora" --help >/dev/null
printf '%064d %s\n' 0 "$archive" > "$download_dir/checksums.txt"
if VERSION="$version" \
AGORA_INSTALL_SOURCE=github \
RELEASES_DOWNLOAD_BASE_URL="${server_url}/download" \
RELEASES_PAGE_URL="$server_url" \
INSTALL_DIR="$bad_install_dir" \
sh ./install.sh --force; then
echo "Expected checksum verification to fail" >&2
exit 1
fi
- name: Smoke test installer S3 fallback (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
version='0.0.0-ci'
arch="$(uname -m)"; case "$arch" in x86_64|amd64) arch=amd64;; aarch64|arm64) arch=arm64;; esac
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
archive="agora-cli_v${version}_${os}_${arch}.tar.gz"
root=".tmp/fallback-fixture"
rel="${root}/releases/v${version}"
install_dir="$PWD/.tmp/fallback-bin"
rm -rf "$root" "$install_dir"
mkdir -p "$rel" "$install_dir"
cp dist/agora "$root/agora"
tar -C "$root" -czf "${rel}/${archive}" agora
if command -v sha256sum >/dev/null 2>&1; then
( cd "$rel" && sha256sum "$archive" > checksums.txt )
else
( cd "$rel" && shasum -a 256 "$archive" > checksums.txt )
fi
printf '{"tag_name":"v%s","version":"%s"}' "$version" "$version" > "${root}/latest.json"
server_log="${root}/http.log"
python3 -m http.server 18082 --directory "$root" >"$server_log" 2>&1 &
server_pid=$!
trap 'kill "$server_pid" 2>/dev/null || true' EXIT
server_ready=0
for _ in $(seq 1 120); do
if ! kill -0 "$server_pid" 2>/dev/null; then
echo "Fixture HTTP server exited before becoming ready." >&2
sed 's/^/ /' "$server_log" >&2 || true
exit 1
fi
if curl -fsS --head --connect-timeout 2 "http://127.0.0.1:18082/latest.json" >/dev/null 2>&1; then
server_ready=1; break
fi
sleep 0.25
done
if [ "$server_ready" != "1" ]; then
echo "Fixture HTTP server did not become ready." >&2
sed 's/^/ /' "$server_log" >&2 || true
exit 1
fi
export INSTALLER_CURL_PROTO_OPTS="--proto =http,https"
GITHUB_API_URL="http://127.0.0.1:1/api" \
RELEASES_DOWNLOAD_BASE_URL="http://127.0.0.1:1/download" \
S3_DOWNLOAD_BASE_URL="http://127.0.0.1:18082/releases" \
S3_LATEST_URL="http://127.0.0.1:18082/latest.json" \
RELEASES_PAGE_URL="http://127.0.0.1:18082" \
INSTALL_DIR="$install_dir" \
sh ./install.sh --force
"$install_dir/agora" --help >/dev/null
echo "Fallback install succeeded via mock S3."
printf '%064d %s\n' 0 "$archive" > "${rel}/checksums.txt"
if GITHUB_API_URL="http://127.0.0.1:1/api" \
RELEASES_DOWNLOAD_BASE_URL="http://127.0.0.1:1/download" \
S3_DOWNLOAD_BASE_URL="http://127.0.0.1:18082/releases" \
S3_LATEST_URL="http://127.0.0.1:18082/latest.json" \
RELEASES_PAGE_URL="http://127.0.0.1:18082" \
INSTALL_DIR="$PWD/.tmp/fallback-bin-bad" \
sh ./install.sh --force; then
echo "Expected checksum verification to fail on the mirrored archive." >&2
exit 1
fi
echo "Checksum verification correctly rejected the tampered mirror archive."
- name: Smoke test PowerShell installer
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = '0.0.0-ci'
$arch = switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()) {
'x64' { 'amd64' }
'arm64' { 'arm64' }
default { throw "Unsupported CI arch: $([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)" }
}
$fixtureRoot = Join-Path $PWD '.tmp/install-fixture'
$downloadDir = Join-Path $fixtureRoot "download/v$version"
$installDir = Join-Path $PWD '.tmp/install-bin'
$badInstallDir = Join-Path $PWD '.tmp/install-bin-bad'
$archive = "agora-cli_v$version" + "_windows_${arch}.zip"
Remove-Item -Recurse -Force $fixtureRoot, $installDir, $badInstallDir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $downloadDir | Out-Null
Compress-Archive -Path (Join-Path $PWD 'dist/agora.exe') -DestinationPath (Join-Path $downloadDir $archive) -Force
$hash = (Get-FileHash -Path (Join-Path $downloadDir $archive) -Algorithm SHA256).Hash.ToLowerInvariant()
Set-Content -Path (Join-Path $downloadDir 'checksums.txt') -Value "$hash $archive"
$serverOutLog = Join-Path $fixtureRoot 'http-server.out.log'
$serverErrLog = Join-Path $fixtureRoot 'http-server.err.log'
$server = Start-Process -FilePath python -ArgumentList '-m', 'http.server', '18081', '--directory', $fixtureRoot -RedirectStandardOutput $serverOutLog -RedirectStandardError $serverErrLog -PassThru
$archiveUrl = "http://127.0.0.1:18081/download/v$version/$archive"
$serverReady = $false
for ($attempt = 1; $attempt -le 60; $attempt++) {
if ($server.HasExited) {
if (Test-Path -LiteralPath $serverOutLog) { Get-Content -Path $serverOutLog | ForEach-Object { Write-Host $_ } }
if (Test-Path -LiteralPath $serverErrLog) { Get-Content -Path $serverErrLog | ForEach-Object { Write-Host $_ } }
throw "Fixture HTTP server exited before serving $archiveUrl."
}
try {
$response = Invoke-WebRequest -Uri $archiveUrl -Method Head -UseBasicParsing
if ($response.StatusCode -eq 200) {
$serverReady = $true
break
}
} catch {
Start-Sleep -Milliseconds 500
}
}
if (-not $serverReady) {
if (Test-Path -LiteralPath $serverOutLog) { Get-Content -Path $serverOutLog | ForEach-Object { Write-Host $_ } }
if (Test-Path -LiteralPath $serverErrLog) { Get-Content -Path $serverErrLog | ForEach-Object { Write-Host $_ } }
throw "Fixture HTTP server did not serve $archiveUrl."
}
try {
$env:VERSION = $version
# Pin source to github so this test only exercises the fixture path
# (auto mode could divert a transient hiccup to the real mirror).
$env:AGORA_INSTALL_SOURCE = 'github'
$env:RELEASES_DOWNLOAD_BASE_URL = 'http://127.0.0.1:18081/download'
$env:RELEASES_PAGE_URL = 'http://127.0.0.1:18081'
& ./install.ps1 -InstallDir $installDir
if ($LASTEXITCODE -ne 0) {
throw "install.ps1 failed with exit code $LASTEXITCODE."
}
& (Join-Path $installDir 'agora.exe') --help *> $null
Set-Content -Path (Join-Path $downloadDir 'checksums.txt') -Value ('0' * 64 + " $archive")
$previousNativePreference = $PSNativeCommandUseErrorActionPreference
$PSNativeCommandUseErrorActionPreference = $false
pwsh -NoProfile -ExecutionPolicy Bypass -File ./install.ps1 -InstallDir $badInstallDir
$badExitCode = $LASTEXITCODE
$PSNativeCommandUseErrorActionPreference = $previousNativePreference
if ($badExitCode -eq 0) {
throw 'Expected checksum verification to fail with a non-zero exit code.'
}
# The expected non-zero $LASTEXITCODE from install.ps1 is good news
# for this assertion, but GitHub Actions' pwsh wrapper appends
# `if (Test-Path variable:\LASTEXITCODE) { exit $LASTEXITCODE }`,
# which would otherwise propagate that non-zero exit and fail the
# whole step. Clear it now that we have what we need.
$global:LASTEXITCODE = 0
} finally {
Stop-Process -Id $server.Id -Force -ErrorAction SilentlyContinue
Remove-Item Env:VERSION, Env:AGORA_INSTALL_SOURCE, Env:RELEASES_DOWNLOAD_BASE_URL, Env:RELEASES_PAGE_URL -ErrorAction SilentlyContinue
}
- name: Smoke test PowerShell installer S3 fallback
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = '0.0.0-ci'
$arch = switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()) {
'x64' { 'amd64' } 'arm64' { 'arm64' } default { throw "Unsupported CI arch" }
}
$root = Join-Path $PWD '.tmp/fallback-fixture'
$rel = Join-Path $root "releases/v$version"
$installDir = Join-Path $PWD '.tmp/fallback-bin'
$archive = "agora-cli_v$version" + "_windows_${arch}.zip"
Remove-Item -Recurse -Force $root, $installDir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $rel, $installDir | Out-Null
Compress-Archive -Path (Join-Path $PWD 'dist/agora.exe') -DestinationPath (Join-Path $rel $archive) -Force
$hash = (Get-FileHash -Path (Join-Path $rel $archive) -Algorithm SHA256).Hash.ToLowerInvariant()
Set-Content -Path (Join-Path $rel 'checksums.txt') -Value "$hash $archive"
Set-Content -NoNewline -Path (Join-Path $root 'latest.json') -Value ('{"tag_name":"v' + $version + '","version":"' + $version + '"}')
$server = Start-Process -FilePath python -ArgumentList '-m', 'http.server', '18083', '--directory', $root -PassThru
try {
$ready = $false
for ($i = 0; $i -lt 120; $i++) {
if ($server.HasExited) { throw 'Fixture HTTP server exited before becoming ready.' }
try { if ((Invoke-WebRequest -Uri 'http://127.0.0.1:18083/latest.json' -UseBasicParsing).StatusCode -eq 200) { $ready = $true; break } } catch { Start-Sleep -Milliseconds 250 }
}
if (-not $ready) { throw 'fixture server not ready at http://127.0.0.1:18083/latest.json' }
$env:GITHUB_API_URL = 'http://127.0.0.1:1/api'
$env:RELEASES_DOWNLOAD_BASE_URL = 'http://127.0.0.1:1/download'
$env:S3_DOWNLOAD_BASE_URL = 'http://127.0.0.1:18083/releases'
$env:S3_LATEST_URL = 'http://127.0.0.1:18083/latest.json'
$env:RELEASES_PAGE_URL = 'http://127.0.0.1:18083'
& ./install.ps1 -InstallDir $installDir
if ($LASTEXITCODE -ne 0) { throw "install.ps1 fallback failed: $LASTEXITCODE" }
& (Join-Path $installDir 'agora.exe') --help *> $null
Write-Host 'Fallback install succeeded via mock S3.'
# Checksum verification must still fire on S3-served bytes: corrupt
# the mirror's checksums.txt and assert install.ps1 refuses.
Set-Content -Path (Join-Path $rel 'checksums.txt') -Value ('0' * 64 + " $archive")
$badInstallDir = Join-Path $PWD '.tmp/fallback-bin-bad'
$previousNativePreference = $PSNativeCommandUseErrorActionPreference
$PSNativeCommandUseErrorActionPreference = $false
pwsh -NoProfile -ExecutionPolicy Bypass -File ./install.ps1 -InstallDir $badInstallDir
$badExitCode = $LASTEXITCODE
$PSNativeCommandUseErrorActionPreference = $previousNativePreference
if ($badExitCode -eq 0) {
throw 'Expected checksum verification to fail on the mirrored archive.'
}
$global:LASTEXITCODE = 0
Write-Host 'Checksum verification correctly rejected the tampered mirror archive.'
} finally {
Stop-Process -Id $server.Id -Force -ErrorAction SilentlyContinue
Remove-Item Env:GITHUB_API_URL, Env:RELEASES_DOWNLOAD_BASE_URL, Env:S3_DOWNLOAD_BASE_URL, Env:S3_LATEST_URL, Env:RELEASES_PAGE_URL -ErrorAction SilentlyContinue
}