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
50 changes: 50 additions & 0 deletions .github/workflows/publish_android_maven_central.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Publish Capacitor Plugin to Maven Central

on:
workflow_call:
secrets:
ANDROID_CENTRAL_USERNAME:
required: true
ANDROID_CENTRAL_PASSWORD:
required: true
ANDROID_SIGNING_KEY_ID:
required: true
ANDROID_SIGNING_PASSWORD:
required: true
ANDROID_SIGNING_KEY:
required: true
ANDROID_SONATYPE_STAGING_PROFILE_ID:
required: true
CAP_GH_RELEASE_TOKEN:
required: true
workflow_dispatch:

jobs:
publish-android:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.ref_name }} # explicitly set ref to include commit from `semantic-release`
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
- name: set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'zulu'
- name: Grant execute permission for publishing script
run: chmod +x ./scripts/publish-android.sh
- name: Run publish script
env:
ANDROID_CENTRAL_USERNAME: ${{ secrets.ANDROID_CENTRAL_USERNAME }}
ANDROID_CENTRAL_PASSWORD: ${{ secrets.ANDROID_CENTRAL_PASSWORD }}
ANDROID_SIGNING_KEY_ID: ${{ secrets.ANDROID_SIGNING_KEY_ID }}
ANDROID_SIGNING_PASSWORD: ${{ secrets.ANDROID_SIGNING_PASSWORD }}
ANDROID_SIGNING_KEY: ${{ secrets.ANDROID_SIGNING_KEY }}
ANDROID_SONATYPE_STAGING_PROFILE_ID: ${{ secrets.ANDROID_SONATYPE_STAGING_PROFILE_ID }}
run: ./scripts/publish-android.sh
39 changes: 39 additions & 0 deletions .github/workflows/publish_ios_cocoapods_trunk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Publish Capacitor Plugin to CocoaPods Trunk

on:
workflow_call:
secrets:
COCOAPODS_TRUNK_TOKEN:
required: true
CAP_GH_RELEASE_TOKEN:
required: true
workflow_dispatch:

jobs:
publish-ios:
runs-on: macos-15
if: github.ref == 'refs/heads/main'
timeout-minutes: 30
steps:
- run: sudo xcode-select --switch /Applications/Xcode_26.0.app
- run: xcrun simctl list > /dev/null
- run: xcodebuild -downloadPlatform iOS
- uses: actions/setup-node@v6
with:
node-version: 22
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.ref_name }} # explicitly set ref to include commit from `semantic-release`
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
- name: Install Cocoapods
run: |
gem install cocoapods
- name: Grant execute permission for publishing script
run: chmod +x ./scripts/publish-ios.sh
- name: Deploy to Cocoapods
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
run: |
set -eo pipefail
./scripts/publish-ios.sh
68 changes: 68 additions & 0 deletions .github/workflows/release_plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "Release Plugin"

on:
push:
branches:
- development
- next
workflow_dispatch:

permissions:
contents: write
issues: write
deployments: write
id-token: write # to enable use of OIDC for npm provenance and trusted publishing
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a reminder that you need to set trusted publishing for the @capacitor/camera npm package at (requires authentication)

Didn't check if you have, but if you haven't, here's npm docs: https://docs.npmjs.com/trusted-publishers

I've done this before, so if you have questions you can ping me.


jobs:
setup:
uses: ./.github/workflows/reusable_setup.yml
secrets:
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}

lint:
needs: 'setup'
uses: ./.github/workflows/reusable_lint.yml
secrets:
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}

build-packages:
needs: 'setup'
uses: ./.github/workflows/reusable_build.yml
secrets:
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}

release:
needs: ['setup','lint','build-packages']
runs-on: 'ubuntu-latest'
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
- name: 'Setup Tools'
uses: ./.github/actions/setup-tools
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
GH_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
run: npx semantic-release

publish-android:
needs: ['release']
uses: ./.github/workflows/publish_android_maven_central.yml
secrets:
ANDROID_CENTRAL_USERNAME: ${{ secrets.ANDROID_CENTRAL_USERNAME }}
ANDROID_CENTRAL_PASSWORD: ${{ secrets.ANDROID_CENTRAL_PASSWORD }}
ANDROID_SIGNING_KEY_ID: ${{ secrets.ANDROID_SIGNING_KEY_ID }}
ANDROID_SIGNING_KEY: ${{ secrets.ANDROID_SIGNING_KEY }}
ANDROID_SIGNING_PASSWORD: ${{ secrets.ANDROID_SIGNING_PASSWORD }}
ANDROID_SONATYPE_STAGING_PROFILE_ID: ${{ secrets.ANDROID_SONATYPE_STAGING_PROFILE_ID }}
CAP_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}

publish-ios:
needs: ['release']
uses: ./.github/workflows/publish_ios_cocoapods_trunk.yml
secrets:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
CAP_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
apply plugin: 'io.github.gradle-nexus.publish-plugin'
apply from: file('../../scripts/android/publish-root.gradle')
apply from: file('../../scripts/android/publish-module.gradle')
apply from: file('../scripts/android/publish-root.gradle')
apply from: file('../scripts/android/publish-module.gradle')
}

android {
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@
"rimraf": "^6.1.0",
"rollup": "^4.53.2",
"swiftlint": "^2.0.0",
"typescript": "^5.9.3"
"typescript": "^5.9.3",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^12.0.2",
"@semantic-release/npm": "^13.1.2",
"semantic-release": "^25.0.2"
},
"peerDependencies": {
"@capacitor/core": ">=8.0.0"
Expand Down
33 changes: 33 additions & 0 deletions release.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module.exports = {
branches: [
{ name: 'main', channel: 'latest' },
{ name: 'next', channel: 'next', prerelease: true },
{ name: 'development', channel: 'dev', prerelease: true }
],
repositoryUrl: 'https://github.com/ionic-team/capacitor-camera.git',
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
'@semantic-release/npm',
[
'@semantic-release/github',
{
successComment: false,
failComment: false,
releasedLabels: false,
addReleases: 'bottom',
releaseNotes: {
changelogFile: 'CHANGELOG.md'
}
}
],
[
'@semantic-release/git',
{
assets: ['CHANGELOG.md', 'package.json'],
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
}
]
]
};
82 changes: 82 additions & 0 deletions scripts/android/publish-module.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'

def LIB_VERSION = System.getenv('PLUGIN_VERSION')
def PLUGIN_NAME = System.getenv('PLUGIN_NAME')
def PLUGIN_REPO = System.getenv('PLUGIN_REPO')
def PLUGIN_SCM = System.getenv('PLUGIN_SCM')

task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
if (project.plugins.findPlugin("com.android.library")) {
from android.sourceSets.main.java.srcDirs
from android.sourceSets.main.kotlin.srcDirs
} else {
from sourceSets.main.java.srcDirs
from sourceSets.main.kotlin.srcDirs
}
}

artifacts {
archives androidSourcesJar
}

group = 'com.capacitorjs'
version = LIB_VERSION

afterEvaluate {
publishing {
publications {
release(MavenPublication) {
// Coordinates
groupId 'com.capacitorjs'
artifactId PLUGIN_NAME
version LIB_VERSION

// Two artifacts, the `aar` (or `jar`) and the sources
if (project.plugins.findPlugin("com.android.library")) {
from components.release
} else {
artifact("$buildDir/libs/${project.getName()}-${version}.jar")
}

artifact androidSourcesJar

// POM Data
pom {
name = PLUGIN_NAME
description = 'Capacitor Android ' + PLUGIN_NAME + ' plugin native library'
url = PLUGIN_REPO
licenses {
license {
name = 'MIT'
url = PLUGIN_REPO + '/blob/main' + '/LICENSE'
}
}
developers {
developer {
name = 'Ionic'
email = 'hi@ionic.io'
}
}

// Version Control Info
scm {
connection = 'scm:git:' + PLUGIN_SCM + '.git'
developerConnection = 'scm:git:ssh://' + PLUGIN_SCM + '.git'
url = PLUGIN_REPO + '/tree/main'
}
}
}
}
}
}

signing {
useInMemoryPgpKeys(
rootProject.ext["signing.keyId"],
rootProject.ext["signing.key"],
rootProject.ext["signing.password"],
)
sign publishing.publications
}
44 changes: 44 additions & 0 deletions scripts/android/publish-root.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Create variables with empty default values
ext["signing.keyId"] = ''
ext["signing.key"] = ''
ext["signing.password"] = ''
ext["centralTokenUsername"] = ''
ext["centralTokenPassword"] = ''
ext["sonatypeStagingProfileId"] = ''

File globalSecretPropsFile = file('../scripts/android/local.properties')
File secretPropsFile = project.rootProject.file('local.properties')
if (globalSecretPropsFile.exists()) {
println "Reading globalSecretPropsFile"
// Read global local.properties file first if it exists (scripts/android/local.properties)
Properties p = new Properties()
new FileInputStream(globalSecretPropsFile).withCloseable { is -> p.load(is) }
p.each { name, value -> ext[name] = value }
} else if (secretPropsFile.exists()) {
// Read plugin project specific local.properties file next if it exists
Properties p = new Properties()
new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) }
p.each { name, value -> ext[name] = value }
} else {
// Use system environment variables
ext["centralTokenUsername"] = System.getenv('ANDROID_CENTRAL_USERNAME')
ext["centralTokenPassword"] = System.getenv('ANDROID_CENTRAL_PASSWORD')
ext["sonatypeStagingProfileId"] = System.getenv('ANDROID_SONATYPE_STAGING_PROFILE_ID')
ext["signing.keyId"] = System.getenv('ANDROID_SIGNING_KEY_ID')
ext["signing.key"] = System.getenv('ANDROID_SIGNING_KEY')
ext["signing.password"] = System.getenv('ANDROID_SIGNING_PASSWORD')
}

// Set up Sonatype repository
nexusPublishing {
repositories {
sonatype {
stagingProfileId = sonatypeStagingProfileId
username = centralTokenUsername
password = centralTokenPassword
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
}
}
repositoryDescription = 'Capacitor Android ' + System.getenv('PLUGIN_NAME') + ' plugin v' + System.getenv('PLUGIN_VERSION')
}
Loading
Loading