Skip to content

Commit 7ca70cf

Browse files
hughnst3chguy
andauthored
Publish embedded package for releases of Element Call (#3086)
* Publish embedded package for releases of Element Call Part of #2994 This PR: - Publishes embedded builds as Tarball, NPM, AAR, SwiftPM for releases - Publishes full builds as Tarball for releases - Adds comments to release notes with the built artifact locations * Update embedded/web/package.json Co-authored-by: Michael Telatynski <[email protected]> * Update .github/workflows/publish-embedded-packages.yaml * Update embedded/ios/Package.swift * Apply suggestions from code review * Try dry-run of gradlew * Whitespace * Fix more instances of unpinned GHA * Minimise permissions * Upload release notes once To reduce concurrency * Fix npm publish permissions --------- Co-authored-by: Michael Telatynski <[email protected]>
1 parent 246e6a6 commit 7ca70cf

26 files changed

+2254
-51
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
name: Build & publish embedded packages for releases
2+
3+
on:
4+
release:
5+
types: [published]
6+
pull_request:
7+
types:
8+
- synchronize
9+
- opened
10+
- labeled
11+
push:
12+
branches: [livekit]
13+
14+
env:
15+
# We perform a dry run for all events except releases.
16+
# This is to help make sure that we notice if the packaging process has become
17+
# broken ahead of a release.
18+
DRY_RUN: ${{ github.event_name != 'release' }}
19+
# We should only use the hard coded test value for a dry run
20+
VERSION: ${{ github.event_name == 'release' && github.event.release.tag_name || 'v0.0.0-pre.0' }}
21+
22+
jobs:
23+
build_element_call:
24+
uses: ./.github/workflows/build-element-call.yaml
25+
with:
26+
vite_app_version: embedded-${{ github.event.release.tag_name || 'v0.0.0-pre.0' }} # Using ${{ env.VERSION }} here doesn't work
27+
package: embedded
28+
secrets:
29+
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
30+
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
31+
SENTRY_URL: ${{ secrets.SENTRY_URL }}
32+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
33+
34+
publish_tarball:
35+
needs: build_element_call
36+
if: always()
37+
name: Publish tarball
38+
runs-on: ubuntu-latest
39+
permissions:
40+
contents: write # required to upload release asset
41+
steps:
42+
- name: Determine filename
43+
run: echo "FILENAME_PREFIX=element-call-embedded-${VERSION:1}" >> "$GITHUB_ENV"
44+
- name: 📥 Download built element-call artifact
45+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
46+
with:
47+
github-token: ${{ secrets.GITHUB_TOKEN }}
48+
run-id: ${{ github.event.workflow_run.id || github.run_id }}
49+
name: build-output-embedded
50+
path: ${{ env.FILENAME_PREFIX}}
51+
- name: Create Tarball
52+
run: tar --numeric-owner -cvzf ${{ env.FILENAME_PREFIX }}.tar.gz ${{ env.FILENAME_PREFIX }}
53+
- name: Create Checksum
54+
run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256
55+
- name: Upload
56+
if: ${{ env.DRY_RUN == 'false' }}
57+
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
58+
with:
59+
files: |
60+
${{ env.FILENAME_PREFIX }}.tar.gz
61+
${{ env.FILENAME_PREFIX }}.sha256
62+
63+
publish_npm:
64+
needs: build_element_call
65+
if: always()
66+
name: Publish NPM
67+
runs-on: ubuntu-latest
68+
permissions:
69+
contents: read
70+
id-token: write # required for the provenance flag on npm publish
71+
steps:
72+
- name: Checkout
73+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
74+
75+
- name: 📥 Download built element-call artifact
76+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
77+
with:
78+
github-token: ${{ secrets.GITHUB_TOKEN }}
79+
run-id: ${{ github.event.workflow_run.id || github.run_id }}
80+
name: build-output-embedded
81+
path: embedded/web/dist
82+
83+
- name: Setup node
84+
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
85+
with:
86+
node-version-file: .node-version
87+
registry-url: "https://registry.npmjs.org"
88+
89+
- name: Publish npm
90+
working-directory: embedded/web
91+
run: |
92+
npm version ${{ env.VERSION }} --no-git-tag-version
93+
echo "ARTIFACT_VERSION=$(jq '.version' --raw-output package.json)" >> "$GITHUB_ENV"
94+
npm publish --provenance --access public ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
95+
env:
96+
NODE_AUTH_TOKEN: ${{ secrets.NPM_RELEASE_TOKEN }}
97+
98+
publish_android:
99+
needs: build_element_call
100+
if: always()
101+
name: Publish Android AAR
102+
runs-on: ubuntu-latest
103+
permissions:
104+
contents: read
105+
steps:
106+
- name: Checkout
107+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
108+
109+
- name: 📥 Download built element-call artifact
110+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
111+
with:
112+
github-token: ${{ secrets.GITHUB_TOKEN }}
113+
run-id: ${{ github.event.workflow_run.id || github.run_id }}
114+
name: build-output-embedded
115+
path: embedded/android/lib/src/main/assets/element-call
116+
117+
- name: ☕️ Setup Java
118+
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
119+
with:
120+
distribution: "temurin"
121+
java-version: "17"
122+
123+
- name: Get artifact version
124+
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
125+
126+
- name: Publish AAR
127+
working-directory: embedded/android
128+
env:
129+
EC_VERSION: ${{ env.ARTIFACT_VERSION }}
130+
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_RELEASE_USERNAME }}
131+
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_RELEASE_PASSWORD }}
132+
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SIGNING_KEY }}
133+
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SIGNING_KEY_PASSWORD }}
134+
run: ./gradlew publishAndReleaseToMavenCentral --no-daemon ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
135+
136+
publish_ios:
137+
needs: build_element_call
138+
if: always()
139+
name: Publish SwiftPM Library
140+
runs-on: ubuntu-latest
141+
permissions:
142+
contents: read
143+
steps:
144+
- name: Checkout
145+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
146+
with:
147+
path: element-call
148+
149+
- name: 📥 Download built element-call artifact
150+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
151+
with:
152+
github-token: ${{ secrets.GITHUB_TOKEN }}
153+
run-id: ${{ github.event.workflow_run.id || github.run_id }}
154+
name: build-output-embedded
155+
path: element-call/embedded/ios/Sources/dist
156+
157+
- name: Checkout element-call-swift
158+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
159+
with:
160+
repository: element-hq/element-call-swift
161+
path: element-call-swift
162+
token: ${{ secrets.SWIFT_RELEASE_TOKEN }}
163+
164+
- name: Copy files
165+
run: rsync -a --delete --exclude .git element-call/embedded/ios/ element-call-swift
166+
167+
- name: Get artifact version
168+
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
169+
170+
- name: Commit and tag
171+
working-directory: element-call-swift
172+
run: |
173+
git config --global user.email "[email protected]"
174+
git config --global user.name "Element CI"
175+
git add -A
176+
git commit -am "Release ${{ env.VERSION }}"
177+
git tag -a ${{ env.ARTIFACT_VERSION }} -m "${{ github.event.release.html_url }}"
178+
179+
- name: Push
180+
working-directory: element-call-swift
181+
run: |
182+
git push --tags ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
183+
184+
release_notes:
185+
needs: [publish_npm, publish_android, publish_ios]
186+
if: always()
187+
name: Update release notes
188+
runs-on: ubuntu-latest
189+
permissions:
190+
contents: write # to update release notes
191+
steps:
192+
- name: Get artifact version
193+
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
194+
195+
- name: Add release notes
196+
if: ${{ env.DRY_RUN == 'false' }}
197+
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
198+
with:
199+
append_body: true
200+
body: |
201+
202+
## Embedded packages
203+
204+
This release includes the following embedded packages that allow Element Call to be used as an embedded widget
205+
within another application.
206+
207+
### NPM
208+
209+
```
210+
npm install @element-hq/element-call-embedded@${{ env.ARTIFACT_VERSION }}
211+
```
212+
213+
### Android AAR
214+
215+
```
216+
dependencies {
217+
implementation 'io.element.android:element-call-embedded:${{ env.ARTIFACT_VERSION }}'
218+
}
219+
```
220+
221+
### SwiftPM
222+
223+
```
224+
.package(url: "https://github.com/element-hq/element-call-swift.git", from: "${{ env.ARTIFACT_VERSION }}")
225+
```

.github/workflows/publish.yaml

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,57 @@
1-
name: Build & publish images to the package registry for releases
1+
name: Build & publish full packages for releases
22

33
on:
44
release:
55
types: [published]
66

77
env:
8-
REGISTRY: ghcr.io
9-
IMAGE_NAME: ${{ github.repository }}
8+
VERSION: ${{ github.event.release.tag_name }}
109

1110
jobs:
1211
build_element_call:
13-
if: ${{ github.event_name == 'release' }}
1412
uses: ./.github/workflows/build-element-call.yaml
1513
with:
1614
package: full
17-
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
15+
vite_app_version: ${{ github.event.release.tag_name }} # Using ${{ env.VERSION }} here doesn't work
1816
secrets:
1917
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
2018
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
2119
SENTRY_URL: ${{ secrets.SENTRY_URL }}
2220
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
21+
2322
publish_tarball:
2423
needs: build_element_call
2524
if: always()
2625
name: Publish tarball
2726
runs-on: ubuntu-latest
28-
outputs:
29-
unix_time: ${{steps.current-time.outputs.unix_time}}
3027
permissions:
3128
contents: write # required to upload release asset
3229
packages: write
3330
steps:
34-
- name: Get current time
35-
id: current-time
36-
run: echo "unix_time=$(date +'%s')" >> $GITHUB_OUTPUT
37-
- name: 📥 Download artifact
31+
- name: Determine filename
32+
run: echo "FILENAME_PREFIX=element-call-${VERSION:1}" >> "$GITHUB_ENV"
33+
- name: 📥 Download built element-call artifact
3834
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
3935
with:
4036
github-token: ${{ secrets.GITHUB_TOKEN }}
4137
run-id: ${{ github.event.workflow_run.id || github.run_id }}
4238
name: build-output-full
43-
path: dist
39+
path: ${{ env.FILENAME_PREFIX }}
4440
- name: Create Tarball
45-
env:
46-
TARBALL_VERSION: ${{ github.event.release.tag_name || github.sha }}
47-
run: |
48-
tar --numeric-owner --transform "s/dist/element-call-${TARBALL_VERSION}/" -cvzf element-call-${TARBALL_VERSION}.tar.gz dist
41+
run: tar --numeric-owner --transform "s/dist/${{ env.FILENAME_PREFIX }}/" -cvzf ${{ env.FILENAME_PREFIX }}.tar.gz ${{ env.FILENAME_PREFIX }}
42+
- name: Create Checksum
43+
run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256
4944
- name: Upload
50-
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
51-
env:
52-
GITHUB_TOKEN: ${{ github.token }}
45+
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
5346
with:
54-
path: "./element-call-*.tar.gz"
47+
files: |
48+
${{ env.FILENAME_PREFIX }}.tar.gz
49+
${{ env.FILENAME_PREFIX }}.sha256
50+
5551
publish_docker:
56-
needs: publish_tarball
52+
needs: build_element_call
5753
if: always()
54+
name: Publish docker
5855
permissions:
5956
contents: write
6057
packages: write
@@ -64,3 +61,23 @@ jobs:
6461
docker_tags: |
6562
type=sha,format=short,event=branch
6663
type=semver,pattern=v{{version}}
64+
add_docker_release_note:
65+
needs: publish_docker
66+
name: Add docker release note
67+
runs-on: ubuntu-latest
68+
steps:
69+
- name: Get artifact version
70+
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
71+
- name: Add release note
72+
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
73+
with:
74+
append_body: true
75+
body: |
76+
## Docker full package
77+
Element Call is available as a Docker image from the [GitHub Container Registry](https://github.com/element-hq/element-call/pkgs/container/element-call).
78+
79+
The image provides a full build of Element Call that can be used both in standalone and as a widget (on a remote URL).
80+
81+
```
82+
docker pull ghcr.io/element-hq/element-call:${{ env.ARTIFACT_VERSION }}
83+
```

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ Element Call can be packaged in two ways:
5252
**Full Package** – Supports both **Standalone** and **Widget** mode. Hosted as
5353
a static web page and accessed via a URL when used as a widget.
5454

55-
**Embedded Package**🚧 **Coming [Soon](https://github.com/element-hq/element-call/issues/2994):** Designed for **Widget mode** only. Bundled with a
55+
**Embedded Package** – Designed for **Widget mode** only. Bundled with a
5656
messenger app for seamless integration. This is the recommended method for
5757
embedding Element Call into a messenger app.
5858

59+
See the [here](./docs/embedded-standalone.md) for more information on the packages.
60+
5961
### Standalone mode
6062

6163
![Element Call in Standalone Mode](./docs/element_call_standalone.drawio.png)

docs/embedded-standalone.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1-
## Embedded vs standalone mode
1+
## Element Call packages
22

3-
Element call is developed using the js-sdk with matroska mode. This means the app can run either as a standalone app directly connected to a homeserver providing login interfaces or it can be used as a widget.
3+
Element Call is available as two different packages: Full Package and Embedded Package. The Full Package is designed for standalone use, while the Embedded Package is designed for widget mode only. The table below provides a comparison of the two packages:
44

5-
As a widget the app only uses the core calling (MatrixRTC) parts. The rest (authentication, sending events, getting room state updates about calls) is done by the hosting client.
6-
Element Call and the hosting client are connected via the widget api.
5+
| | Full Package | Embedded Package |
6+
| ------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------- |
7+
| **Supports use as standalone** |||
8+
| **Supports use as widget** |||
9+
| **Deployment mode** | Hosted as a static web page and accessed via a URL when used as a widget | Bundled within a messenger app for seamless integration |
10+
| **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS |
11+
| **Recommended for** | Standalone/guest access usage | Embedding within messenger apps |
712

8-
Element call detects that it is run as a widget if a widgetId is defined in the url parameters. If `widgetId` is present element call will try to connect to the client via the widget postMessage api using the parameters provided in [Url Format and parameters
13+
For examples of how to use the platform specific release artifacts (e.g. Android AAR) see
14+
the Element Messenger apps for: [Web](https://github.com/element-hq/element-web), [iOS](https://github.com/element-hq/element-x-ios) and [Android](https://github.com/element-hq/element-x-android).
15+
16+
## Widget vs standalone mode
17+
18+
Element Call is developed using the [js-sdk](https://github.com/matrix-org/matrix-js-sdk) with matroska mode. This means the app can run either as a standalone app directly connected to a homeserver providing login interfaces or it can be used as a widget within a Matrix client.
19+
20+
As a widget, the app only uses the core calling (MatrixRTC) parts. The rest (authentication, sending events, getting room state updates about calls) is done by the hosting client.
21+
Element Call and the hosting client are connected via the widget API.
22+
23+
Element Call detects that it is run as a widget if a widgetId is defined in the url parameters. If `widgetId` is present then Element Call will try to connect to the client via the widget postMessage API using the parameters provided in [Url Format and parameters
924
](./url-params.md).

0 commit comments

Comments
 (0)