Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/bump-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ on:
workflow_dispatch:
inputs:
bump:
description: "Release type: fix (0.1.0 -> 0.1.1), feature (-> 0.2.0), major (-> 1.0.0), or auto from CHANGELOG.md"
description: "Release type: fix (1.1.0 -> 1.1.1), feature (-> 1.2.0), major (-> 2.0.0), alpha / beta / rc (-> 1.2.0-alpha01 ...), stable (1.2.0-rc01 -> 1.2.0), or auto from CHANGELOG.md"
type: choice
options: [auto, fix, feature, major]
options: [auto, fix, feature, major, alpha, beta, rc, stable]
default: auto

permissions:
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/publish-maven-central.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Publish to Maven Central

# Publishes an already released version that isn't on Maven Central yet, from a branch made from its tag
# with the Maven Central setup added (e.g. central/v1.0.0). New versions are published by the Release workflow.
on:
workflow_dispatch:
inputs:
ref:
description: "Branch to publish, e.g. central/v1.0.0"
type: string
required: true

permissions:
contents: read

jobs:
publish:
name: Publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ inputs.ref }}
fetch-depth: 0
persist-credentials: false

- name: Check version
run: |
version=$(grep '^VERSION_NAME=' gradle.properties | cut -d= -f2)
if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|rc)[0-9]{2})?$ ]]; then
echo "::error::VERSION_NAME=${version} isn't X.Y.Z or X.Y.Z-(alpha|beta|rc)NN"
exit 1
fi
# Only versions that were already released and tagged; the Release workflow handles new ones.
if ! git rev-parse -q --verify "refs/tags/v${version}" >/dev/null; then
echo "::error::v${version} isn't tagged; release new versions with Bump version instead"
exit 1
fi
echo "Publishing ${version} from ${GITHUB_REF_NAME:-$(git rev-parse --short HEAD)}"

- uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad
with:
distribution: temurin
java-version: 17
- uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6

- name: Build and test
run: ./gradlew assembleRelease testDebugUnitTest

- name: Publish to Maven Central
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
34 changes: 24 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ jobs:
id: version
run: |
version=$(grep '^VERSION_NAME=' gradle.properties | cut -d= -f2)
# AndroidX-style versions only: 1.2.0, or 1.2.0-alpha01 / -beta01 / -rc01 for pre-releases.
if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|rc)[0-9]{2})?$ ]]; then
echo "::error::VERSION_NAME=${version} isn't X.Y.Z or X.Y.Z-(alpha|beta|rc)NN"
exit 1
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"
if [[ "$version" == *-* ]]; then echo "prerelease=true" >> "$GITHUB_OUTPUT"; else echo "prerelease=false" >> "$GITHUB_OUTPUT"; fi
if git rev-parse -q --verify "refs/tags/v${version}" >/dev/null; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "v${version} is already released"
Expand Down Expand Up @@ -58,29 +64,37 @@ jobs:
' CHANGELOG.md > notes.md
if [ ! -s notes.md ]; then echo "See CHANGELOG.md" > notes.md; fi

# Published before tagging, so a failed upload can be retried without a dangling tag.
- name: Publish to Maven Central
if: steps.version.outputs.exists == 'false'
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache

- name: Create tag and GitHub release
if: steps.version.outputs.exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
PRERELEASE: ${{ steps.version.outputs.prerelease }}
run: |
gh release create "v${VERSION}" --target "${GITHUB_SHA}" --title "v${VERSION}" --notes-file notes.md
flags=()
if [ "$PRERELEASE" = "true" ]; then flags+=(--prerelease); fi
gh release create "v${VERSION}" --target "${GITHUB_SHA}" --title "v${VERSION}" --notes-file notes.md "${flags[@]}"

- name: Close milestone
if: steps.version.outputs.exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
number=$(gh api "repos/${GITHUB_REPOSITORY}/milestones?state=open" --jq '.[] | select(.title == "Next release") | .number')
# Close the vX.Y.Z milestone, or rename and close a "Next release" one. Pre-releases leave it open.
if [[ "$VERSION" == *-* ]]; then exit 0; fi
number=$(gh api "repos/${GITHUB_REPOSITORY}/milestones?state=open" \
--jq "[.[] | select(.title == \"v${VERSION}\" or .title == \"Next release\")][0].number // empty")
if [ -n "$number" ]; then
gh api -X PATCH "repos/${GITHUB_REPOSITORY}/milestones/${number}" -f title="v${VERSION}" -f state=closed
fi

- name: Trigger JitPack build
if: steps.version.outputs.exists == 'false'
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
curl -s -o /dev/null -w "JitPack responded %{http_code}\n" --max-time 600 \
"https://jitpack.io/com/github/${GITHUB_REPOSITORY_OWNER}/${GITHUB_REPOSITORY#*/}/v${VERSION}/" || true
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Add entries under **Unreleased** in each pull request. The *Bump version* workfl
## [Unreleased]

### Added
- MIT license, code of conduct, and a demo GIF in the README showing each feature's effect in the sample app.
- MIT license and code of conduct.
- `NetworkLogger.maxTotalBodyChars` (default 12M characters) caps the bodies kept across all calls; the oldest bodies are dropped first, their calls stay listed.
- `AppActions.clearCacheInBackground()` clears the cache off the main thread.
- `TextInputItem`, `NumberInputItem` and `JsonInputItem` take an optional `subtitle`.
Expand All @@ -23,7 +23,9 @@ Add entries under **Unreleased** in each pull request. The *Bump version* workfl

### Changed
- The sample's fake update feed offers 1.1.0 now that the sample is 1.0.0.
- README install lines use a `LATEST_VERSION` placeholder that matches the JitPack badge, plus a version catalog example.
- **Published to Maven Central** as `io.github.appshipkit:devdeck` (and `devdeck-okhttp`, `devdeck-timber`, `devdeck-appdistribution`) instead of JitPack. Change your dependency lines from `com.github.appshipkit.devdeck:<module>:v1.0.0` to `io.github.appshipkit:<module>:<version>`; the JitPack repository is no longer needed. The library's own code and packages are unchanged.
- Versions follow AndroidX style: stable `1.2.0`, pre-releases `1.2.0-alpha01`, `-beta01`, `-rc01`.
- The README is reorganised with a table of contents, a quick start and shorter feature sections, and the demo GIF is gone.
- Drawer pages slide in and out instead of switching instantly.
- The network inspector's clear button sits in the count row, like the other lists.
- The device & app snapshot shows share, save and copy as small icons on the card; they are not part of the shared image.
Expand Down
21 changes: 16 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Review `.api` diffs like code: every line is a promise to library users.

## Versioning and releases

DevDeck uses [Semantic Versioning](https://semver.org/). The version lives in one place: `VERSION_NAME` in `gradle.properties`.
DevDeck uses [Semantic Versioning](https://semver.org/) with AndroidX-style pre-releases: `1.2.0` for stable releases, and `1.2.0-alpha01`, `1.2.0-beta01`, `1.2.0-rc01` before that (two-digit counters, alpha → beta → rc → stable). The version lives in one place: `VERSION_NAME` in `gradle.properties`, and the release workflow rejects any other format.

1. Run the **Bump version** workflow (Actions tab → *Bump version*) and pick the release type:

Expand All @@ -46,16 +46,22 @@ DevDeck uses [Semantic Versioning](https://semver.org/). The version lives in on
| `fix` | 1.0.0 → **1.0.1** | Bug fixes only |
| `feature` | 1.0.0 → **1.1.0** | New features or behaviour changes |
| `major` | 0.x → **1.0.0**, then 1.x → **2.0.0** | The first stable release, and later breaking changes: removed or renamed public API, changed defaults |
| `alpha` | 1.1.0 → **1.2.0-alpha01**, then → **1.2.0-alpha02** | Early previews; APIs may still change |
| `beta` | 1.2.0-alpha03 → **1.2.0-beta01** | Feature complete; fixes only from here |
| `rc` | 1.2.0-beta02 → **1.2.0-rc01** | Release candidate; ships unchanged unless a blocker turns up |
| `stable` | 1.2.0-rc01 → **1.2.0** | Drops the pre-release suffix |
| `auto` (default) | — | Picks one from the `[Unreleased]` entries in `CHANGELOG.md`: `### Removed` or the word `BREAKING` → major; `### Added` / `### Changed` → feature; only `### Fixed` → fix. While on 0.x, breaking changes stay a feature release, so 1.0.0 only happens when you choose `major` |

It updates `VERSION_NAME`, moves the *Unreleased* changelog entries under the new version, and opens a **Release vX.Y.Z** pull request.
2. Merge that pull request. The **Release** workflow then:
- builds and tests,
- creates the `vX.Y.Z` tag and a GitHub release with the changelog notes,
- renames the **Next release** milestone to `vX.Y.Z` and closes it,
- asks JitPack to build the tag.
- signs the four libraries and publishes them to Maven Central as `io.github.appshipkit:<module>:<version>` (they appear on [central.sonatype.com](https://central.sonatype.com/namespace/io.github.appshipkit) within about 30 minutes),
- creates the `vX.Y.Z` tag and a GitHub release with the changelog notes, marked as a pre-release for alpha, beta and rc versions,
- closes the `vX.Y.Z` milestone (stable releases only).

You can also bump locally with `scripts/bump-version.sh <fix|feature|major|auto|x.y.z>` and open the PR yourself.
**Publishing an older release:** to put an already tagged version on Maven Central (for example one released before DevDeck moved there), create a branch from its tag, add the Maven Central setup, and run the **Publish to Maven Central** workflow (Actions tab) with that branch. The tag itself stays as it was.

You can also bump locally with `scripts/bump-version.sh <fix|feature|major|alpha|beta|rc|stable|auto|version>` and open the PR yourself. `./gradlew publishToMavenLocal` installs the libraries in `~/.m2` to try them in another project.

## One-time repository setup

Expand All @@ -68,3 +74,8 @@ Do this once after creating the GitHub repository:
2. **Settings → Actions → General → Workflow permissions:** select *Read and write permissions* and tick *Allow GitHub Actions to create and approve pull requests* (needed by *Bump version*).
3. **Optional: `RELEASE_TOKEN` secret.** Pull requests opened with the default Actions token don't trigger CI, so the release PR's required checks won't run. Add a fine-grained personal access token with *Contents* and *Pull requests* write access as a repository secret named `RELEASE_TOKEN`, and *Bump version* will use it. Without it, re-run the checks by pushing an empty commit to the release branch, or merge as an admin.
4. **Labels and milestone:** run the **Set up repository** workflow once (Actions tab). It creates the `bug`, `enhancement`, `dependencies` and `skip-changelog` labels used by the templates, Dependabot and CI, plus the **Next release** milestone.
5. **Maven Central publishing.** The release workflow needs these, set up once by an admin of the appshipkit organization:
1. Sign in to the [Central Portal](https://central.sonatype.com) with GitHub, then *Namespaces → Add namespace* `io.github.appshipkit`. It shows a verification key; create a public repository with that exact name in the appshipkit organization, press *Verify*, then delete the repository.
2. *Account → Generate user token*. Save the token's username and password.
3. Create a signing key: `gpg --full-generate-key` (RSA 4096), publish the public key with `gpg --keyserver keyserver.ubuntu.com --send-keys <KEY_ID>`, and export the private key with `gpg --armor --export-secret-keys <KEY_ID>`.
4. Add four repository secrets (*Settings → Secrets and variables → Actions*): `MAVEN_CENTRAL_USERNAME` and `MAVEN_CENTRAL_PASSWORD` (the token), `SIGNING_KEY` (the exported private key, including the BEGIN/END lines) and `SIGNING_KEY_PASSWORD`.
Loading
Loading