OXYGENHUB
◆ main oxygenhub-android / .flow / pipeline.kdl
4.8 KiB · last changed Check the changelog on the WASM tier 1 day ago source blame history raw
1
// The OxygenHub Android app's pipeline (OxygenFlow, #19). Every push runs
2
// the unit tests with coverage and a debug build in OxygenFlow's Android
3
// image, with no network: the JDK, the Android SDK and NDK, Gradle,
4
// cargo-ndk, rust-core's crates and the app's Gradle dependencies are all
5
// in the image (oxygenflow/images/android). Rebuild and re-pin it when the
6
// app's SDK, Gradle or dependency versions change, or rust-core's
7
// Cargo.lock does. Locally, ./gradlew :app:createDebugUnitTestCoverageReport
8
// runs the same tests.
9
schema-version 1
10
11
// Cheap checks on the WASM tier (oxygenflow#96): OxygenFlow's checks module,
12
// copied from oxygenflow/.flow/checks.wasm (built there from
13
// crates/flow-checks; copy it again when it changes). No image and no KVM,
14
// so any runner with the WASM tier takes it: a phone, plex, windows-1.
15
sandbox "wasm" {
16
    runtime "wasm"
17
    memory-limit "64MiB"
18
}
19
20
// The changelog's shape, and a section for the version gradle.properties says, so a
21
// release never finds its notes missing.
22
job "changelog" {
23
    sandbox "wasm"
24
    scope "CHANGELOG.md" "gradle.properties" ".flow/checks.wasm"
25
    exec ".flow/checks.wasm" "changelog" "CHANGELOG.md" "gradle.properties"
26
}
27
28
sandbox "android" {
29
    runtime "microvm"
30
    rootfs "cas://blob/d5dabda3166dee2a2fdaca1b245c6e677aa95066beff8b8bb829987cb2fcacd7"
31
    memory-limit "8GiB"
32
    cpu-limit 4
33
    // Loopback only, still offline: Gradle will not start without a
34
    // usable interface for its file-lock listener.
35
    network "loopback"
36
    // Gradle reads dependencies from the image's read-only cache and
37
    // writes its own state under /tmp.
38
    env {
39
        ANDROID_HOME "/opt/android-sdk"
40
        JAVA_HOME "/usr/lib/jvm/java-17-openjdk-amd64"
41
        GRADLE_RO_DEP_CACHE "/opt/gradle-home/caches"
42
        GRADLE_USER_HOME "/tmp/gradle"
43
        CARGO_INCREMENTAL "0"
44
    }
45
}
46
47
job "test" {
48
    sandbox "android"
49
    timeout "60m"
50
    // rust-core (with oxy-core and the runner) for two ABIs is most of the
51
    // build: kept from the last passing run, so only what changed builds.
52
    mount {
53
        source "ephemeral://disk"
54
        target "/src/rust-core/target"
55
        size "20GiB"
56
        cache "rust-core-target"
57
        key "rust-core/Cargo.lock"
58
    }
59
    // The workspace has room for the checkout and a little more: the app's
60
    // build output and Gradle's project cache get disks of their own.
61
    mount {
62
        source "ephemeral://disk"
63
        target "/src/app/build"
64
        size "8GiB"
65
    }
66
    mount {
67
        source "ephemeral://disk"
68
        target "/src/.gradle"
69
        size "2GiB"
70
    }
71
    exec "bash" "scripts/ci.sh"
72
    output {
73
        artifact "junit" {
74
            path "/src/junit.xml"
75
            when "always"
76
        }
77
        artifact "coverage" {
78
            path "/src/coverage.xml"
79
            when "always"
80
        }
81
    }
82
}
83
84
// The release's secrets checked in seconds, with no build (#7): the
85
// keystore's SHA-256, the key its password opens and Firebase's JSON.
86
// By hand only: oh run start --job release-check.
87
job "release-check" {
88
    sandbox "android"
89
    timeout "5m"
90
    on {
91
        manual
92
    }
93
    secret "android-keystore" {
94
        mount-path "/run/secrets/android-keystore"
95
    }
96
    secret "android-keystore-password" {
97
        mount-path "/run/secrets/android-keystore-password"
98
    }
99
    secret "firebase-config" {
100
        mount-path "/run/secrets/firebase-config"
101
    }
102
    exec "bash" "scripts/release-check.sh"
103
}
104
105
// A signed release APK when the version in gradle.properties changes (#7),
106
// for a release on oxygenhub.io. The keystore and its password are the
107
// repository's secrets, mounted as files (never in the environment).
108
job "release" {
109
    sandbox "android"
110
    timeout "60m"
111
    depends-on "test"
112
    scope "gradle.properties"
113
    mount {
114
        source "ephemeral://disk"
115
        target "/src/rust-core/target"
116
        size "20GiB"
117
        cache "rust-core-target"
118
        key "rust-core/Cargo.lock"
119
    }
120
    // The workspace has room for the checkout and a little more: the app's
121
    // build output and Gradle's project cache get disks of their own.
122
    mount {
123
        source "ephemeral://disk"
124
        target "/src/app/build"
125
        size "8GiB"
126
    }
127
    mount {
128
        source "ephemeral://disk"
129
        target "/src/.gradle"
130
        size "2GiB"
131
    }
132
    secret "android-keystore" {
133
        mount-path "/run/secrets/android-keystore"
134
    }
135
    secret "android-keystore-password" {
136
        mount-path "/run/secrets/android-keystore-password"
137
    }
138
    // Firebase's client settings (google-services.json) for alerts (#16).
139
    secret "firebase-config" {
140
        mount-path "/run/secrets/firebase-config"
141
    }
142
    exec "bash" "scripts/release.sh"
143
    output {
144
        artifact "oxygenhub-android-universal.apk" {
145
            path "/src/dist/oxygenhub-android-universal.apk"
146
        }
147
        artifact "SHA256SUMS" {
148
            path "/src/dist/SHA256SUMS"
149
        }
150
    }
151
}