mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
Publish pipeline: goreleaser + Maven Central + npm (#1)
* feat(cli): add Version var and version subcommand * build(gradle): introduce uatu.version property for lockstep releases * build(sdk-android): swap GitHub Packages for vanniktech Maven Central plugin * build(spec-api): make package publish-ready for npm * ci(release): add goreleaser config for cross-platform uatu CLI builds * ci: add ci and release GitHub Actions workflows * ci: restrict ci.yml to PR + workflow_dispatch (no direct push to master) * docs(release): add local release targets, env example, and install docs * build(sdk-android): make signAllPublications conditional on signing key * ci(release): stage sidecar JAR at embed path before go build * chore(spec-api): regenerate package-lock for updated package.json * ci: install protoc-gen-go plugins before buf generate * ci: bump Node to 22 (required for --experimental-strip-types)
This commit is contained in:
17 files changed
+555
-36
No files matched your search
@@ -0,0 +1,29 @@
|
|||||||
|
# uatu release credentials (local dev only).
|
||||||
|
#
|
||||||
|
# Copy to `.env.local` (gitignored) and fill in values ONLY if you need to
|
||||||
|
# fire a real release from your laptop. Day-to-day work and the `release-cli`
|
||||||
|
# / `release-android-local` / `release-npm-dry` Make targets don't need any
|
||||||
|
# of these — they're snapshot/local-only.
|
||||||
|
#
|
||||||
|
# In CI, these are provided via GitHub Actions secrets (see .github/workflows/release.yml).
|
||||||
|
|
||||||
|
# npm automation token (bypasses 2FA).
|
||||||
|
# Create at npmjs.com → Access Tokens → Generate New Token → Automation.
|
||||||
|
NPM_TOKEN=
|
||||||
|
|
||||||
|
# Sonatype Central user token (username half).
|
||||||
|
# Create at central.sonatype.com → Account → Generate User Token.
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralUsername=
|
||||||
|
|
||||||
|
# Sonatype Central user token (password half).
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralPassword=
|
||||||
|
|
||||||
|
# ASCII-armored GPG private key for release signing. Include the full
|
||||||
|
# "-----BEGIN PGP PRIVATE KEY BLOCK-----…-----END PGP PRIVATE KEY BLOCK-----"
|
||||||
|
# payload, with literal \n newlines escaped inside quotes, e.g.:
|
||||||
|
# ORG_GRADLE_PROJECT_signingInMemoryKey="-----BEGIN PGP PRIVATE KEY BLOCK-----\nlQVYBG…\n-----END PGP PRIVATE KEY BLOCK-----"
|
||||||
|
# Generate with: gpg --export-secret-keys --armor <KEYID>
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKey=
|
||||||
|
|
||||||
|
# Passphrase for the GPG key above.
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword=
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
# Runs on PRs (opened / synchronize / reopened — the defaults) and manual
|
||||||
|
# dispatch only. We deliberately don't run on direct pushes to master:
|
||||||
|
# master is PR-merge-only, and PR validation already covers the merge
|
||||||
|
# commit via the `synchronize` event on the PR branch.
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "17"
|
||||||
|
|
||||||
|
- name: Set up Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Set up Node 22
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: pkg/spec-api/package-lock.json
|
||||||
|
|
||||||
|
- name: Install buf
|
||||||
|
uses: bufbuild/buf-setup-action@v1
|
||||||
|
|
||||||
|
- name: Install protoc plugins
|
||||||
|
run: |
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
|
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: Cache Gradle
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
|
restore-keys: |
|
||||||
|
gradle-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Bootstrap
|
||||||
|
run: make bootstrap
|
||||||
|
|
||||||
|
- name: Lint proto
|
||||||
|
run: buf lint
|
||||||
|
|
||||||
|
- name: Go vet
|
||||||
|
run: go vet ./...
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: make test
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
name: release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: "Tag to release (e.g. v0.0.1-rc1). Must already exist."
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: release-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release-android:
|
||||||
|
name: Publish sdk-android to Maven Central
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.tag || github.ref }}
|
||||||
|
|
||||||
|
- name: Resolve version
|
||||||
|
id: ver
|
||||||
|
run: |
|
||||||
|
raw="${{ inputs.tag || github.ref_name }}"
|
||||||
|
echo "version=${raw#v}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "17"
|
||||||
|
|
||||||
|
- name: Set up Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Cache Gradle
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
|
restore-keys: |
|
||||||
|
gradle-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Publish to Maven Central
|
||||||
|
run: ./gradlew :sdk-android:publishAndReleaseToMavenCentral -Puatu.version=${{ steps.ver.outputs.version }}
|
||||||
|
|
||||||
|
release-npm:
|
||||||
|
name: Publish @uatu/spec to npm
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.tag || github.ref }}
|
||||||
|
|
||||||
|
- name: Resolve version
|
||||||
|
id: ver
|
||||||
|
run: |
|
||||||
|
raw="${{ inputs.tag || github.ref_name }}"
|
||||||
|
echo "version=${raw#v}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Set up Node 22
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: pkg/spec-api/package-lock.json
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: pkg/spec-api
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Stamp version
|
||||||
|
working-directory: pkg/spec-api
|
||||||
|
run: npm version ${{ steps.ver.outputs.version }} --no-git-tag-version --allow-same-version
|
||||||
|
|
||||||
|
- name: Publish
|
||||||
|
working-directory: pkg/spec-api
|
||||||
|
# npm tag pre-releases (e.g. 0.1.0-rc1) as "next" so npm install @uatu/spec
|
||||||
|
# keeps resolving the latest stable.
|
||||||
|
run: |
|
||||||
|
if [[ "${{ steps.ver.outputs.version }}" == *-* ]]; then
|
||||||
|
npm publish --access public --tag next
|
||||||
|
else
|
||||||
|
npm publish --access public
|
||||||
|
fi
|
||||||
|
|
||||||
|
release-cli:
|
||||||
|
name: Publish uatu CLI to GitHub Releases
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.tag || github.ref }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "17"
|
||||||
|
|
||||||
|
- name: Set up Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Cache Gradle
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
|
restore-keys: |
|
||||||
|
gradle-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Build sidecar JAR
|
||||||
|
run: make sidecar
|
||||||
|
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v6
|
||||||
|
with:
|
||||||
|
version: "~> v2"
|
||||||
|
args: release --clean
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -30,3 +30,9 @@ node_modules/
|
|||||||
# Sidecar fat JAR — build artifact copied in by `make uatu` before
|
# Sidecar fat JAR — build artifact copied in by `make uatu` before
|
||||||
# `go build -tags withsidecar`. Never commit: it's ~130 MB.
|
# `go build -tags withsidecar`. Never commit: it's ~130 MB.
|
||||||
internal/sidecar/assets/sidecar-all.jar
|
internal/sidecar/assets/sidecar-all.jar
|
||||||
|
|
||||||
|
# spec-api compiled output
|
||||||
|
pkg/spec-api/dist/
|
||||||
|
|
||||||
|
# goreleaser local output
|
||||||
|
dist/
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
project_name: uatu
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# The Go binary embeds the sidecar fat JAR via //go:embed gated by the
|
||||||
|
# `withsidecar` build tag. Rebuild the JAR and stage it at the embed
|
||||||
|
# path so the `go build` below picks up fresh bytes.
|
||||||
|
- make sidecar
|
||||||
|
- sh -c 'mkdir -p internal/sidecar/assets && cp sidecar/build/libs/sidecar-all.jar internal/sidecar/assets/sidecar-all.jar'
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- id: uatu
|
||||||
|
main: ./cmd/uatu
|
||||||
|
binary: uatu
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
flags:
|
||||||
|
- -tags=withsidecar
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X main.Version={{.Version}}
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- id: uatu
|
||||||
|
ids:
|
||||||
|
- uatu
|
||||||
|
formats: [tar.gz]
|
||||||
|
name_template: "uatu_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
- LICENSE*
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: checksums.txt
|
||||||
|
algorithm: sha256
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
version_template: "{{ incpatch .Version }}-snapshot-{{ .ShortCommit }}"
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
use: github
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
- "^chore:"
|
||||||
|
- "^ci:"
|
||||||
|
- Merge pull request
|
||||||
|
- Merge branch
|
||||||
|
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: priyanshujain
|
||||||
|
name: uatu
|
||||||
|
draft: false
|
||||||
|
prerelease: auto
|
||||||
@@ -11,7 +11,7 @@ SIDECAR_EMBED := internal/sidecar/assets/sidecar-all.jar
|
|||||||
SDK_AAR := sdk/android/build/outputs/aar/sdk-android-release.aar
|
SDK_AAR := sdk/android/build/outputs/aar/sdk-android-release.aar
|
||||||
UATU_BIN := bin/uatu
|
UATU_BIN := bin/uatu
|
||||||
|
|
||||||
.PHONY: bootstrap proto sidecar sdk-android sdk-android-publish uatu test test-go test-kotlin test-spec-api clean
|
.PHONY: bootstrap proto sidecar sdk-android sdk-android-publish uatu test test-go test-kotlin test-spec-api clean release-cli release-android-local release-npm-dry
|
||||||
|
|
||||||
bootstrap:
|
bootstrap:
|
||||||
$(GO) mod download
|
$(GO) mod download
|
||||||
@@ -29,8 +29,7 @@ sdk-android:
|
|||||||
ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:assembleRelease
|
ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:assembleRelease
|
||||||
|
|
||||||
sdk-android-publish:
|
sdk-android-publish:
|
||||||
@if [ -z "$$GH_TOKEN" ]; then echo "GH_TOKEN must be set" >&2; exit 1; fi
|
ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publishToMavenLocal
|
||||||
ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publish
|
|
||||||
|
|
||||||
uatu: $(UATU_BIN)
|
uatu: $(UATU_BIN)
|
||||||
|
|
||||||
@@ -55,5 +54,18 @@ test-spec-api:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(GO) clean
|
$(GO) clean
|
||||||
rm -rf bin
|
rm -rf bin dist pkg/spec-api/dist
|
||||||
$(GRADLE) clean
|
$(GRADLE) clean
|
||||||
|
|
||||||
|
# Local release dry-runs. None of these touch remote registries.
|
||||||
|
|
||||||
|
release-cli:
|
||||||
|
$(MAKE) sidecar
|
||||||
|
goreleaser release --snapshot --clean
|
||||||
|
|
||||||
|
release-android-local:
|
||||||
|
@if [ -f .env.local ]; then set -a; . ./.env.local; set +a; fi; \
|
||||||
|
ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publishToMavenLocal -Puatu.version=0.0.0-local
|
||||||
|
|
||||||
|
release-npm-dry:
|
||||||
|
cd pkg/spec-api && npm ci && npm run build && npm pack --dry-run
|
||||||
@@ -6,3 +6,46 @@ Testing framework and spec in ts/js used for blackbox testing and property based
|
|||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
- android
|
- android
|
||||||
- ios
|
- ios
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
Download the platform tarball from [GitHub Releases](https://github.com/priyanshujain/uatu/releases/latest):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# macOS arm64
|
||||||
|
curl -L https://github.com/priyanshujain/uatu/releases/latest/download/uatu_<version>_darwin_arm64.tar.gz | tar xz
|
||||||
|
# Linux amd64
|
||||||
|
curl -L https://github.com/priyanshujain/uatu/releases/latest/download/uatu_<version>_linux_amd64.tar.gz | tar xz
|
||||||
|
|
||||||
|
./uatu version
|
||||||
|
```
|
||||||
|
|
||||||
|
Pre-built for `darwin/arm64`, `darwin/amd64`, `linux/amd64`, `linux/arm64`.
|
||||||
|
|
||||||
|
### Spec API (npm)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @uatu/spec
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { extract, always, actions } from "@uatu/spec";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android SDK (Maven Central)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// settings.gradle.kts
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// app/build.gradle.kts
|
||||||
|
dependencies {
|
||||||
|
implementation("io.github.priyanshujain:sdk-android:<version>")
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -10,6 +10,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Version is stamped at build time via goreleaser ldflags.
|
||||||
|
// Default "dev" marks untagged local builds.
|
||||||
|
var Version = "dev"
|
||||||
|
|
||||||
type testOptions struct {
|
type testOptions struct {
|
||||||
spec string
|
spec string
|
||||||
bundleID string
|
bundleID string
|
||||||
@@ -29,6 +33,7 @@ Usage:
|
|||||||
Commands:
|
Commands:
|
||||||
test Run a spec against an app for a fixed duration.
|
test Run a spec against an app for a fixed duration.
|
||||||
doctor Check that the host environment is ready to run uatu.
|
doctor Check that the host environment is ready to run uatu.
|
||||||
|
version Print the uatu version.
|
||||||
|
|
||||||
Run "uatu <command> -h" for command-specific flags.
|
Run "uatu <command> -h" for command-specific flags.
|
||||||
`
|
`
|
||||||
@@ -87,6 +92,9 @@ func run(args []string, stdout, stderr io.Writer) error {
|
|||||||
return runTest(options, stdout)
|
return runTest(options, stdout)
|
||||||
case "doctor":
|
case "doctor":
|
||||||
return runDoctor(stdout)
|
return runDoctor(stdout)
|
||||||
|
case "version", "-v", "--version":
|
||||||
|
fmt.Fprintln(stdout, Version)
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown command: %q (try 'uatu help')", args[1])
|
return fmt.Errorf("unknown command: %q (try 'uatu help')", args[1])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,22 @@ func TestRun_HelpPrintsUsage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRun_VersionPrintsVersion(t *testing.T) {
|
||||||
|
prev := Version
|
||||||
|
Version = "1.2.3-test"
|
||||||
|
defer func() { Version = prev }()
|
||||||
|
|
||||||
|
for _, arg := range []string{"version", "--version", "-v"} {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
if err := run([]string{"uatu", arg}, &stdout, io.Discard); err != nil {
|
||||||
|
t.Fatalf("%s: %v", arg, err)
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(stdout.String()) != "1.2.3-test" {
|
||||||
|
t.Errorf("%s: got %q, want 1.2.3-test", arg, stdout.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRun_UnknownCommand(t *testing.T) {
|
func TestRun_UnknownCommand(t *testing.T) {
|
||||||
err := run([]string{"uatu", "wat"}, io.Discard, io.Discard)
|
err := run([]string{"uatu", "wat"}, io.Discard, io.Discard)
|
||||||
if err == nil || !strings.Contains(err.Error(), "unknown command") {
|
if err == nil || !strings.Contains(err.Error(), "unknown command") {
|
||||||
|
|||||||
@@ -3,3 +3,8 @@ org.gradle.parallel=true
|
|||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
|
||||||
|
# Single source of truth at release time is the git tag (e.g. v0.1.0 → 0.1.0),
|
||||||
|
# forwarded via `-Puatu.version=...` or `ORG_GRADLE_PROJECT_uatu.version`.
|
||||||
|
# The default below only applies to untagged local builds.
|
||||||
|
uatu.version=0.0.0-dev
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# @uatu/spec
|
||||||
|
|
||||||
|
TypeScript spec API for [uatu](https://github.com/priyanshujain/uatu) — a property-based UI fuzzer for mobile apps.
|
||||||
|
|
||||||
|
Spec authors write specs in TypeScript that describe what an app should *always* do (safety invariants), generate weighted actions to exercise the app, and extract structured state from the accessibility tree. The `uatu` CLI picks up the spec and drives the app under test.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @uatu/spec
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { extract, always, actions, Tap, weighted } from "@uatu/spec";
|
||||||
|
|
||||||
|
export const spec = {
|
||||||
|
extract: extract((tree) => ({
|
||||||
|
onHomeScreen: tree.some((n) => n.text === "Home"),
|
||||||
|
})),
|
||||||
|
|
||||||
|
always: always(({ state }) => state.onHomeScreen || !state.startedOnHome),
|
||||||
|
|
||||||
|
actions: actions(({ tree }) =>
|
||||||
|
weighted([
|
||||||
|
[1, Tap(tree.first((n) => n.text === "Checkout"))],
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version compatibility
|
||||||
|
|
||||||
|
`@uatu/spec` is released in lockstep with the uatu CLI. Pin the same major/minor version as your installed `uatu` binary.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache-2.0
|
||||||
Generated
+4
-3
@@ -1,15 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@uatu/spec",
|
"name": "@uatu/spec",
|
||||||
"version": "0.0.1",
|
"version": "0.0.0-dev",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@uatu/spec",
|
"name": "@uatu/spec",
|
||||||
"version": "0.0.1",
|
"version": "0.0.0-dev",
|
||||||
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.7.5",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
|
|||||||
@@ -1,17 +1,42 @@
|
|||||||
{
|
{
|
||||||
"name": "@uatu/spec",
|
"name": "@uatu/spec",
|
||||||
"version": "0.0.1",
|
"version": "0.0.0-dev",
|
||||||
"description": "TypeScript spec API for Uatu (vendored locally; not published to npm in v0.1).",
|
"description": "TypeScript spec API for uatu — a property-based UI fuzzer for mobile apps.",
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"types": "src/index.ts",
|
"main": "./dist/index.js",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"import": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/priyanshujain/uatu.git",
|
||||||
|
"directory": "pkg/spec-api"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/priyanshujain/uatu",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/priyanshujain/uatu/issues"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"author": "Priyanshu Jain",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "tsc -p tsconfig.build.json",
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
"check": "tsc --noEmit",
|
"check": "tsc --noEmit",
|
||||||
"test": "node --test --experimental-strip-types test/*.test.ts"
|
"test": "node --test --experimental-strip-types test/*.test.ts"
|
||||||
},
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.7.5",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"noEmit": false,
|
||||||
|
"emitDeclarationOnly": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"rewriteRelativeImportExtensions": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["test/**/*", "dist/**/*", "node_modules"]
|
||||||
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
|
import com.vanniktech.maven.publish.AndroidSingleVariantLibrary
|
||||||
|
import com.vanniktech.maven.publish.SonatypeHost
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.library") version "8.11.0"
|
id("com.android.library") version "8.11.0"
|
||||||
kotlin("android") version "2.1.21"
|
kotlin("android") version "2.1.21"
|
||||||
`maven-publish`
|
id("com.vanniktech.maven.publish") version "0.30.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version = findProperty("uatu.version") as String? ?: "0.0.0-dev"
|
||||||
|
group = "io.github.priyanshujain"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "dev.uatu.sdk"
|
namespace = "dev.uatu.sdk"
|
||||||
compileSdk = 35
|
compileSdk = 35
|
||||||
@@ -25,33 +31,60 @@ android {
|
|||||||
testOptions {
|
testOptions {
|
||||||
unitTests.isReturnDefaultValues = true
|
unitTests.isReturnDefaultValues = true
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
|
||||||
singleVariant("release") {
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mavenPublishing {
|
||||||
|
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, automaticRelease = true)
|
||||||
|
|
||||||
|
// Sign only when a release-signing key is provided (env or Gradle
|
||||||
|
// property). Unsigned runs are useful for `publishToMavenLocal` dry-runs;
|
||||||
|
// CI always has the key set so the actual Central push is always signed.
|
||||||
|
if (findProperty("signingInMemoryKey") != null) {
|
||||||
|
signAllPublications()
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(
|
||||||
|
AndroidSingleVariantLibrary(
|
||||||
|
variant = "release",
|
||||||
|
sourcesJar = true,
|
||||||
|
publishJavadocJar = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
coordinates(
|
||||||
|
groupId = "io.github.priyanshujain",
|
||||||
|
artifactId = "sdk-android",
|
||||||
|
version = version.toString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("uatu sdk-android")
|
||||||
|
description.set(
|
||||||
|
"Android runtime SDK for uatu — a property-based UI fuzzer for mobile apps. " +
|
||||||
|
"Exposes a content-provider accessibility bridge consumed by the uatu CLI at test time.",
|
||||||
|
)
|
||||||
|
url.set("https://github.com/priyanshujain/uatu")
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("Apache License, Version 2.0")
|
||||||
|
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||||
|
distribution.set("repo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
developers {
|
||||||
publications {
|
developer {
|
||||||
register<MavenPublication>("release") {
|
id.set("priyanshujain")
|
||||||
groupId = "dev.uatu"
|
name.set("Priyanshu Jain")
|
||||||
artifactId = "sdk-android"
|
url.set("https://github.com/priyanshujain")
|
||||||
version = "0.0.1"
|
|
||||||
afterEvaluate {
|
|
||||||
from(components["release"])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
repositories {
|
scm {
|
||||||
maven {
|
url.set("https://github.com/priyanshujain/uatu")
|
||||||
name = "GitHubPackages"
|
connection.set("scm:git:git://github.com/priyanshujain/uatu.git")
|
||||||
url = uri("https://maven.pkg.github.com/priyanshujain/uatu")
|
developerConnection.set("scm:git:ssh://git@github.com/priyanshujain/uatu.git")
|
||||||
credentials {
|
|
||||||
username = System.getenv("GH_USERNAME") ?: System.getenv("GITHUB_ACTOR") ?: "priyanshujain"
|
|
||||||
password = System.getenv("GH_TOKEN") ?: System.getenv("GITHUB_TOKEN") ?: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ android {
|
|||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "0.0.1"
|
versionName = findProperty("uatu.version") as String? ?: "0.0.0-dev"
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ plugins {
|
|||||||
id("com.google.protobuf") version "0.9.5"
|
id("com.google.protobuf") version "0.9.5"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version = findProperty("uatu.version") as String? ?: "0.0.0-dev"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion.set(JavaLanguageVersion.of(17))
|
languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
|||||||
Reference in new issue
Block a user