Skip to content

Commit a6d2b24

Browse files
committed
add pagination logic to latestActiveDeployment() to make it more robust
1 parent d806f9d commit a6d2b24

File tree

4 files changed

+221
-44
lines changed

4 files changed

+221
-44
lines changed

__tests__/functions/deployment.test.js

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ beforeEach(() => {
4747
oid: '315cec138fc9d7dac8a47c6bba4217d3965ede3b'
4848
}
4949
}
50-
]
50+
],
51+
pageInfo: {
52+
endCursor: null,
53+
hasNextPage: false
54+
}
5155
}
5256
}
5357
}
@@ -139,6 +143,121 @@ test('returns null if no deployments are found', async () => {
139143
expect(octokit.graphql).toHaveBeenCalled()
140144
})
141145

146+
test('returns null if no deployments are found in 3 pages of queries', async () => {
147+
octokit.graphql = jest
148+
.fn()
149+
.mockReturnValueOnce({
150+
repository: {
151+
deployments: {
152+
nodes: [
153+
{
154+
state: 'INACTIVE'
155+
}
156+
],
157+
pageInfo: {
158+
endCursor: 'cursor',
159+
hasNextPage: true
160+
}
161+
}
162+
}
163+
})
164+
.mockReturnValueOnce({
165+
repository: {
166+
deployments: {
167+
nodes: [
168+
{
169+
state: 'INACTIVE'
170+
}
171+
],
172+
pageInfo: {
173+
endCursor: 'cursor',
174+
hasNextPage: true
175+
}
176+
}
177+
}
178+
})
179+
.mockReturnValueOnce({
180+
repository: {
181+
deployments: {
182+
nodes: [
183+
{
184+
state: 'INACTIVE'
185+
}
186+
],
187+
pageInfo: {
188+
endCursor: 'cursor',
189+
hasNextPage: false
190+
}
191+
}
192+
}
193+
})
194+
195+
expect(await latestActiveDeployment(octokit, context, environment)).toBeNull()
196+
197+
expect(octokit.graphql).toHaveBeenCalledTimes(3)
198+
})
199+
200+
test('returns the deployment when it is found in the second page of queries', async () => {
201+
octokit.graphql = jest
202+
.fn()
203+
.mockReturnValueOnce({
204+
repository: {
205+
deployments: {
206+
nodes: [
207+
{
208+
state: 'INACTIVE'
209+
},
210+
{
211+
state: 'INACTIVE'
212+
},
213+
{
214+
state: 'INACTIVE'
215+
},
216+
{
217+
state: 'PENDING'
218+
}
219+
],
220+
pageInfo: {
221+
endCursor: 'cursor',
222+
hasNextPage: true
223+
}
224+
}
225+
}
226+
})
227+
.mockReturnValueOnce({
228+
repository: {
229+
deployments: {
230+
nodes: [
231+
{
232+
state: 'INACTIVE'
233+
},
234+
{
235+
state: 'INACTIVE'
236+
},
237+
{
238+
state: 'ACTIVE'
239+
},
240+
{
241+
state: 'INACTIVE'
242+
}
243+
],
244+
pageInfo: {
245+
endCursor: 'cursor',
246+
hasNextPage: true
247+
}
248+
}
249+
}
250+
})
251+
252+
expect(
253+
await latestActiveDeployment(octokit, context, environment)
254+
).toStrictEqual({
255+
state: 'ACTIVE'
256+
})
257+
258+
expect(octokit.graphql).toHaveBeenCalledTimes(2)
259+
})
260+
142261
test('returns false if the deployment is not active', async () => {
143262
mockDeploymentData.repository.deployments.nodes[0].state = 'INACTIVE'
144263
octokit = createMockGraphQLOctokit(mockDeploymentData)

dist/index.js

Lines changed: 50 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/functions/deployment.js

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,56 @@ export async function activeDeployment(octokit, context, environment, sha) {
7878
// }
7979
// ]
8080
export async function latestActiveDeployment(octokit, context, environment) {
81-
// Get the owner and the repo from the context
8281
const {owner, repo} = context.repo
8382

84-
const query = `
83+
const variables = {
84+
repo_owner: owner,
85+
repo_name: repo,
86+
environment: environment
87+
}
88+
89+
let data = await octokit.graphql(buildQuery(), variables)
90+
// nodes may be empty if no matching deployments were found - ex: []
91+
let nodes = data.repository.deployments.nodes
92+
93+
// If no deployments were found, return null
94+
if (nodes.length === 0) {
95+
return null
96+
}
97+
98+
// Check for an active deployment in the first page of deployments
99+
let activeDeployment = nodes.find(deployment => deployment.state === 'ACTIVE')
100+
if (activeDeployment) {
101+
return activeDeployment
102+
}
103+
104+
// Paginate to find the active deployment if it exists
105+
let hasNextPage = data.repository.deployments.pageInfo.hasNextPage
106+
let endCursor = data.repository.deployments.pageInfo.endCursor
107+
108+
while (hasNextPage) {
109+
data = await octokit.graphql(buildQuery(endCursor), variables)
110+
111+
nodes = data.repository.deployments.nodes
112+
activeDeployment = nodes.find(deployment => deployment.state === 'ACTIVE')
113+
114+
if (activeDeployment) {
115+
return activeDeployment
116+
}
117+
118+
hasNextPage = data.repository.deployments.pageInfo.hasNextPage
119+
endCursor = data.repository.deployments.pageInfo.endCursor
120+
}
121+
122+
// If no active deployment was found, return null
123+
return null
124+
}
125+
126+
function buildQuery(page = null) {
127+
return `
85128
query ($repo_owner: String!, $repo_name: String!, $environment: String!) {
86129
repository(owner: $repo_owner, name: $repo_name) {
87-
deployments(environments: [$environment], first: 1, orderBy: { field: CREATED_AT, direction: DESC }) {
130+
deployments(environments: [$environment], first: 100, after: ${page}, orderBy: { field: CREATED_AT, direction: DESC }) {
88131
nodes {
89132
createdAt
90133
environment
@@ -102,25 +145,11 @@ export async function latestActiveDeployment(octokit, context, environment) {
102145
oid
103146
}
104147
}
148+
pageInfo {
149+
endCursor
150+
hasNextPage
151+
}
105152
}
106153
}
107154
}`
108-
109-
const variables = {
110-
repo_owner: owner,
111-
repo_name: repo,
112-
environment: environment
113-
}
114-
115-
const data = await octokit.graphql(query, variables)
116-
// nodes may be empty if no matching deployments were found - ex: []
117-
const nodes = data.repository.deployments.nodes
118-
119-
// If no deployments were found, return null
120-
if (nodes.length === 0) {
121-
return null
122-
}
123-
124-
// Otherwise, return the latest deployment
125-
return nodes[0]
126155
}

0 commit comments

Comments
 (0)