Skip to content

Commit

Permalink
Set up publishing for Maven Central (#115)
Browse files Browse the repository at this point in the history
Initial work to publish to Maven Central

Co-authored-by: Drew Hannay <[email protected]>
  • Loading branch information
drewhannay and Drew Hannay authored Feb 18, 2021
1 parent 269b863 commit 8e98ad5
Show file tree
Hide file tree
Showing 12 changed files with 299 additions and 225 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/deploy-snapshot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Deploy snapshot
on:
push:
branches:
- master
jobs:
publish:
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, 'Prepare for release') }}
steps:
- uses: actions/checkout@v2

- name: Cache Gradle Files
uses: actions/cache@v2
with:
path: |
~/.gradle/caches/
~/.gradle/wrapper/
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Set up Java
uses: actions/setup-java@v1
with:
java-version: 1.8

- name: Build
run: ./gradlew build

- name: Publish package
run: ./gradlew publishAllPublicationsToSonatypeSnapshotRepository
env:
SONATYPE_USER: ${{ secrets.SONATYPE_USER }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
27 changes: 27 additions & 0 deletions .github/workflows/publish-maven-central.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Publish package to the Maven Central Repository
on:
release:
types: [published]
branches:
- master
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Java
uses: actions/setup-java@v1
with:
java-version: 1.8

- name: Build
run: ./gradlew build

- name: Publish package
run: ./gradlew publishAllPublicationsToMavenCentralRepository
env:
SONATYPE_USER: ${{ secrets.SONATYPE_USER }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SPYGLASS_GPG_PRIVATE_KEY: ${{ secrets.SPYGLASS_GPG_PRIVATE_KEY }}
SPYGLASS_GPG_PRIVATE_KEY_PASSWORD: ${{ secrets.SPYGLASS_GPG_PRIVATE_KEY_PASSWORD }}
37 changes: 23 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
Spyglass [![Build Status](https://img.shields.io/github/workflow/status/linkedin/Spyglass/Merge%20checks)](https://img.shields.io/github/workflow/status/linkedin/Spyglass/Merge%20checks)
========
# Spyglass [![Build Status](https://img.shields.io/github/workflow/status/linkedin/Spyglass/Merge%20checks)](https://img.shields.io/github/workflow/status/linkedin/Spyglass/Merge%20checks)

A powerful Android library that provides highly-customizable widgets (with smart defaults) to easily add social-media-esque mention (aka tag) support to your app

*For a broad overview, check out our [blog post](https://engineering.linkedin.com/android/open-sourcing-spyglass-flexible-library-implementing-mentions-android) at the LinkedIn engineering blog.*

Features
--------
## Features

- A subclass of `EditText` that contains enhanced functionality in order to tokenize user input and display mentions
- A custom view, similar to a `MultiAutoCompleteTextView`, that displays suggestions in an embedded `ListView` rather than a `Popup`
- Custom tokenizer interface, including a default implementation containing several options for customization
- Designed to handle suggestions dynamically as are retrieved from multiple data sources
- Supports both implicit and explicit (i.e. "@User Name") mentions

Getting Started
---------------
## Getting Started

Grab via Maven:
```xml
Expand All @@ -30,8 +27,7 @@ or Gradle:
api 'com.linkedin.android.spyglass:spyglass:2.2.0'
```

Overview
---------------
## Overview

Spyglass is divided into three, customizable layers: *tokenization*, *suggestions*, and *mentions*. Together, these layers form the update lifecycle used within Spyglass:

Expand Down Expand Up @@ -66,21 +62,34 @@ As the suggestions come in from multiple data sources, the suggestions must be d

All mentions that Spyglass insert must be a subclass of the `MentionSpan`. By default, you can easily tweak how your mentions appear (i.e. highlight and text colors). Additionally, you may alter how they behave when they are deleted via multi-stage deletions. We use this extensively in the LinkedIn app to allow users to delete only the last name of a mentioned member (leaving just the first name).

Usage
-----
## Usage

To use Spyglass, you have two options: the `MentionsEditText` and the `RichEditorView`.

The `MentionsEditText` is a subclass of `EditText`. It contains extra functionality for tokenizing user input into query tokens and inserting new mentions to be displayed. Note that it does not have any view associated with displaying suggestions. You must provide that. This gives you the most power to customize how your mentions-enabled text box feels and behaves. See the "Grid Mentions" example in the sample app for a demo.

The `RichEditorView` is the quickest way to add mentions into your app. It is built on top of the aforementioned `MentionsEditText` and displays suggestions in an embedded `ListView`. It serves a similar functionality as Android's `MultiAutoCompleteTextView`. Note that you can still alter how suggestion items are displayed in the list, and you can still alter the tokenization and mention displaying options used by the underlying `MentionsEditText`.

Sample App
----------
## Sample App

The ''spyglass-sample'' app contains several examples of using the library. For more detailed information, see the documentation [here](spyglass-sample/README.md).

Testing
-------
## Testing

We use the Robolectric framework coupled with Mockito for our unit tests. You can run them via the `gradle clean test` command.

## Snapshots

You can use snapshot builds to test the latest unreleased changes. A new snapshot is published
after every merge to the main branch by the [Deploy Snapshot Github Action workflow](.github/workflows/deploy-snapshot.yml).

Just add the Sonatype snapshot repository to your Gradle scripts:
```gradle
repositories {
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
```

You can find the latest snapshot version to use in the [gradle.properties](gradle.properties) file.
39 changes: 20 additions & 19 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
Releasing
=========
# Releasing

1. Change the version in `gradle.properties` to a non-SNAPSHOT version.
2. Update the `CHANGELOG.md` for the impending release.
3. Update the `README.md` with the new version.
4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version)
5. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version)
6. `./gradlew clean bintrayUpload`
7. Update the `gradle.properties` to the next SNAPSHOT version.
8. `git commit -am "Prepare next development version."`
9. `git push && git push --tags`
1. Change the version in `gradle.properties` to a non-SNAPSHOT version.
2. Update the `CHANGELOG.md` for the impending release.
3. Update the `README.md` with the new version.
4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version)
5. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version)
6. Update the `gradle.properties` to the next SNAPSHOT version.
7. `git commit -am "Prepare next development version."`
8. `git push && git push --tags`
9. Create a new release in the releases tab on GitHub
10. Wait for the [publish-maven-central.yml](.github/workflows/publish-maven-central.yml) action to complete.
11. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact.

## How it works

Prerequisites
-------------
The [deploy-snapshot.yml](.github/workflows/deploy-snapshot.yml) workflow runs on every
push to the main branch as long as the commit message does not contain `Prepare for release`. This
workflow calls Gradle to publish to the Sonatype snapshot repository.

First, you will need a Bintray account with access to the [linkedin-spyglass](https://bintray.com/linkedin-spyglass) organization.

Then, set the following environment variables:

* `BINTRAY_USER` - Bintray username
* `BINTRAY_KEY` - Bintray API key for the given user account
For actual releases, there is a separate [publish-maven-central.yml](.github/workflows/publish-maven-central.yml)
workflow which runs after a new release is created in the GitHub UI. This will call Gradle on the
tagged release commit and upload to the staging repository. After that completes, you will need to
go and promote the artifacts to production.
13 changes: 8 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
buildscript {

repositories {
jcenter()
google()
mavenCentral()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:4.1.2'
}
}

Expand All @@ -22,8 +22,11 @@ ext {

subprojects {
repositories {
jcenter()
google()
mavenCentral()
jcenter()
}
tasks.withType(Javadoc).all { enabled = false }

group = GROUP_ID
version = VERSION_NAME
}
88 changes: 88 additions & 0 deletions gradle/publishing.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Ideally AGP should provide sources and javadoc integration for their components:
// https://issuetracker.google.com/issues/145670440
tasks.register("sourcesJar", Jar) {
classifier 'sources'
from android.sourceSets.main.java.srcDirs
}

tasks.register("javadoc", Javadoc) {
failOnError false
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

tasks.register("javadocJar", Jar) {
dependsOn javadoc
classifier 'javadoc'
from javadoc.destinationDir
}

// AGP creates the components in afterEvaluate, so we need to use it too
// https://developer.android.com/studio/build/maven-publish-plugin
afterEvaluate {
publishing {
publications {
maven(MavenPublication) {
from components.release

artifact sourcesJar
artifact javadocJar

pom {
name = 'Spyglass'
description = 'Flexible library extending EditText to support mentions on Android.'
url = 'https://github.com/linkedin/Spyglass'
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'com.linkedin'
name = 'LinkedIn Corp'
}
}
scm {
connection = 'scm:git:git://github.com/linkedin/Spyglass.git'
developerConnection = 'scm:git:ssh://github.com:linkedin/Spyglass.git'
url = 'https://github.com/linkedin/Spyglass/tree/master'
}
}

repositories {
def sonatypeUsername = System.getenv("SONATYPE_USER")
def sonatypePassword = System.getenv("SONATYPE_PASSWORD")
maven {
name = "sonatypeSnapshot"
url = "https://oss.sonatype.org/content/repositories/snapshots"
credentials {
username = sonatypeUsername
password = sonatypePassword
}
}
maven {
name = "mavenCentral"
url = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
credentials {
username = sonatypeUsername
password = sonatypePassword
}
}
}
}
}
}

// SPYGLASS_GPG_PRIVATE_KEY should contain the armoured private key that
// starts with -----BEGIN PGP PRIVATE KEY BLOCK-----
// It can be obtained with gpg --armour --export-secret-keys KEY_ID
def signingKey = System.getenv("SPYGLASS_GPG_PRIVATE_KEY")
def signingPassword = System.getenv("SPYGLASS_GPG_PRIVATE_KEY_PASSWORD")
signing {
required { signingKey != null && signingPassword != null }
useInMemoryPgpKeys(signingKey, signingPassword)
sign publishing.publications.maven
}
}
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
3 changes: 1 addition & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Wed Sep 26 10:14:49 PDT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip
Loading

0 comments on commit 8e98ad5

Please sign in to comment.