Skip to content

Commit c71f6e6

Browse files
authored
Merge pull request #310 from atlassian/GUA-708-fix-unknown-env-for-builds
Gua 708 fix unknown env for builds
2 parents 60c4047 + 9c74782 commit c71f6e6

File tree

4 files changed

+68
-12
lines changed

4 files changed

+68
-12
lines changed

app/README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,22 @@ The filter `setid` is used in `/app/.gitattributes` so that it replaces your app
7171
#### Install the app to your Jira instance
7272

7373
1. Build your app by running `yarn build` in **/app/jenkins-for-jira-ui**.
74-
2. Deploy your app by running `forge deploy` in **/app**. See [Common Issues](#common-issues) if unsuccessful.
74+
2. Deploy your app by running `forge deploy --no-verify` in **/app**. See [Common Issues](#common-issues) if unsuccessful.
7575
3. Install your app to your Jira site by running `forge install` in **/app**.
7676

7777
Follow the instructions in this setup wizard. Enter the hostname for your Jira site (e.g. `<your-site-name>.atlassian.net`).
7878

7979
> NOTE: This is the *only* step that needs to be repeated to install on different Jira sites. Do not repeat the steps above `forge deploy`. To run your app, follow the steps below.
8080
8181
## Running the app
82-
To run the app, make sure you have installed the app on your site as described above. You'll also need to your `ngrok-config-path` so you can create a local tunnel. Sign up to [ngrok](https://ngrok.com/) if you have not done so. To do this:
83-
1. Run `forge settings set ngrok-config-path <path-to-your-ngrok-config>`.
84-
2. Confirm this was set correctly by running `forge settings list`. You should see a table that includes this variable with a value set to your ngrok config path.
8582

8683
### Run the app locally
8784

8885
To start the app locally, run `yarn start` in **/app/jenkins-for-jira-ui**.
8986

9087
The command line will suggest navigating to `localhost:3000` but this does not work for `Custom UI` Forge apps. For more information, see [here](https://community.developer.atlassian.com/t/forge-tunneling-customui-with-ui-resolver-error-cannot-read-property-callbridge-of-undefined/47010/3).
9188

92-
To see your local app in the Jira instance you installed the app into, run `forge tunnel` in the **/app** folder. If this fails, ensure you have correctly set `ngrok-config-path`.
89+
To see your local app in the Jira instance you installed the app into, run `forge tunnel` in the **/app** folder.
9390

9491
All your changes are instantly propagated to your Jira site and you can see them without the need to rebuild or redeploy your app.
9592

@@ -114,4 +111,3 @@ In the **/app/jenkins-for-jira-ui** dir, run `yarn test`.
114111
1. For unsuccessful `forge deploy`, run `forge deploy --no-verify` if everything is good except for 2 acceptable errors...
115112
- `invalid value 'devops:deploymentInfoProvider' in modules`
116113
- `invalid value 'devops:buildInfoProvider' in modules`
117-

app/jenkins-for-jira-ui/src/components/InProductHelpDrawer/InProductHelp.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,12 @@ describe('InProductHelpDrawer Suite', () => {
197197
isDrawerOpen
198198
setIsDrawerOpen={() => {}}
199199
searchResults={[
200-
{id: '1', title: 'Result 1', body: 'Body 1', bodyText: 'Body Text 1'},
201-
{id: '2', title: 'Result 2', body: 'Body 2', bodyText: 'Body Text 2'}]}
200+
{
201+
id: '1', title: 'Result 1', body: 'Body 1', bodyText: 'Body Text 1'
202+
},
203+
{
204+
id: '2', title: 'Result 2', body: 'Body 2', bodyText: 'Body Text 2'
205+
}]}
202206
isLoading={false}
203207
searchQuery=""
204208
setIsLoading={() => {}}

app/src/webtrigger/handle-jenkins-request.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const JENKINS_SERVER_UUID = '1aaf4ea5-bca5-4ec9-86ed-c359e359eb97';
5656
// You can paste the JWT into https://jwt.io to see its contents
5757
/* eslint-disable-next-line max-len */
5858
const BUILD_EVENT_JWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJqZW5raW5zLWZvcmdlLWFwcCIsInJlcXVlc3RfYm9keV9qc29uIjoie1wicmVxdWVzdFR5cGVcIjpcImV2ZW50XCIsXCJldmVudFR5cGVcIjpcImJ1aWxkXCIsXCJwaXBlbGluZU5hbWVcIjpcInBpcGVsaW5lTmFtZVwiLFwic3RhdHVzXCI6XCJzdWNjZXNzZnVsXCIsXCJsYXN0VXBkYXRlZFwiOlwiMjAyMi0wMy0wN1QwNDozOTozMy4xNDE5NjNaXCIsXCJwYXlsb2FkXCI6e1wicHJvcGVydGllc1wiOntcInNvdXJjZVwiOlwiamVua2luc1wifSxcInByb3ZpZGVyTWV0YWRhdGFcIjp7XCJwcm9kdWN0XCI6XCJqZW5raW5zXCJ9LFwiYnVpbGRzXCI6W3tcInBpcGVsaW5lSWRcIjpcInBpcGVsaW5lSWRcIixcImJ1aWxkTnVtYmVyXCI6MTIsXCJ1cGRhdGVTZXF1ZW5jZU51bWJlclwiOjEyLFwiZGlzcGxheU5hbWVcIjpcInBpcGVsaW5lTmFtZVwiLFwiZGVzY3JpcHRpb25cIjpcImRlc2NyaXB0aW9uXCIsXCJsYWJlbFwiOlwibGFiZWxcIixcInVybFwiOlwiaHR0cHM6Ly91cmwuY29tXCIsXCJzdGF0ZVwiOlwic3VjY2Vzc2Z1bFwiLFwibGFzdFVwZGF0ZWRcIjpcIjIwMjItMDMtMDdUMDQ6Mzk6MzMuMTQyMjAxWlwiLFwiaXNzdWVLZXlzXCI6W1wiSkVOLTI1XCJdLFwicmVmZXJlbmNlc1wiOlt7XCJjb21taXRcIjp7XCJpZFwiOlwiY2FmZWJhYmVcIixcInJlcG9zaXRvcnlVcmlcIjpcImh0dHBzOi8vcmVwby51cmxcIn0sXCJyZWZcIjp7XCJuYW1lXCI6XCJyZWZuYW1lXCIsXCJ1cmlcIjpcImh0dHBzOnJlZi51cmlcIn19XSxcInRlc3RJbmZvXCI6e1widG90YWxOdW1iZXJcIjowLFwibnVtYmVyUGFzc2VkXCI6MCxcIm51bWJlckZhaWxlZFwiOjAsXCJudW1iZXJTa2lwcGVkXCI6MH0sXCJzY2hlbWFWZXJzaW9uXCI6XCIxLjBcIn1dfSxcInBpcGVsaW5lSWRcIjpcInBpcGVsaW5lSWRcIn0iLCJpc3MiOiJqZW5raW5zLXBsdWdpbiIsImV4cCI6MzI0NzQ4MzkxNzEsImlhdCI6MTY0NjYyNzk3M30.N5ZcLeoBVLlnZYok0AWqzYkxoS-O3vBilmiOXoobiko';
59+
const BUILD_EVENT_LAST_UPDATED = '2022-03-07T04:39:33.141963Z';
5960
const BUILD_EVENT_PAYLOAD = {
6061
properties: { source: 'jenkins' },
6162
providerMetadata: { product: 'jenkins' },
@@ -94,6 +95,7 @@ const BUILD_EVENT_PAYLOAD = {
9495
// You can paste the JWT into https://jwt.io to see its contents
9596
/* eslint-disable-next-line max-len */
9697
const DEPLOYMENT_EVENT_JWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJqZW5raW5zLWZvcmdlLWFwcCIsInJlcXVlc3RfYm9keV9qc29uIjoie1wicmVxdWVzdFR5cGVcIjpcImV2ZW50XCIsXCJldmVudFR5cGVcIjpcImRlcGxveW1lbnRcIixcInBpcGVsaW5lTmFtZVwiOlwicGlwZWxpbmVOYW1lXCIsXCJzdGF0dXNcIjpcInN1Y2Nlc3NmdWxcIixcImxhc3RVcGRhdGVkXCI6XCIyMDIyLTAzLTA3VDA2OjMwOjQ4Ljg3MDMwOVpcIixcInBheWxvYWRcIjp7XCJwcm9wZXJ0aWVzXCI6e1wic291cmNlXCI6XCJqZW5raW5zXCJ9LFwicHJvdmlkZXJNZXRhZGF0YVwiOntcInByb2R1Y3RcIjpcImplbmtpbnNcIn0sXCJkZXBsb3ltZW50c1wiOlt7XCJkZXBsb3ltZW50U2VxdWVuY2VOdW1iZXJcIjo0MixcInVwZGF0ZVNlcXVlbmNlTnVtYmVyXCI6NDUsXCJhc3NvY2lhdGlvbnNcIjpbe1widmFsdWVzXCI6W1wiSkVOLTI1XCJdLFwiYXNzb2NpYXRpb25UeXBlXCI6XCJpc3N1ZUtleXNcIn1dLFwiZGlzcGxheU5hbWVcIjpcInBpcGVsaW5lTmFtZVwiLFwidXJsXCI6XCJodHRwczovL3VybC5jb21cIixcImRlc2NyaXB0aW9uXCI6XCJkZXNjcmlwdGlvblwiLFwibGFzdFVwZGF0ZWRcIjpcIjIwMjItMDMtMDdUMDY6MzA6NDguODcwNTkzWlwiLFwibGFiZWxcIjpcImxhYmVsXCIsXCJzdGF0ZVwiOlwic3VjY2Vzc2Z1bFwiLFwicGlwZWxpbmVcIjp7XCJpZFwiOlwicGlwZWxpbmVJZFwiLFwiZGlzcGxheU5hbWVcIjpcInBpcGVsaW5lTmFtZVwiLFwidXJsXCI6XCJodHRwczovL3VybC5jb21cIn0sXCJlbnZpcm9ubWVudFwiOntcImlkXCI6XCJzdGctZWFzdFwiLFwiZGlzcGxheU5hbWVcIjpcIlN0YWdpbmcgZWFzdFwiLFwidHlwZVwiOlwic3RhZ2luZ1wifSxcInNjaGVtYVZlcnNpb25cIjpcIjEuMFwifV19LFwicGlwZWxpbmVJZFwiOlwicGlwZWxpbmVJZFwifSIsImlzcyI6ImplbmtpbnMtcGx1Z2luIiwiZXhwIjozMjQ3NDg0NTg0NywiaWF0IjoxNjQ2NjM0NjQ4fQ.D1JP5439A3CQ-8ys6gGCrMfhpeaFuMITaFwqSo86MbU';
98+
const DEPLOYMENT_EVENT_LAST_UPDATED = '2022-03-07T06:30:48.870309Z';
9799
const DEPLOYMENT_EVENT_PAYLOAD = {
98100
properties: { source: 'jenkins' },
99101
providerMetadata: { product: 'jenkins' },
@@ -226,6 +228,30 @@ describe('Jenkins webtrigger', () => {
226228
expect(response.body).toBe(JSON.stringify(jiraResponse.body));
227229
});
228230

231+
it('should save a build to server state', async () => {
232+
// given
233+
const jiraResponse = createJiraResponse(200);
234+
givenStorageReturnsJenkinsServerSecret();
235+
givenStorageReturnsJenkinsServer();
236+
givenJiraRespondsToEvent(EventType.BUILD, BUILD_EVENT_PAYLOAD, jiraResponse);
237+
238+
// when
239+
await handleJenkinsRequest(createWebtriggerRequest(BUILD_EVENT_JWT), context);
240+
241+
// then
242+
expect(storage.set).toBeCalledWith(`jenkinsServer-${JENKINS_SERVER_UUID}`, {
243+
name: 'Jenkins Server',
244+
pipelines: [{
245+
name: 'pipelineName',
246+
environmentNames: undefined,
247+
lastEventDate: BUILD_EVENT_LAST_UPDATED,
248+
lastEventType: EventType.BUILD,
249+
lastEventStatus: BUILD_EVENT_PAYLOAD.builds[0].state
250+
}],
251+
uuid: JENKINS_SERVER_UUID
252+
});
253+
});
254+
229255
it('should send a deployment event to Jira and return the Jira response', async () => {
230256
// given
231257
const jiraResponse = createJiraResponse(200);
@@ -242,6 +268,30 @@ describe('Jenkins webtrigger', () => {
242268
expect(response.body).toBe(JSON.stringify(jiraResponse.body));
243269
});
244270

271+
it('should save a deployment to server state', async () => {
272+
// given
273+
const jiraResponse = createJiraResponse(200);
274+
givenStorageReturnsJenkinsServerSecret();
275+
givenStorageReturnsJenkinsServer();
276+
givenJiraRespondsToEvent(EventType.DEPLOYMENT, DEPLOYMENT_EVENT_PAYLOAD, jiraResponse);
277+
278+
// when
279+
await handleJenkinsRequest(createWebtriggerRequest(DEPLOYMENT_EVENT_JWT), context);
280+
281+
// then
282+
expect(storage.set).toBeCalledWith(`jenkinsServer-${JENKINS_SERVER_UUID}`, {
283+
name: 'Jenkins Server',
284+
pipelines: [{
285+
name: 'pipelineName',
286+
environmentNames: [DEPLOYMENT_EVENT_PAYLOAD.deployments[0].environment.displayName],
287+
lastEventDate: DEPLOYMENT_EVENT_LAST_UPDATED,
288+
lastEventType: EventType.DEPLOYMENT,
289+
lastEventStatus: DEPLOYMENT_EVENT_PAYLOAD.deployments[0].state
290+
}],
291+
uuid: JENKINS_SERVER_UUID
292+
});
293+
});
294+
245295
it('should return 400 on invalid request type', async () => {
246296
// given
247297
givenStorageReturnsJenkinsServerSecret();

app/src/webtrigger/handle-jenkins-request.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ export default async function handleJenkinsRequest(
8585
}
8686
}
8787

88-
function extractEnvironmentName(event: JenkinsEvent): string {
88+
function extractEnvironmentName(event: JenkinsEvent): string | undefined {
89+
if (event.eventType === EventType.BUILD) {
90+
return undefined;
91+
}
8992
const { payload } = event;
9093

9194
return (
@@ -107,8 +110,10 @@ async function handleEvent(
107110
return createWebtriggerResponse(400, `invalid event type: ${event.eventType}`);
108111
}
109112

110-
const pipeline: JenkinsPipeline = convertToPipeline(event);
111-
await updateJenkinsServerState(jenkinsServerUuid, pipeline, logger);
113+
{
114+
const pipeline: JenkinsPipeline = convertToPipeline(event);
115+
await updateJenkinsServerState(jenkinsServerUuid, pipeline, logger);
116+
}
112117
event.payload.properties = event.payload.properties || {};
113118
event.payload.properties.cloudId = cloudId;
114119
event.payload.properties.jenkinsServerUuid = jenkinsServerUuid;
@@ -169,11 +174,12 @@ function isBuildOrDeploymentEvent(type: EventType): boolean {
169174
}
170175

171176
function convertToPipeline(event: JenkinsEvent): JenkinsPipeline {
177+
const maybeEnvName = extractEnvironmentName(event);
172178
return {
173179
name: event.pipelineName!,
174180
lastEventType: event.eventType,
175181
lastEventStatus: event.status!,
176182
lastEventDate: event.lastUpdated!,
177-
environmentNames: [extractEnvironmentName(event)]
183+
environmentNames: maybeEnvName ? [maybeEnvName] : undefined
178184
};
179185
}

0 commit comments

Comments
 (0)