Skip to content

Commit 402bba2

Browse files
chore(ci): add release workflows (#32)
* chore: add templates for PR, bug report, and feature request * chore: configure release workflows (based on other Capacitor plugins) * chore: delete github templates for now --------- Co-authored-by: OS-pedrogustavobilro <pedro.gustavo.bilro@outsystems.com>
1 parent 5d6d881 commit 402bba2

File tree

10 files changed

+448
-3
lines changed

10 files changed

+448
-3
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Publish Capacitor Plugin to Maven Central
2+
3+
on:
4+
workflow_call:
5+
secrets:
6+
ANDROID_CENTRAL_USERNAME:
7+
required: true
8+
ANDROID_CENTRAL_PASSWORD:
9+
required: true
10+
ANDROID_SIGNING_KEY_ID:
11+
required: true
12+
ANDROID_SIGNING_PASSWORD:
13+
required: true
14+
ANDROID_SIGNING_KEY:
15+
required: true
16+
ANDROID_SONATYPE_STAGING_PROFILE_ID:
17+
required: true
18+
CAP_GH_RELEASE_TOKEN:
19+
required: true
20+
workflow_dispatch:
21+
22+
jobs:
23+
publish-android:
24+
if: github.ref == 'refs/heads/main'
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 60
27+
permissions:
28+
contents: read
29+
steps:
30+
- uses: actions/checkout@v6
31+
with:
32+
fetch-depth: 0
33+
ref: ${{ github.ref_name }} # explicitly set ref to include commit from `semantic-release`
34+
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
35+
- name: set up JDK 21
36+
uses: actions/setup-java@v5
37+
with:
38+
java-version: '21'
39+
distribution: 'zulu'
40+
- name: Grant execute permission for publishing script
41+
run: chmod +x ./scripts/publish-android.sh
42+
- name: Run publish script
43+
env:
44+
ANDROID_CENTRAL_USERNAME: ${{ secrets.ANDROID_CENTRAL_USERNAME }}
45+
ANDROID_CENTRAL_PASSWORD: ${{ secrets.ANDROID_CENTRAL_PASSWORD }}
46+
ANDROID_SIGNING_KEY_ID: ${{ secrets.ANDROID_SIGNING_KEY_ID }}
47+
ANDROID_SIGNING_PASSWORD: ${{ secrets.ANDROID_SIGNING_PASSWORD }}
48+
ANDROID_SIGNING_KEY: ${{ secrets.ANDROID_SIGNING_KEY }}
49+
ANDROID_SONATYPE_STAGING_PROFILE_ID: ${{ secrets.ANDROID_SONATYPE_STAGING_PROFILE_ID }}
50+
run: ./scripts/publish-android.sh
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Publish Capacitor Plugin to CocoaPods Trunk
2+
3+
on:
4+
workflow_call:
5+
secrets:
6+
COCOAPODS_TRUNK_TOKEN:
7+
required: true
8+
CAP_GH_RELEASE_TOKEN:
9+
required: true
10+
workflow_dispatch:
11+
12+
jobs:
13+
publish-ios:
14+
runs-on: macos-15
15+
if: github.ref == 'refs/heads/main'
16+
timeout-minutes: 30
17+
steps:
18+
- run: sudo xcode-select --switch /Applications/Xcode_26.0.app
19+
- run: xcrun simctl list > /dev/null
20+
- run: xcodebuild -downloadPlatform iOS
21+
- uses: actions/setup-node@v6
22+
with:
23+
node-version: 22
24+
- uses: actions/checkout@v6
25+
with:
26+
fetch-depth: 0
27+
ref: ${{ github.ref_name }} # explicitly set ref to include commit from `semantic-release`
28+
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
29+
- name: Install Cocoapods
30+
run: |
31+
gem install cocoapods
32+
- name: Grant execute permission for publishing script
33+
run: chmod +x ./scripts/publish-ios.sh
34+
- name: Deploy to Cocoapods
35+
env:
36+
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
37+
run: |
38+
set -eo pipefail
39+
./scripts/publish-ios.sh
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: "Release Plugin"
2+
3+
on:
4+
push:
5+
branches:
6+
- development
7+
- next
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: write
12+
issues: write
13+
deployments: write
14+
id-token: write # to enable use of OIDC for npm provenance and trusted publishing
15+
16+
jobs:
17+
setup:
18+
uses: ./.github/workflows/reusable_setup.yml
19+
secrets:
20+
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
21+
22+
lint:
23+
needs: 'setup'
24+
uses: ./.github/workflows/reusable_lint.yml
25+
secrets:
26+
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
27+
28+
build-packages:
29+
needs: 'setup'
30+
uses: ./.github/workflows/reusable_build.yml
31+
secrets:
32+
THE_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
33+
34+
release:
35+
needs: ['setup','lint','build-packages']
36+
runs-on: 'ubuntu-latest'
37+
timeout-minutes: 30
38+
steps:
39+
- uses: actions/checkout@v6
40+
with:
41+
fetch-depth: 0
42+
token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
43+
- name: 'Setup Tools'
44+
uses: ./.github/actions/setup-tools
45+
- name: Release
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
48+
GH_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
49+
run: npx semantic-release
50+
51+
publish-android:
52+
needs: ['release']
53+
uses: ./.github/workflows/publish_android_maven_central.yml
54+
secrets:
55+
ANDROID_CENTRAL_USERNAME: ${{ secrets.ANDROID_CENTRAL_USERNAME }}
56+
ANDROID_CENTRAL_PASSWORD: ${{ secrets.ANDROID_CENTRAL_PASSWORD }}
57+
ANDROID_SIGNING_KEY_ID: ${{ secrets.ANDROID_SIGNING_KEY_ID }}
58+
ANDROID_SIGNING_KEY: ${{ secrets.ANDROID_SIGNING_KEY }}
59+
ANDROID_SIGNING_PASSWORD: ${{ secrets.ANDROID_SIGNING_PASSWORD }}
60+
ANDROID_SONATYPE_STAGING_PROFILE_ID: ${{ secrets.ANDROID_SONATYPE_STAGING_PROFILE_ID }}
61+
CAP_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
62+
63+
publish-ios:
64+
needs: ['release']
65+
uses: ./.github/workflows/publish_ios_cocoapods_trunk.yml
66+
secrets:
67+
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
68+
CAP_GH_RELEASE_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}

android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ apply plugin: 'com.android.library'
3030
apply plugin: 'kotlin-android'
3131
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
3232
apply plugin: 'io.github.gradle-nexus.publish-plugin'
33-
apply from: file('../../scripts/android/publish-root.gradle')
34-
apply from: file('../../scripts/android/publish-module.gradle')
33+
apply from: file('../scripts/android/publish-root.gradle')
34+
apply from: file('../scripts/android/publish-module.gradle')
3535
}
3636

3737
android {

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@
6161
"rimraf": "^6.1.0",
6262
"rollup": "^4.53.2",
6363
"swiftlint": "^2.0.0",
64-
"typescript": "^5.9.3"
64+
"typescript": "^5.9.3",
65+
"@semantic-release/changelog": "^6.0.3",
66+
"@semantic-release/exec": "^7.1.0",
67+
"@semantic-release/git": "^10.0.1",
68+
"@semantic-release/github": "^12.0.2",
69+
"@semantic-release/npm": "^13.1.2",
70+
"semantic-release": "^25.0.2"
6571
},
6672
"peerDependencies": {
6773
"@capacitor/core": ">=8.0.0"

release.config.cjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module.exports = {
2+
branches: [
3+
{ name: 'main', channel: 'latest' },
4+
{ name: 'next', channel: 'next', prerelease: true },
5+
{ name: 'development', channel: 'dev', prerelease: true }
6+
],
7+
repositoryUrl: 'https://github.com/ionic-team/capacitor-camera.git',
8+
plugins: [
9+
'@semantic-release/commit-analyzer',
10+
'@semantic-release/release-notes-generator',
11+
'@semantic-release/changelog',
12+
'@semantic-release/npm',
13+
[
14+
'@semantic-release/github',
15+
{
16+
successComment: false,
17+
failComment: false,
18+
releasedLabels: false,
19+
addReleases: 'bottom',
20+
releaseNotes: {
21+
changelogFile: 'CHANGELOG.md'
22+
}
23+
}
24+
],
25+
[
26+
'@semantic-release/git',
27+
{
28+
assets: ['CHANGELOG.md', 'package.json'],
29+
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
30+
}
31+
]
32+
]
33+
};
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
apply plugin: 'maven-publish'
2+
apply plugin: 'signing'
3+
4+
def LIB_VERSION = System.getenv('PLUGIN_VERSION')
5+
def PLUGIN_NAME = System.getenv('PLUGIN_NAME')
6+
def PLUGIN_REPO = System.getenv('PLUGIN_REPO')
7+
def PLUGIN_SCM = System.getenv('PLUGIN_SCM')
8+
9+
task androidSourcesJar(type: Jar) {
10+
archiveClassifier.set('sources')
11+
if (project.plugins.findPlugin("com.android.library")) {
12+
from android.sourceSets.main.java.srcDirs
13+
from android.sourceSets.main.kotlin.srcDirs
14+
} else {
15+
from sourceSets.main.java.srcDirs
16+
from sourceSets.main.kotlin.srcDirs
17+
}
18+
}
19+
20+
artifacts {
21+
archives androidSourcesJar
22+
}
23+
24+
group = 'com.capacitorjs'
25+
version = LIB_VERSION
26+
27+
afterEvaluate {
28+
publishing {
29+
publications {
30+
release(MavenPublication) {
31+
// Coordinates
32+
groupId 'com.capacitorjs'
33+
artifactId PLUGIN_NAME
34+
version LIB_VERSION
35+
36+
// Two artifacts, the `aar` (or `jar`) and the sources
37+
if (project.plugins.findPlugin("com.android.library")) {
38+
from components.release
39+
} else {
40+
artifact("$buildDir/libs/${project.getName()}-${version}.jar")
41+
}
42+
43+
artifact androidSourcesJar
44+
45+
// POM Data
46+
pom {
47+
name = PLUGIN_NAME
48+
description = 'Capacitor Android ' + PLUGIN_NAME + ' plugin native library'
49+
url = PLUGIN_REPO
50+
licenses {
51+
license {
52+
name = 'MIT'
53+
url = PLUGIN_REPO + '/blob/main' + '/LICENSE'
54+
}
55+
}
56+
developers {
57+
developer {
58+
name = 'Ionic'
59+
email = 'hi@ionic.io'
60+
}
61+
}
62+
63+
// Version Control Info
64+
scm {
65+
connection = 'scm:git:' + PLUGIN_SCM + '.git'
66+
developerConnection = 'scm:git:ssh://' + PLUGIN_SCM + '.git'
67+
url = PLUGIN_REPO + '/tree/main'
68+
}
69+
}
70+
}
71+
}
72+
}
73+
}
74+
75+
signing {
76+
useInMemoryPgpKeys(
77+
rootProject.ext["signing.keyId"],
78+
rootProject.ext["signing.key"],
79+
rootProject.ext["signing.password"],
80+
)
81+
sign publishing.publications
82+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Create variables with empty default values
2+
ext["signing.keyId"] = ''
3+
ext["signing.key"] = ''
4+
ext["signing.password"] = ''
5+
ext["centralTokenUsername"] = ''
6+
ext["centralTokenPassword"] = ''
7+
ext["sonatypeStagingProfileId"] = ''
8+
9+
File globalSecretPropsFile = file('../scripts/android/local.properties')
10+
File secretPropsFile = project.rootProject.file('local.properties')
11+
if (globalSecretPropsFile.exists()) {
12+
println "Reading globalSecretPropsFile"
13+
// Read global local.properties file first if it exists (scripts/android/local.properties)
14+
Properties p = new Properties()
15+
new FileInputStream(globalSecretPropsFile).withCloseable { is -> p.load(is) }
16+
p.each { name, value -> ext[name] = value }
17+
} else if (secretPropsFile.exists()) {
18+
// Read plugin project specific local.properties file next if it exists
19+
Properties p = new Properties()
20+
new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) }
21+
p.each { name, value -> ext[name] = value }
22+
} else {
23+
// Use system environment variables
24+
ext["centralTokenUsername"] = System.getenv('ANDROID_CENTRAL_USERNAME')
25+
ext["centralTokenPassword"] = System.getenv('ANDROID_CENTRAL_PASSWORD')
26+
ext["sonatypeStagingProfileId"] = System.getenv('ANDROID_SONATYPE_STAGING_PROFILE_ID')
27+
ext["signing.keyId"] = System.getenv('ANDROID_SIGNING_KEY_ID')
28+
ext["signing.key"] = System.getenv('ANDROID_SIGNING_KEY')
29+
ext["signing.password"] = System.getenv('ANDROID_SIGNING_PASSWORD')
30+
}
31+
32+
// Set up Sonatype repository
33+
nexusPublishing {
34+
repositories {
35+
sonatype {
36+
stagingProfileId = sonatypeStagingProfileId
37+
username = centralTokenUsername
38+
password = centralTokenPassword
39+
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
40+
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
41+
}
42+
}
43+
repositoryDescription = 'Capacitor Android ' + System.getenv('PLUGIN_NAME') + ' plugin v' + System.getenv('PLUGIN_VERSION')
44+
}

0 commit comments

Comments
 (0)