Forge rolling releases is available through Forge's Early Access Program (EAP). This feature is currently only available in Jira and Confluence.
EAP grants selected users early testing access for feedback; APIs and features in EAP are experimental, unsupported, subject to change without notice, and not recommended for production. To join the EAP, please complete the sign-up form.
For more details, see Forge EAP, Preview, and GA.
Rolling releases decouple permissions (scopes, egress, and remotes) from app code versions. This means you can deploy new code without waiting for admin approval of new permissions.
Currently, when permissions change, the app remains on the old version of the code for all existing installations, and admins are sometimes slow to update the apps, causing version fragmentation.
With rolling releases, when you deploy a new version with permission changes:
One of the drivers for this change is developers having many customers not getting the latest version of the code, and developers need to back-port fixes and security patches to old major versions, increasing the load on developers to support old major versions. Some developers have expressed that they do not have the capacity to maintain old versions.
Key benefits:
When an installation is upgraded with a code-only upgrade:
This state is called "decoupled" because the code version is ahead of the permission version.
When an admin approves new permissions, the permissions will then match the manifest of that version, and is no longer considered "decoupled".
Update the permissions in the app manifest to indicate that app is managing missing permissions. This is done by adding enforcement: app-managed config to app permissions.
1 2app: id: ... permissions: enforcement: app-managed scopes: - ... external: - ...
Please see Permissions SDK to check for missing permissions at runtime.
The updated code may include changes that depend on new permissions but since only the app code was upgraded, some permissions might be missing. To handle such cases, use the permissions SDK to verify if the permission exists and gracefully handle if the needed permission does not exist.
The Permissions SDK is available for both frontend (@forge/react) and backend (@forge/api) code.
Install the pre-release version of the @forge/react package:
1 2npm install --save @forge/react@next
Import the usePermissions hook to check permissions:
1 2import { usePermissions } from '@forge/react'; const MyComponent = () => { const { hasPermission, isLoading, missingPermissions, error } = usePermissions({ scopes: ['read:confluence-content', 'write:confluence-content'], external: { fetch: { backend: ['https://api.example.com'], client: ['https://cdn.example.com'] }, images: ['https://images.example.com'], fonts: ['https://fonts.googleapis.com'] } }); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; if (!hasPermission) { return <div>Missing: {JSON.stringify(missingPermissions)}</div>; } return <div>All permissions granted!</div>; };
Install the next version of the @forge/api package:
1 2npm install --save @forge/api@next
1 2import { permissions } from '@forge/api'; const isPermitted = permissions.hasScope('storage:app')
1 2import { permissions } from '@forge/api'; const isPermitted = permissions.canFetchFrom('backend', 'https://api.example.com')
1 2import { permissions } from '@forge/api'; const isPermitted = permissions.canLoadResource('images', 'https://api.example.com/image.png')
1 2import { permissions } from '@forge/api'; const { granted, missing } = permissions.hasPermission({ scopes: ['storage:app'], external: { fetch: { backend: ["https://api.example.com", "https://blah.com", "https://www.google.com"] }, images: ["https://images.example.com", "https://cdn.example.com"], } })
For a developer to ensure their app will work when apps upgrade from previous versions, and they have checked the correct permissions in the correct places, they need to enter a decoupled state with various permission combinations from previous major versions.
To test how your app behaves with different permission levels, you can install directly into a decoupled state:
1 2# Install with permission version 2, code version 2 (coupled) forge install --major-version 2 # Upgrade only code to version 4 (decoupled state: permissions v2, code v4) forge install --upgrade code --major-version 4 # Upgrade both code and permissions to version 4 (coupled again) forge install --upgrade --major-version 4
The following features are under development, therefore are not offered as part of EAP:
true in cases where paths are in the manifest.
usePermissionspermissions.canFetchFrom('client', '...')permissions.canLoadResource(..., ...)permissions.external.fetch.client: "https://api.example.com/api"permissions.canFetchFrom("client", "https://api.example.com/whatever")false, Actual: trueFor a hands-on walkthrough of building an app with rolling releases:
Rate this page: