Skip to content

Commit 2f8147b

Browse files
committed
P42-216: Update the build and add publishing tasks
1 parent 1113686 commit 2f8147b

File tree

10 files changed

+289
-19
lines changed

10 files changed

+289
-19
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# Mobi Lab MVVM library
1+
![Mobi Lab](docs/assets/mobilab-header-logo.png)
2+
# Mobi Lab MVVM
23

34
Mobi Lab MVVM library (mvvm-android) is a library for using the MVVM architecture in your Android application.
45

RELEASE_GUIDE.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Mobi Lab MVVM Library Release Guide
2+
3+
Disclaimer: This release guide assumes you are an employee of Mobi Lab and have access to the company's account in Codemagic CI.
4+
5+
Note: Every time you notice something in this guide is out-of-date or incorrect then fix it right away. Only then does this document have any value.
6+
7+
## Links
8+
9+
- Repository on GitHub: https://github.com/LabMobi/mvvm-android
10+
- Sonatype OSSRH Nexus UI: [https://s01.oss.sonatype.org](https://s01.oss.sonatype.org/)
11+
- Artifacts on Maven Central: https://repo1.maven.org/maven2/mobi/lab/mvvm/mvvm/ (can take some time)
12+
- Artifacts on Sonatype OSSRH: https://s01.oss.sonatype.org/content/groups/public/mobi/lab/mvvm/mvvm/ (available right away after publishing)
13+
- Original Sonatype OSSRH JIRA issue: https://issues.sonatype.org/browse/OSSRH-66630
14+
- Can be used to add user access
15+
- Project access Lab's internal Confluence: https://labmobi.atlassian.net/wiki/spaces/DEV/pages/15990951/Sonatype+Maven+Access+Credentials
16+
- Codemagic CI: https://codemagic.io/app/65310d8ec931a19db6581c3d/settings
17+
- OSSRH guide: https://central.sonatype.org/publish/publish-guide/
18+
19+
## Prerequisites
20+
21+
1. Access to Lab's accounts at Codemagic (https://codemagic.io/apps) and OSSRH https://s01.oss.sonatype.org/. For manual publishing access to credentials at https://confluence.lab.mobi/display/DEV/Sonatype+Maven+Access+Credentials
22+
23+
2. Make sure all the new features have been committed to `develop` branch.
24+
25+
3. Make sure all the functionality in the `develop` branch works.
26+
27+
4. Make sure the code in the `develop` builds correctly with the release build task:
28+
29+
```bash
30+
./gradlew buildAllRelease
31+
```
32+
33+
5. Make sure the "Compatible versions" list in the README.md is up-to-date
34+
35+
## Release process
36+
37+
1) Update the `CHANGELOG.md` document on the `develop` branch, add a section for this new release. If possible then follow https://keepachangelog.com/en/1.0.0/
38+
39+
Commit and push the change:
40+
41+
```bash
42+
git add CHANGELOG.md
43+
git commit -m "Add changelog for version X.Y.Z"
44+
git push
45+
```
46+
47+
2) Make sure the version code in the `develop` branch is correct. If needed then update the library version from the `build.gradle` file in the project root folder:
48+
49+
```groovy
50+
ext {
51+
// Current version of the library
52+
libraryVersion = "X.Y.Z"
53+
}
54+
```
55+
56+
Commit and push the changes
57+
58+
```bash
59+
git add build.gradle
60+
git commit -m "Update the version code to X.Y.Z"
61+
git push
62+
```
63+
64+
2) Make sure the develop build (`develop-builds (Development builds)`) you just started at Codemagic CI is ok and everything is in green.
65+
66+
3) Merge the `develop` branch to `main`.
67+
68+
```bash
69+
git checkout develop
70+
git pull
71+
git checkout main
72+
git pull
73+
git merge develop
74+
git push
75+
```
76+
77+
4) Start the release build (`release-builds (Release builds for verification (main branch only))`) at Codemagic CI from the `main` branch, make sure it builds fine and everything is in green.
78+
79+
5) Start the publish build (`publish-builds Publish to Maven builds (main branch only)`) at Codemagic CI from the `main` branch, make sure it builds fine and everything is in green.
80+
81+
6) Open up https://s01.oss.sonatype.org/, navigate to Build Promotion -> Staging repositories, check the published repository there.
82+
83+
- There should be a repository with the same version number
84+
- Download the `mvvm-x.y.z.aar` artifact from there, make sure it is ok.
85+
86+
7. Publish the staging repository at https://s01.oss.sonatype.org/ as follows:
87+
88+
- First mark it as `Closed`. This button triggers a validation process for your project. If the validation passes then proceed. Fix the issues otherwise
89+
- If you need to remove the repo and start again then use `Drop`
90+
91+
- Release the closed repository. Now the new artifact should be available shortly on the Maven Central at https://repo1.maven.org/maven2/mobi/lab/lab/mvvm/mvvm/
92+
93+
- NOTE: Depending in the time of day this can take some time (wait up to 1h and then complain under the original JIRA issue)
94+
95+
8. Create a new release and a Git tag in GitHub as follows:
96+
- Open up the GitHub release page at https://github.com/LabMobi/mvvm-android/releases, create a new release `vX.Y.Z`. Don't write an additional changelog there, just link to the changelog document.
97+
- Let it automatically create a tag for the release, in the form of "release-X.Y.Z".
98+
99+
9) OPTIONAL: Update the library in at least one of the projects using it to make sure everything is in order.
100+
101+
## Post-release actions
102+
103+
1. In the `develop` branch update the library version code to a new version so the `develop` branch code and the released code does not have a matching version.
104+
105+
106+
```
107+
git checkout develop
108+
git pull
109+
```
110+
111+
- Keep the release number in the style of X.Y.Z.
112+
113+
114+
```groovy
115+
ext {
116+
// Current version of the library
117+
libraryVersion = "X.Y.Z"
118+
}
119+
```
120+
121+
and commit and push the changes:
122+
123+
```bash
124+
git add build.gradle
125+
git commit -m "Update the version code to X.Y.Z"
126+
git push
127+
```
128+
129+
## EXTRA: Manual publishing
130+
131+
If for some reason CI can't be used for publishing then manual publishing process is overall the same as in CI, just skip the CI parts and
132+
133+
1) Rename the `publish.properties_TEMPLATE` and fill it with the correct values.
134+
135+
2) Check if the local publishing works by
136+
137+
```bash
138+
./gradlew publishToMavenLocal
139+
```
140+
141+
The artifacts should be available under your user folder at `~/.m2/repository/mobi/lab/mvvm/mvvm/`
142+
143+
3) If everything is in order then publish to OSSRH:
144+
145+
```bash
146+
./gradlew buildAndPublishRelease
147+
```
148+
149+
After that follow the steps from OSSRH nexus described above.
150+
151+
NOTE: To make the PGP private key to a single-line for props you can use the following command:
152+
153+
```bash
154+
awk -v ORS='\\n' '1' mobi_lab_maven_artifact_PRIVATE_KEY.pgp > singlelinekey.txt
155+
```
156+

SECURITY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
Please send an email about the vulnerability to [email protected].
1.35 MB
Loading

mvvm/build.gradle

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ repositories {
33
mavenCentral()
44
}
55

6+
apply plugin: 'maven-publish'
7+
apply plugin: 'signing'
68
apply plugin: 'com.android.library'
79
apply plugin: 'kotlin-android'
810

@@ -13,6 +15,12 @@ android {
1315

1416
kotlinOptions {
1517
jvmTarget = "1.8"
18+
19+
// For Kotlin API strict mode.
20+
// In the future we should be able to do it easier.
21+
// When https://youtrack.jetbrains.com/issue/KT-37652 is fixed
22+
// then we can use the module annotation to enable this instead of the compiler flag.
23+
freeCompilerArgs += '-Xexplicit-api=strict'
1624
}
1725

1826
compileOptions {
@@ -41,6 +49,16 @@ android {
4149
}
4250
}
4351
}
52+
53+
lint {
54+
fatal "StopShip"
55+
}
56+
57+
publishing {
58+
singleVariant("release") {
59+
withSourcesJar()
60+
}
61+
}
4462
}
4563

4664
dependencies {
@@ -61,3 +79,72 @@ buildLibDebug.description = "Build the debug version of components lib"
6179
task buildLibRelease(dependsOn: ["buildLibDebug"])
6280
buildLibRelease.group = GROUP_CI_BUILD_TASKS
6381
buildLibRelease.description = "Build the release version of components lib"
82+
83+
task buildAndPublishRelease(dependsOn: ['buildLibRelease', 'publish'])
84+
buildAndPublishRelease.group = GROUP_CI_BUILD_TASKS
85+
buildAndPublishRelease.description = "Build the library release version and publish it"
86+
87+
publish.mustRunAfter tasks.findByPath('buildLibRelease')
88+
89+
Properties properties = new Properties()
90+
try {
91+
properties.load(project.rootProject.file('publish.properties').newDataInputStream())
92+
} catch (Exception ignored) {
93+
println "publish.properties missing"
94+
}
95+
96+
afterEvaluate {
97+
publishing {
98+
publications {
99+
release(MavenPublication) {
100+
groupId = 'mobi.lab.mvvm'
101+
artifactId = 'mvvm'
102+
from components.release
103+
pom {
104+
packaging = 'aar'
105+
name = 'Mobi Lab MVVM library.'
106+
description = 'Mobi Lab MVVM is a library for using the MVVM architecture in your Android application.'
107+
url = 'https://github.com/LabMobi/mvvm-android'
108+
109+
licenses {
110+
license {
111+
name = 'The MIT License'
112+
url = 'https://opensource.org/licenses/mit-license.php'
113+
}
114+
}
115+
developers {
116+
developer {
117+
name = properties.getProperty("publish_developer_name")
118+
name = properties.getProperty("publish_developer_name")
119+
email = properties.getProperty("publish_developer_email")
120+
organization = properties.getProperty("publish_developer_organization")
121+
organizationUrl = properties.getProperty("publish_developer_organization_url")
122+
}
123+
}
124+
scm {
125+
connection = 'https://github.com/LabMobi/mvvm-android.git'
126+
developerConnection = 'https://github.com/LabMobi/mvvm-android.git'
127+
url = 'https://github.com/LabMobi/mvvm-android'
128+
}
129+
}
130+
}
131+
}
132+
repositories {
133+
maven {
134+
name = "OSSRH"
135+
url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2"
136+
credentials {
137+
username = properties.getProperty("publish_ossrh_username")
138+
password = properties.getProperty("publish_ossrh_password")
139+
}
140+
}
141+
}
142+
}
143+
144+
signing {
145+
def signingKey = properties.getProperty("signing_key")
146+
def signingPassword = properties.getProperty("signing_password")
147+
useInMemoryPgpKeys(signingKey, signingPassword)
148+
sign publishing.publications
149+
}
150+
}

mvvm/src/main/java/mobi/lab/mvvm/MvvmExtensions.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import androidx.lifecycle.ViewModelProvider
1212
import androidx.lifecycle.ViewModelStoreOwner
1313
import androidx.savedstate.SavedStateRegistryOwner
1414

15-
fun <T : Any> MutableLiveData<T>.asLiveData() = this as LiveData<T>
16-
fun <T : Any> MutableLiveData<T?>.asNullableLiveData() = this as LiveData<T?>
15+
public fun <T : Any> MutableLiveData<T>.asLiveData(): LiveData<T> = this
16+
public fun <T : Any> MutableLiveData<T?>.asNullableLiveData(): LiveData<T?> = this
1717

1818
/**
1919
* Activity based Assisted Injection
2020
*
2121
* Convenience function to init ViewModels lazily using Assisted Injection.
2222
* Wraps the assisted factory invocation with a ViewModelProvider.Factory
2323
*/
24-
inline fun <reified VM : ViewModel> ComponentActivity.assistedViewModels(
24+
public inline fun <reified VM : ViewModel> ComponentActivity.assistedViewModels(
2525
crossinline assistedViewModelFactory: () -> VM
2626
): Lazy<VM> {
2727
return lazy(LazyThreadSafetyMode.NONE) { createViewModel(this, assistedViewModelFactory) }
@@ -33,7 +33,7 @@ inline fun <reified VM : ViewModel> ComponentActivity.assistedViewModels(
3333
* Convenience function to init ViewModels lazily using Assisted Injection.
3434
* Wraps the assisted factory invocation with a ViewModelProvider.Factory
3535
*/
36-
inline fun <reified VM : ViewModel> Fragment.assistedViewModels(
36+
public inline fun <reified VM : ViewModel> Fragment.assistedViewModels(
3737
crossinline assistedViewModelFactory: () -> VM
3838
): Lazy<VM> {
3939
return lazy(LazyThreadSafetyMode.NONE) { createViewModel(this, assistedViewModelFactory) }
@@ -45,7 +45,7 @@ inline fun <reified VM : ViewModel> Fragment.assistedViewModels(
4545
* Convenience function to init ViewModels lazily using Assisted Injection and get access to SavedStateHandle.
4646
* Wraps the assisted factory invocation with a AbstractSavedStateViewModelFactory
4747
*/
48-
inline fun <reified VM : ViewModel> ComponentActivity.assistedSavedStateViewModels(
48+
public inline fun <reified VM : ViewModel> ComponentActivity.assistedSavedStateViewModels(
4949
crossinline initialStateFactory: () -> Bundle? = { null },
5050
crossinline savedStateViewModelFactory: (handle: SavedStateHandle) -> VM
5151
): Lazy<VM> {
@@ -58,7 +58,7 @@ inline fun <reified VM : ViewModel> ComponentActivity.assistedSavedStateViewMode
5858
* Convenience function to init ViewModels lazily using Assisted Injection and get access to SavedStateHandle.
5959
* Wraps the assisted factory invocation with a AbstractSavedStateViewModelFactory
6060
*/
61-
inline fun <reified VM : ViewModel> Fragment.assistedSavedStateViewModels(
61+
public inline fun <reified VM : ViewModel> Fragment.assistedSavedStateViewModels(
6262
crossinline initialStateFactory: () -> Bundle? = { null },
6363
crossinline savedStateViewModelFactory: (handle: SavedStateHandle) -> VM
6464
): Lazy<VM> {
@@ -68,7 +68,7 @@ inline fun <reified VM : ViewModel> Fragment.assistedSavedStateViewModels(
6868
/**
6969
* Internal function to create SavedStateViewModels by invoking a custom factory
7070
*/
71-
inline fun <reified VM : ViewModel> createSavedStateViewModel(
71+
public inline fun <reified VM : ViewModel> createSavedStateViewModel(
7272
viewModelStoreOwner: ViewModelStoreOwner,
7373
savedStateRegistryOwner: SavedStateRegistryOwner,
7474
crossinline initialStateFactory: () -> Bundle?,
@@ -87,7 +87,7 @@ inline fun <reified VM : ViewModel> createSavedStateViewModel(
8787
/**
8888
* Internal function to create ViewModels by invoking a custom factory
8989
*/
90-
inline fun <reified VM : ViewModel> createViewModel(
90+
public inline fun <reified VM : ViewModel> createViewModel(
9191
viewModelStoreOwner: ViewModelStoreOwner,
9292
crossinline viewModelFactory: () -> VM
9393
): VM {

mvvm/src/main/java/mobi/lab/mvvm/MvvmLiveDataExtensions.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ import androidx.lifecycle.LifecycleOwner
44
import androidx.lifecycle.LiveData
55
import androidx.lifecycle.Observer
66

7-
interface MvvmLiveDataExtensions {
8-
fun getLifecycleOwner(): LifecycleOwner
7+
public interface MvvmLiveDataExtensions {
8+
public fun getLifecycleOwner(): LifecycleOwner
99

10-
fun <T> LiveData<T>.onEachNotNull(block: (T) -> Unit) {
10+
public fun <T> LiveData<T>.onEachNotNull(block: (T) -> Unit) {
1111
this.observe(getLifecycleOwner(), Observer { it?.let(block) })
1212
}
1313

14-
fun <T> LiveData<T>.onEach(block: (T?) -> Unit) {
14+
public fun <T> LiveData<T>.onEach(block: (T?) -> Unit) {
1515
this.observe(getLifecycleOwner(), Observer { block(it) })
1616
}
1717

1818
@Suppress("UNCHECKED_CAST")
19-
fun <T, E : SingleEvent<T>> LiveData<E>.onEachEvent(block: (T) -> Unit) {
19+
public fun <T, E : SingleEvent<T>> LiveData<E>.onEachEvent(block: (T) -> Unit) {
2020
this.observe(getLifecycleOwner(), SingleEventObserver<T> { block(it) } as Observer<E>)
2121
}
2222
}

0 commit comments

Comments
 (0)