Introducing alpha support for adding Forge to your existing Connect app

Hello everyone,

Today we are announcing an alpha release of functionality that allows developers to add Forge features to existing Connect apps.

The alpha release is intended to provide a way for our community to test out what’s been built so far and help us prioritise subsequent features along the way to a production-ready launch.

Getting started

Please see our developer documentation on Build a Connect on Forge app to get started.

We want your feedback

I’m super interested in any feedback you want to share on what has been built so far, and what would be most valuable for us to prioritise next.

Thanks! :slight_smile:
Joe

22 Likes

Hi,
Thank you this, that’s really an exciting feature, being able to gradually adopt Forge!

I’ve tried to follow along the tutorial you linked to, but ran into the following error when using forge deploy -e development --verbose:

Found unsupported modules in the manifest
Validation errors: {
  "forbiddenModules": [
    "connect-jira:lifecycle",
    "connect-jira:generalPages"
  ]
}

I am using forge 0.24.0 and have not made any changes to the code apart from what is suggested in the tutorial. Any idea what I might be doing wrong? Do I need to enable this feature somehow?

Cheers and thanks for an amazing feature,
Oliver

1 Like

Hi @osiebenmarck, thanks for trying out the feature and please accept my apologies; there was a feature flag I didn’t realise was necessary to activate in order to make the connect modules broadly available. It’s now on; please let me know if that fixes it for you.

Cheers,
James

2 Likes

Hi @jhazelwood,
Thank you for the quick reply, that actually helped and I can now deploy the sample app. Unfortunately, I am now stuck at the forge install step, which fails with an unexpected error:

 ▶️  GraphQL https://api.atlassian.com/graphql
Query: 
      mutation installApp($input: AppInstallationInput!) {
        installApp(input: $input) {
          success
          message
          errorDetails {
            code
          }
          installationId
          authorizationUrl
        }
      }
    
Variables: {
  "input": {
    "installationContext": "ari:cloud:jira::site/3e5c0e4b-3b9f-45a8-8baa-9e679221db83",
    "appId": "ari:cloud:ecosystem::app/1f8ff8e1-45bf-4a20-beb7-ecc7b082ec10",
    "environmentKey": "default"
  }
}
  ◀️  GraphQL
Request ID: 185ffaef3aac9184
Result: {
  "installApp": {
    "success": false,
    "message": "An unexpected error occurred",
    "errorDetails": {
      "code": "INTERNAL_SERVER_ERROR"
    },
    "installationId": null,
    "authorizationUrl": null
  }
}

Error: Installation error: An unexpected error occurred (requestId: 185ffaef3aac9184)

I am logged in and can deploy/install other Forge apps without problems. Do you have any more ideas?

Thank you,
Oliver

1 Like

Thanks again @osiebenmarck for getting back to us and for your patience. Our error messages need work, but digging into the logs it appears that your app server returned a non-200 response to the installation hook. We aren’t logging the status codes or response bodies so I can’t give you any more information beyond that, but do you see anything in the logs of your standalone app server? It should be logging the urls and response status codes of all requests it receives.

One wild theory: is your node version greater than or equal to 10.12.0? If not the issue could be with the code to save the installation data - it uses a flag introduced in that version to create directories recursively.

I’m in the Sydney timezone but I’ll check in this evening (your morning) to see if I can assist you in a more synchronous fashion.

Thanks again,
James

Hi, I just had another thought - it could be that the bad response code is coming from your ngrok as well - I did see a 402 payment required one time when testing the ngrok in unlicensed mode, and had to restart it and update to the new base URL.

1 Like

Hi @jhazelwood, Thank you soo much, the ngrok thing was it. I had restarted ngrok, but forgot to update the manifest.yml to the new url. Once I did that, everything went smooth.

Again, thanks for the quick help, hope you didn’t stay up to late.

Best regards,
Oliver

3 Likes

Hooray! So glad to hear it. Not at all, I only just checked in now, and it’s only 7:30pm.

3 Likes

Hi Everyone,

The alpha will be paused for 24-48 hours.

We’ve uncovered a bug thats causing pure Forge apps that are 3 months or older to fail on install. The fix for this should be out in the next two days, stay tuned to this thread to see when we’ve reenabled the functionality.

Thanks,
Athan

1 Like

Hi All,

We’ve fixed the bug and have turned the alpha features back on.

Thanks!
Athan

2 Likes

Hi!

I have some atlassian-connect application (it has REST-endpoints) and my new Forge-application. I want to call these REST-endpoints from my Forge-application, but I need the authorization token.

I can use AP.context.getToken for the atlassian-connect applications, but how can I get the token in the Forge-application? Is there any alternative AP.context.getToken in Forge?

Is there any difference (I mean to get the token) between two applications (atlassian-connect and Forge) and one hybrid application?

I have read the article https://developer.atlassian.com/platform/forge/build-a-connect-on-forge-app/ , but I don’t want to generate the token manually (it’s too hard).

Kind regards,
Andrey

1 Like

Hi @aorlov,

Unfortunately we haven’t yet added support for Forge to make authenticated requests to Connect, and vice versa. We’ve got plans to add authentication functionality in the future.

In terms of the difference between two applications and a single hybrid application, there are a few differences. Firstly, because in the ‘hybrid’ model, the apps share an identity, the apps will most likely share authentication credentials (once we implement that) - this should make authentication simpler as there would be no need to do an additional secret exchange. Secondly, the ‘hybrid’ app is discovered and installed separately for your users - they only have one app to install in ordee to get both underlying apps (the Forge app and the connect app) installed and enabled.

Are you able to share any details about the app that you’re building? I’m interested in hearing more about scenarios where building Forge and Connect apps in tandem is useful. You can DM me if you don’t want to share any information publicly.

Thanks!
Joe.

4 Likes

Hi @HeyJoe ,
Thank you for your answer. I have some additional question. Is there any possibility to set connectScopes (like connectModules) in Forge manifest.yml ? I mean the scopes https://developer.atlassian.com/cloud/confluence/scopes-for-connect-and-oauth-2-3LO-apps/ for my Java-backend.

Hi @aorlov,
As per this part of the guide, the connect scopes appear under scopes alongside the Forge scopes, but have a slightly different format:

Connect scopes appear in the Forge manifest as lower-cased, and with a suffix of either :connect-jira or :connect-confluence . It makes no difference which of the two is used, as long as the suffix contains connect in it. For example, the Connect READ scope becomes read:connect-jira or read:connect-confluence .

1 Like

Hey @jhazelwood I just started to play around with this and tried to add the PROJECT_ADMIN Connect scope to the manifest.yml. According to the quoted docs, this would translate to project_admin:connect-jira.

Unfortunately, this is rejected when I try to run forge deploy:

1:0     error    permissions property scopes 'project_admin:connect-jira' should match pattern "^[a-z]+:[a-z-.]+$"  valid-document-required

The regex does not accept scopes including underlines before the colon. I have tried a few variants of project_admin:connect-jira that would pass the regex but that then fails with

78:6    error    Invalid permission in the manifest.yml file: 'projectadmin:connect-jira'. Learn more about permissions at: http://go.atlassian.com/forge-permission

Can you advise on how to convert Connect scopes that include _ characters?

I am trying to add all my Connect modules to the Forge manifest.yml. For most this seems to have worked fine but the following two modules cause forge deploy to error.

  "jira:postInstallPage":
    {
      "key": "post-install-instructions",
      "location": "none",
      "name": {
        "value": "Post Install Instructions"
      },
      "url": "/post_install",
      "cacheable": true
    }
  "jira:webhooks":
    [
      {
        "event": "jira:issue_updated",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/issue/updated?projectId=${project.id}",
        "propertyKeys": [
            "intercom.conversation.links"
        ]
      },
      {
        "event": "comment_created",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/comment/created?projectId=${project.id}"
      },
      {
        "event": "comment_updated",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/comment/updated?projectId=${project.id}"
      }
    ]
forge deploy --verbose` log messages
...
Variables: {
  "appId": "ari:cloud:ecosystem::app/643bac58-09ea-4198-8943-87e12c9a3012",
  "environmentKey": "default",
  "id": "21"
}
  ◀️  GraphQL
Request ID: 5e3e90656d367cea
Result: {
  "appDeployment": {
    "status": "FAILED",
    "errorDetails": {
      "code": "ENVIRONMENT_UPDATE_VALIDATION_FAILED",
      "message": "Manifest validation failed",
      "fields": {
        "validationResult": {
          "tid": "785c9013da4026c8",
          "code": 400,
          "type": "APIError",
          "message": "RequestValidationError RequestValidationError: Schema validation error "
        }
      }
    },
    "stages": [
      {
        "description": "Validating manifest",
        "events": [
...
          {
            "__typename": "AppDeploymentLogEvent",
            "stepName": "Validate manifest",
            "createdAt": "2021-03-11T04:03:52.138Z",
            "message": "Manifest validation failed\nValidation errors: {\n  \"validationResult\": {\n    \"tid\": \"785c9013da4026c8\",\n    \"code\": 400,\n    \"type\": \"APIError\",\n    \"message\": \"RequestValidationError RequestValidationError: Schema validation error \"\n  }\n}",
            "level": "WARNING"
          },
          {
            "__typename": "AppDeploymentTransitionEvent",
            "stepName": "Validate manifest",
            "createdAt": "2021-03-11T04:03:52.139Z",
            "newStatus": "FAILED"
          }
        ]
      },
      {
        "description": "Snapshotting functions",
        "events": []
      },
      {
        "description": "Deploying to environment",
        "events": []
      }
    ]
  }
}
  Manifest validation failed
Validation errors: {
  "validationResult": {
    "tid": "785c9013da4026c8",
    "code": 400,
    "type": "APIError",
    "message": "RequestValidationError RequestValidationError: Schema validation error "
  }
}

Error: Deployment failed

Error: Deployment failed
    at ArtifactDeployer.handleErrorEvent (/usr/local/lib/node_modules/@forge/cli/out/deploy/deployer/deployer.js:138:15)
    at ArtifactDeployer.pollAndCheckEvents (/usr/local/lib/node_modules/@forge/cli/out/deploy/deployer/deployer.js:61:18)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
    at async ArtifactDeployer.monitorDeployment (/usr/local/lib/node_modules/@forge/cli/out/deploy/deployer/deployer.js:72:28)
    at async ArtifactDeployer.deploy (/usr/local/lib/node_modules/@forge/cli/out/deploy/deployer/deployer.js:36:9)
    at async PackageUploadDeployCommand.execute (/usr/local/lib/node_modules/@forge/cli/out/deploy/package-upload-deploy.js:14:9)
    at async CommandLineUI.displayProgress (/usr/local/lib/node_modules/@forge/cli/node_modules/@forge/cli-shared/out/ui/command-line-ui.js:44:28)
    at async DeployView.reportDeploymentProgress (/usr/local/lib/node_modules/@forge/cli/out/command-line/view/deploy-view.js:31:24)
    at async DeployController.run (/usr/local/lib/node_modules/@forge/cli/out/command-line/controller/deploy-controller.js:58:27)
    at async Command.actionProcessor (/usr/local/lib/node_modules/@forge/cli/out/command-line/command.js:74:32)

The logs point to schema validation issues but do not give a clear indication of where the problem is. I have tried with only the postInstallPage module and only the webhooks module but both failed. I have copy-pasted these modules from my Connect descriptor (apart from adding the jira: prefix) just like all the others.

Am I missing something here?

Hi @tbinna, I see that the docs are innaccurate on that point, sorry. project-admin:connect-jira is the scope you’re after. I’m investigating your second question now; for some reason the additional schema validation details have gone missing.

Thanks, James. I thought it should be project-admin:connect-jira but this variant is rejected by the Forge CLI which says scopes have to match this regex: ^[a-z]+:[a-z-.]+$. Before the colon, only lower-case characters are accepted. I guess it should be changed to something like ^[a-z-]+:[a-z-.]+$

Oh, dear. Thanks for the clarification, I’ll look into getting that fixed.

2 Likes

Hello again. I was able to find the details of the validation errors in our logs. I think there’s been a regression causing them not to come all the way through to the client. I’ll work on fixing that, but in the mean time here’s what worked for me. The changes I made were:

  • Put the postInstallPage in an array
  • Add keys to the webhooks
  • Add a remote with a baseUrl (you might’ve already done that and just not included it in your sample).

Until the fix for the scopes regex lands, you can pass --no-verify to the deploy method to force forge to try and deploy the manifest for you anyway.

connectModules:
  "jira:postInstallPage":
    [
      {
        "key": "post-install-instructions",
        "location": "none",
        "name": {
          "value": "Post Install Instructions"
        },
        "url": "/post_install",
        "cacheable": true
      }
    ]
  "jira:webhooks":
    [
      {
        "key": "jira-issue-updated",
        "event": "jira:issue_updated",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/issue/updated?projectId=${project.id}",
        "propertyKeys": [
            "intercom.conversation.links"
        ]
      },
      {
        "key": "comment-created",
        "event": "comment_created",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/comment/created?projectId=${project.id}"
      },
      {
        "key": "comment-updated",
        "event": "comment_updated",
        "filter": "project.conversationLinkingEnabled = 'true'",
        "url": "/webhook/comment/updated?projectId=${project.id}"
      }
    ]
remotes:
  - key: connect
    baseUrl: "https://www.example.com"
app:
  id: ari:cloud:ecosystem::app/3f27f440-d411-4b84-a0cc-62e09693cbb3
  name: harmonised-manifest-fail
2 Likes