mirror of
https://github.com/actions/configure-pages.git
synced 2025-12-08 16:16:09 +00:00
Add new API client to consolidate REST API calls
This commit is contained in:
87
src/api-client.js
Normal file
87
src/api-client.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
const axios = require('axios')
|
||||||
|
const core = require('@actions/core')
|
||||||
|
|
||||||
|
async function enablePagesSite({ repositoryNwo, githubToken }) {
|
||||||
|
const pagesEndpoint = `https://api.github.com/repos/${repositoryNwo}/pages`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
pagesEndpoint,
|
||||||
|
{ build_type: 'workflow' },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/vnd.github.v3+json',
|
||||||
|
Authorization: `Bearer ${githubToken}`,
|
||||||
|
'Content-type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const pageObject = response.data
|
||||||
|
return pageObject
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response && error.response.status === 409) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPagesSite({ repositoryNwo, githubToken }) {
|
||||||
|
try {
|
||||||
|
const pagesEndpoint = `https://api.github.com/repos/${repositoryNwo}/pages`
|
||||||
|
|
||||||
|
const response = await axios.get(pagesEndpoint, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/vnd.github.v3+json',
|
||||||
|
Authorization: `Bearer ${githubToken}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const pageObject = response.data
|
||||||
|
return pageObject
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findOrCreatePagesSite({ repositoryNwo, githubToken, enablement = true }) {
|
||||||
|
let pageObject
|
||||||
|
|
||||||
|
// Try to find an existing Pages site first
|
||||||
|
try {
|
||||||
|
pageObject = await getPagesSite({ repositoryNwo, githubToken })
|
||||||
|
} catch (error) {
|
||||||
|
if (!enablement) {
|
||||||
|
core.error('Get Pages site failed', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
core.warning('Get Pages site failed', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pageObject && enablement) {
|
||||||
|
// Create a new Pages site if one doesn't exist
|
||||||
|
try {
|
||||||
|
pageObject = await enablePagesSite({ repositoryNwo, githubToken })
|
||||||
|
} catch (error) {
|
||||||
|
core.error('Create Pages site failed', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
// This somehow implies that the Pages site was already created but initially failed to be retrieved.
|
||||||
|
// Try one more time for this extreme edge case!
|
||||||
|
if (pageObject == null) {
|
||||||
|
try {
|
||||||
|
pageObject = await getPagesSite({ repositoryNwo, githubToken })
|
||||||
|
} catch (error) {
|
||||||
|
core.error('Get Pages site still failed', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageObject
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { findOrCreatePagesSite, enablePagesSite, getPagesSite }
|
||||||
199
src/api-client.test.js
Normal file
199
src/api-client.test.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
const core = require('@actions/core')
|
||||||
|
const axios = require('axios')
|
||||||
|
|
||||||
|
const apiClient = require('./api-client')
|
||||||
|
|
||||||
|
describe('apiClient', () => {
|
||||||
|
const GITHUB_REPOSITORY = 'paper-spa/is-awesome'
|
||||||
|
const GITHUB_TOKEN = 'gha-token'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
|
||||||
|
// Mock error/warning/info/debug
|
||||||
|
jest.spyOn(core, 'error').mockImplementation(jest.fn())
|
||||||
|
jest.spyOn(core, 'warning').mockImplementation(jest.fn())
|
||||||
|
jest.spyOn(core, 'info').mockImplementation(jest.fn())
|
||||||
|
jest.spyOn(core, 'debug').mockImplementation(jest.fn())
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
describe('enablePagesSite', () => {
|
||||||
|
it('makes a request to create a page', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: pageObject }))
|
||||||
|
|
||||||
|
const result = await apiClient.enablePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles a 409 response when the page already exists', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(axios, 'post')
|
||||||
|
.mockImplementationOnce(() => Promise.reject({ response: { status: 409 } }))
|
||||||
|
|
||||||
|
// Simply assert that no error is raised
|
||||||
|
const result = await apiClient.enablePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toBe(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('re-raises errors on failure status codes', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(axios, 'post')
|
||||||
|
.mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
|
||||||
|
let erred = false
|
||||||
|
try {
|
||||||
|
await apiClient.enablePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
erred = true
|
||||||
|
expect(error.response.status).toEqual(404)
|
||||||
|
}
|
||||||
|
expect(erred).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getPagesSite', () => {
|
||||||
|
it('makes a request to get a page', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.resolve({ status: 200, data: pageObject }))
|
||||||
|
|
||||||
|
const result = await apiClient.getPagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('re-raises errors on failure status codes', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(axios, 'get')
|
||||||
|
.mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
|
||||||
|
let erred = false
|
||||||
|
try {
|
||||||
|
await apiClient.getPagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
erred = true
|
||||||
|
expect(error.response.status).toEqual(404)
|
||||||
|
}
|
||||||
|
expect(erred).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('findOrCreatePagesSite', () => {
|
||||||
|
it('does not make a request to create a page if it already exists', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.resolve({ status: 200, data: pageObject }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
|
||||||
|
const result = await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('makes request to create a page by default if it does not exist', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: pageObject }))
|
||||||
|
|
||||||
|
const result = await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('makes a request to create a page when explicitly enabled if it does not exist', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: pageObject }))
|
||||||
|
|
||||||
|
const result = await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN,
|
||||||
|
enablement: true
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not make a request to create a page when explicitly disabled even if it does not exist', async () => {
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 500 } })) // just so they both aren't 404
|
||||||
|
|
||||||
|
let erred = false
|
||||||
|
try {
|
||||||
|
await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN,
|
||||||
|
enablement: false
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
erred = true
|
||||||
|
// re-raised error
|
||||||
|
expect(error.response.status).toEqual(404)
|
||||||
|
}
|
||||||
|
expect(erred).toBe(true)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not make a second request to get page if create fails for reason other than existence', async () => {
|
||||||
|
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 500 } })) // just so they both aren't 404
|
||||||
|
|
||||||
|
let erred = false
|
||||||
|
try {
|
||||||
|
await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
erred = true
|
||||||
|
// re-raised error
|
||||||
|
expect(error.response.status).toEqual(500)
|
||||||
|
}
|
||||||
|
expect(erred).toBe(true)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('makes second request to get page if create fails because of existence', async () => {
|
||||||
|
const pageObject = { html_url: 'https://paper-spa.github.io/is-awesome/' }
|
||||||
|
jest.spyOn(axios, 'get')
|
||||||
|
.mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
|
||||||
|
.mockImplementationOnce(() => Promise.resolve({ status: 200, data: pageObject }))
|
||||||
|
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 409 } }))
|
||||||
|
|
||||||
|
const result = await apiClient.findOrCreatePagesSite({
|
||||||
|
repositoryNwo: GITHUB_REPOSITORY,
|
||||||
|
githubToken: GITHUB_TOKEN
|
||||||
|
})
|
||||||
|
expect(result).toEqual(pageObject)
|
||||||
|
expect(axios.get).toHaveBeenCalledTimes(2)
|
||||||
|
expect(axios.post).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user