diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3735cb5..33ba420 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,7 +1,8 @@
name: Build and test
on:
# Build PRs and branches.
- pull_request:
+ pull_request_target:
+ types: [ opened, synchronize, reopened ]
paths-ignore:
- .github/workflows/deploy-tagged.yml
push:
@@ -23,10 +24,11 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v3
-
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: ${{ matrix.java }}
distribution: 'temurin'
@@ -46,3 +48,58 @@ jobs:
- name: Build and test
run: ./gradlew build --stacktrace
+
+ publish-snapshot:
+ name: Publish snapshot to GitHub Packages
+ runs-on: ubuntu-latest
+ needs: build
+ if: github.event_name == 'pull_request_target' || (github.event_name == 'push' && github.ref == 'refs/heads/master')
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ - name: Get base version
+ id: get-version
+ run: |
+ BASE_VERSION=$(grep -iE "version([ ]*)=" gradle.properties | cut -f 2 -d "=" | tr -d '[:space:]')
+ # Strip any existing -SNAPSHOT suffix so we can re-apply it cleanly
+ BASE_VERSION="${BASE_VERSION%-SNAPSHOT}"
+ echo "base_version=${BASE_VERSION}" >> $GITHUB_OUTPUT
+
+ - name: Determine snapshot version
+ id: snapshot-version
+ run: |
+ if [ "${{ github.event_name }}" == "pull_request_target" ]; then
+ SNAPSHOT_VERSION="${{ steps.get-version.outputs.base_version }}-PR-${{ github.event.pull_request.number }}-SNAPSHOT"
+ else
+ SNAPSHOT_VERSION="${{ steps.get-version.outputs.base_version }}-SNAPSHOT"
+ fi
+ echo "snapshot_version=${SNAPSHOT_VERSION}" >> $GITHUB_OUTPUT
+ echo "Publishing snapshot version: ${SNAPSHOT_VERSION}"
+
+ - name: Setup JDK
+ uses: actions/setup-java@v5
+ with:
+ java-version: 8
+ distribution: 'temurin'
+
+ - name: Setup Gradle
+ uses: gradle/gradle-build-action@v2
+ with:
+ gradle-version: wrapper
+ gradle-home-cache-cleanup: true
+ gradle-home-cache-includes: |
+ caches
+ notifications
+ jdks
+
+ - name: Publish snapshot to GitHub Packages
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_ACTOR: ${{ github.actor }}
+ run: ./gradlew publishReleasePublicationToGitHubPackagesRepository -Pversion=${{ steps.snapshot-version.outputs.snapshot_version }} --stacktrace
diff --git a/.github/workflows/cleanup-snapshot.yml b/.github/workflows/cleanup-snapshot.yml
new file mode 100644
index 0000000..f43a04d
--- /dev/null
+++ b/.github/workflows/cleanup-snapshot.yml
@@ -0,0 +1,56 @@
+name: Clean up PR snapshot
+
+on:
+ pull_request:
+ types: [closed]
+
+jobs:
+ cleanup-snapshot:
+ name: Delete PR snapshot from GitHub Packages
+ runs-on: ubuntu-latest
+ # Only run when the PR was actually merged, not just closed.
+ if: github.event.pull_request.merged == true
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Get base version
+ id: get-version
+ run: |
+ BASE_VERSION=$(grep -iE "version([ ]*)=" gradle.properties | cut -f 2 -d "=" | tr -d '[:space:]')
+ # Strip any existing -SNAPSHOT suffix so we can re-apply it cleanly
+ BASE_VERSION="${BASE_VERSION%-SNAPSHOT}"
+ echo "base_version=${BASE_VERSION}" >> $GITHUB_OUTPUT
+
+ - name: Delete PR snapshot from GitHub Packages
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ SNAPSHOT_VERSION="${{ steps.get-version.outputs.base_version }}-PR-${{ github.event.pull_request.number }}-SNAPSHOT"
+ echo "Looking for package version: ${SNAPSHOT_VERSION}"
+
+ # Retrieve the numeric ID of any published version matching this snapshot.
+ # --paginate ensures all pages are scanned; --jq filters on each page.
+ VERSION_IDS=$(gh api \
+ --paginate \
+ -H "Accept: application/vnd.github+json" \
+ "/orgs/${{ github.repository_owner }}/packages/maven/com.uploadcare.uploadcare/versions" \
+ --jq ".[] | select(.name == \"${SNAPSHOT_VERSION}\") | .id" 2>/dev/null || true)
+
+ if [ -z "$VERSION_IDS" ]; then
+ echo "No published version found for ${SNAPSHOT_VERSION} — nothing to delete."
+ exit 0
+ fi
+
+ while IFS= read -r VERSION_ID; do
+ echo "Deleting version ID ${VERSION_ID} (${SNAPSHOT_VERSION}) …"
+ gh api --method DELETE \
+ -H "Accept: application/vnd.github+json" \
+ "/orgs/${{ github.repository_owner }}/packages/maven/com.uploadcare.uploadcare/versions/${VERSION_ID}"
+ echo "Deleted version ID ${VERSION_ID}."
+ done <<< "$VERSION_IDS"
+ echo "Done cleaning up ${SNAPSHOT_VERSION}."
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 8d45a23..b112cfd 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/deploy-tagged.yml b/.github/workflows/deploy-tagged.yml
index 921d68a..cfba8de 100644
--- a/.github/workflows/deploy-tagged.yml
+++ b/.github/workflows/deploy-tagged.yml
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v6
with:
ref: ${{ env.TAG }}
@@ -37,7 +37,7 @@ jobs:
fi
- name: Setup JDK and Maven
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: 8
distribution: "temurin"
diff --git a/README.md b/README.md
index 26041f1..37e1410 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,74 @@ If you are using the kotlin style `build.gradle.kts`:
implementation("com.uploadcare:uploadcare:3.5.1")
```
+## Snapshot Builds (Pre-release)
+
+Snapshot builds are published to [GitHub Packages](https://github.com/uploadcare/uploadcare-java/packages) automatically:
+
+- **From pull requests**: version format `{version}-PR-{pr-number}-SNAPSHOT` (e.g. `3.5.3-PR-42-SNAPSHOT`)
+- **From the `master` branch**: version format `{version}-SNAPSHOT` (e.g. `3.5.3-SNAPSHOT`)
+
+To consume a snapshot build, add the GitHub Packages repository and authenticate with a [personal access token](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry#authenticating-to-github-packages) (PAT) that has `read:packages` scope.
+
+### Maven (snapshot)
+
+Add to your `~/.m2/settings.xml`:
+
+```xml
+
+
+
+ uploadcare-snapshots
+ YOUR_GITHUB_USERNAME
+ YOUR_GITHUB_PAT
+
+
+
+```
+
+Add to your `pom.xml`:
+
+```xml
+
+
+ uploadcare-snapshots
+ https://maven.pkg.github.com/uploadcare/uploadcare-java
+
+ true
+
+
+
+
+
+
+ com.uploadcare
+ uploadcare
+ 3.5.3-SNAPSHOT
+
+
+```
+
+### Gradle (snapshot)
+
+Add to your `build.gradle` (or `build.gradle.kts`):
+
+```groovy
+repositories {
+ maven {
+ name = "GitHubPackages"
+ url = uri("https://maven.pkg.github.com/uploadcare/uploadcare-java")
+ credentials {
+ username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
+ password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
+ }
+ }
+}
+
+dependencies {
+ implementation("com.uploadcare:uploadcare:3.5.3-SNAPSHOT")
+}
+```
+
## Examples
Get your [API keys](https://uploadcare.com/docs/start/settings/#keys) to proceed with the examples below.
diff --git a/build.gradle.kts b/build.gradle.kts
index bf62e79..2b2583a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -31,12 +31,28 @@ dependencies {
// Setup global publishing repository settings.
signing {
+ setRequired({ isReleaseVersion })
useGpgCmd()
sign(publishing.publications)
}
+// Skip signing entirely for non-release (snapshot) builds.
+tasks {
+ withType().configureEach {
+ onlyIf { isReleaseVersion }
+ }
+}
+
publishing {
repositories {
+ maven {
+ name = "GitHubPackages"
+ url = uri("https://maven.pkg.github.com/uploadcare/uploadcare-java")
+ credentials {
+ username = System.getenv("GITHUB_ACTOR") ?: ""
+ password = System.getenv("GITHUB_TOKEN") ?: ""
+ }
+ }
maven {
// Dynamically select either Maven Central or na Internal repository depending on the value of uploadcare.publish.type / UPLOADCARE_PUBLISH_TYPE
name = "selected"