Skip to content

Commit

Permalink
Revert "feat(defaults): Download defaults file from github release" (#…
Browse files Browse the repository at this point in the history
…175)

Revert "feat(defaults): Download defaults file from github release (#174)"

This reverts commit 56cb244.
  • Loading branch information
CCFenner authored Feb 20, 2024
1 parent 56cb244 commit 28caec7
Show file tree
Hide file tree
Showing 9 changed files with 391 additions and 386 deletions.
244 changes: 146 additions & 98 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

69 changes: 28 additions & 41 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import { debug, exportVariable, info } from '@actions/core'
import * as artifact from '@actions/artifact'
import { type UploadResponse } from '@actions/artifact'
import { executePiper } from './execute'
import { downloadFileFromGitHub, getHost, getReleaseAssetUrl } from './github'
import {
ENTERPRISE_DEFAULTS_FILENAME,
ENTERPRISE_STAGE_CONFIG_FILENAME,
getEnterpriseStageConfigUrl
} from './enterprise'
import { downloadFileFromGitHub, getHost } from './github'
import { ENTERPRISE_DEFAULTS_FILENAME, ENTERPRISE_STAGE_CONFIG_FILENAME, getEnterpriseDefaultsUrl, getEnterpriseStageConfigUrl } from './enterprise'
import { internalActionVariables } from './piper'

export const CONFIG_DIR = '.pipeline'
export const ARTIFACT_NAME = 'Pipeline defaults'

export async function getDefaultConfig (
server: string, apiURL: string, version: string, token: string, owner: string, repository: string, customDefaultsPaths: string
): Promise<number> {
export async function getDefaultConfig (server: string, token: string, owner: string, repository: string, customDefaultsPaths: string): Promise<number> {
if (fs.existsSync(path.join(CONFIG_DIR, ENTERPRISE_DEFAULTS_FILENAME))) {
info('Defaults are present')

Expand All @@ -28,38 +22,35 @@ export async function getDefaultConfig (
}

return await Promise.resolve(0)
}

try {
info('Restoring default config')
// throws an error with message containing 'Unable to find' if artifact does not exist
await restoreDefaultConfig()
info('Defaults restored from artifact')

return await Promise.resolve(0)
} catch (err: unknown) {
if (err instanceof Error && !err.message.includes('Unable to find')) {
throw err
} else {
try {
info('Restoring default config')
// throws an error with message containing 'Unable to find' if artifact does not exist
await restoreDefaultConfig()
info('Defaults restored from artifact')

return await Promise.resolve(0)
} catch (err: unknown) {
if (err instanceof Error && !err.message.includes('Unable to find')) {
throw err
}

// continue with downloading defaults and upload as artifact
info('Defaults artifact does not exist yet')
info('Downloading defaults')
await downloadDefaultConfig(server, token, owner, repository, customDefaultsPaths)

return await Promise.resolve(0)
}

// continue with downloading defaults and upload as artifact
info('Defaults artifact does not exist yet')
info('Downloading defaults')
await downloadDefaultConfig(server, apiURL, version, token, owner, repository, customDefaultsPaths)

return await Promise.resolve(0)
}
}

export async function downloadDefaultConfig (
server: string, apiURL: string, version: string, token: string, owner: string, repository: string, customDefaultsPaths: string
): Promise<UploadResponse> {
export async function downloadDefaultConfig (server: string, token: string, owner: string, repository: string, customDefaultsPaths: string): Promise<UploadResponse> {
const customDefaultsPathsArray = customDefaultsPaths !== '' ? customDefaultsPaths.split(',') : []

const [defaultsAssetURL] = await getReleaseAssetUrl(ENTERPRISE_DEFAULTS_FILENAME, version, apiURL, token, owner, repository)
const enterpriseDefaultsPath = getEnterpriseDefaultsUrl(owner, repository)
let defaultsPaths: string[] = []
if (defaultsAssetURL !== '') {
defaultsPaths = defaultsPaths.concat([defaultsAssetURL])
if (enterpriseDefaultsPath !== '') {
defaultsPaths = defaultsPaths.concat([enterpriseDefaultsPath])
}
defaultsPaths = defaultsPaths.concat(customDefaultsPathsArray)
const defaultsPathsArgs = defaultsPaths.map((url) => ['--defaultsFile', url]).flat()
Expand All @@ -74,9 +65,7 @@ export async function downloadDefaultConfig (
const piperExec = await executePiper('getDefaults', flags)

let defaultConfigs = JSON.parse(piperExec.output)
if (customDefaultsPathsArray.length === 0) {
defaultConfigs = [defaultConfigs]
}
if (customDefaultsPathsArray.length === 0) { defaultConfigs = [defaultConfigs] }

const savedDefaultsPaths = saveDefaultConfigs(defaultConfigs)
const uploadResponse = await uploadDefaultConfigArtifact(savedDefaultsPaths)
Expand Down Expand Up @@ -120,9 +109,7 @@ export async function createCheckIfStepActiveMaps (token: string, owner: string,

await downloadStageConfig(token, owner, repository)
.then(async () => await checkIfStepActive('_', '_', true))
.catch(err => {
info(`checkIfStepActive failed: ${err as string}`)
})
.catch(err => { info(`checkIfStepActive failed: ${err as string}`) })
}

export async function checkIfStepActive (stepName: string, stageName: string, outputMaps: boolean): Promise<number> {
Expand Down
9 changes: 8 additions & 1 deletion src/enterprise.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GITHUB_COM_SERVER_URL } from './github'

export const ENTERPRISE_DEFAULTS_FILENAME = 'piper-defaults-github.yml'
export const ENTERPRISE_DEFAULTS_FILENAME = 'piper-defaults.yml'
export const ENTERPRISE_STAGE_CONFIG_FILENAME = 'github-stage-config.yml'

const ENTERPRISE_STEPNAME_PREFIX = 'sap'
Expand All @@ -17,6 +17,13 @@ export function onGitHubEnterprise (): boolean {
return process.env.GITHUB_SERVER_URL !== GITHUB_COM_SERVER_URL
}

export function getEnterpriseDefaultsUrl (owner: string, repository: string): string {
if (onGitHubEnterprise() && owner !== '' && repository !== '') {
return `${process.env.GITHUB_API_URL}/repos/${owner}/${repository}/contents/resources/${ENTERPRISE_DEFAULTS_FILENAME}`
}
return ''
}

export function getEnterpriseStageConfigUrl (owner: string, repository: string): string {
if (onGitHubEnterprise() && owner !== '' && repository !== '') {
return `${process.env.GITHUB_API_URL}/repos/${owner}/${repository}/contents/resources/${ENTERPRISE_STAGE_CONFIG_FILENAME}`
Expand Down
184 changes: 107 additions & 77 deletions src/github.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,60 @@
import * as fs from 'fs'
import { join } from 'path'
import { chdir, cwd } from 'process'
import fetch from 'node-fetch'
import { Octokit } from '@octokit/core'
import { type OctokitOptions } from '@octokit/core/dist-types/types'
import { type OctokitResponse } from '@octokit/types'
import { downloadTool, extractZip } from '@actions/tool-cache'
import { debug, info } from '@actions/core'
import { info } from '@actions/core'
import { exec } from '@actions/exec'
import { isEnterpriseStep } from './enterprise'
// import { restoreCache, saveCache } from '@actions/cache'

export const GITHUB_COM_SERVER_URL = 'https://github.com'
export const GITHUB_COM_API_URL = 'https://api.github.com'
export const OS_PIPER_OWNER = 'SAP'
export const OS_PIPER_REPO = 'jenkins-library'

export function getHost (url: string): string {
return url === '' ? '' : new URL(url).host
}

export async function downloadPiperBinary (stepName: string, version: string, apiURL: string, token: string, owner: string, repo: string): Promise<string> {
const isEnterprise = isEnterpriseStep(stepName)
if (isEnterprise && token === '') {
export async function downloadPiperBinary (stepName: string, version: string, api: string, token: string, sapPiperOwner: string, sapPiperRepository: string): Promise<string> {
if (token === undefined && isEnterpriseStep(stepName)) {
throw new Error(`Token is not provided for enterprise step: ${stepName}`)
}
if (owner === '') {
throw new Error('owner is not provided')
}
if (repo === '') {
throw new Error('repository is not provided')
}

const piperBinaryName = await getPiperBinaryNameFromInputs(isEnterprise, version)
const [binaryAssetURL, tag] = await getReleaseAssetUrl(piperBinaryName, version, apiURL, token, owner, repo)
const headers: any = {}
headers.Accept = 'application/octet-stream'
if (token !== '') {
headers.Authorization = `token ${token}`
const piper = await getPiperBinaryNameFromInputs(stepName, version)
let url, headers
if (token !== undefined && token !== '') {
const response = await getPiperReleases(isEnterpriseStep(stepName), version, api, token, sapPiperOwner, sapPiperRepository)
url = response.data.assets.find((asset: { name: string }) => {
return asset.name === piper
}).url
version = response.data.tag_name
headers = {
Authorization: `token ${token}`,
Accept: 'application/octet-stream'
}
} else {
url = await getPiperDownloadURL(piper, version)
version = url.split('/').slice(-2)[0]
}

const piperBinaryDestPath = `${process.cwd()}/${tag.replace(/\./g, '_')}/${piperBinaryName}`
if (fs.existsSync(piperBinaryDestPath)) {
return piperBinaryDestPath
const piperPath = `${process.cwd()}/${version.replace(/\./g, '_')}/${piper}`
if (fs.existsSync(piperPath)) {
return piperPath
}

info(`Downloading binary '${piperBinaryName}' into ${piperBinaryDestPath}`)
// let piperPathCached
// if ((piperPathCached = await restorePiper(piperPath))) {
// return piperPathCached
// }
info(`Downloading ${piper}`)
await downloadTool(
binaryAssetURL,
piperBinaryDestPath,
url,
piperPath,
undefined,
headers
)

return piperBinaryDestPath
}

export async function getReleaseAssetUrl (
assetName: string, version: string, apiURL: string, token: string, owner: string, repo: string
): Promise<[string, string]> {
const getReleaseResponse = await getPiperReleases(version, apiURL, token, owner, repo)
const url = getReleaseResponse.data.assets.find((asset: { name: string }) => {
return asset.name === assetName
}).url

const tag = getReleaseResponse.data.tag_name // version of release
debug(`Found asset URL: ${url} and tag: ${tag}`)
return [url, tag]
}

// by default for inner source Piper
async function getPiperReleases (version: string, api: string, token: string, owner: string, repository: string): Promise<OctokitResponse<any>> {
const tag = getTag(version)

const options: OctokitOptions = {}
options.baseUrl = api
if (token !== '') {
options.auth = token
}

const octokit = new Octokit(options)
info(`Getting releases from /repos/${owner}/${repository}/releases/${tag}`)
const response = await octokit.request(`GET /repos/${owner}/${repository}/releases/${tag}`)
if (response.status !== 200) {
throw new Error(`can't get release by tag ${tag}: ${response.status}`)
}

return response
// await savePiper(piperPath)
return piperPath
}

// Format for development versions (all parts required): 'devel:GH_OWNER:REPOSITORY:COMMITISH'
Expand Down Expand Up @@ -114,7 +84,9 @@ export async function buildPiperFromSource (version: string): Promise<string> {
const url = `${GITHUB_COM_SERVER_URL}/${owner}/${repository}/archive/${commitISH}.zip`
info(`URL: ${url}`)
await extractZip(
await downloadTool(url, `${path}/source-code.zip`), `${path}`)
await downloadTool(url, `${path}/source-code.zip`),
`${path}`
)
const wd = cwd()

const repositoryPath = join(path, fs.readdirSync(path).find((name: string) => {
Expand All @@ -128,9 +100,9 @@ export async function buildPiperFromSource (version: string): Promise<string> {
'go build -o ../piper',
[
'-ldflags',
`-X github.com/SAP/jenkins-library/cmd.GitCommit=${commitISH}
-X github.com/SAP/jenkins-library/pkg/log.LibraryRepository=${GITHUB_COM_SERVER_URL}/${owner}/${repository}
-X github.com/SAP/jenkins-library/pkg/telemetry.LibraryRepository=${GITHUB_COM_SERVER_URL}/${owner}/${repository}`
`-X github.com/SAP/jenkins-library/cmd.GitCommit=${commitISH}
-X github.com/SAP/jenkins-library/pkg/log.LibraryRepository=${GITHUB_COM_SERVER_URL}/${owner}/${repository}
-X github.com/SAP/jenkins-library/pkg/telemetry.LibraryRepository=${GITHUB_COM_SERVER_URL}/${owner}/${repository}`
]
)
process.env.CGO_ENABLED = cgoEnabled
Expand All @@ -141,9 +113,45 @@ export async function buildPiperFromSource (version: string): Promise<string> {
return piperPath
}

async function getPiperBinaryNameFromInputs (isEnterpriseStep: boolean, version?: string): Promise<string> {
// by default for inner source Piper
async function getPiperReleases (isSAPStep: boolean, version: string, api: string, token: string, owner: string, repository: string): Promise<OctokitResponse<any, number>> {
if (owner === '') {
throw new Error('owner is not provided')
}
if (repository === '') {
throw new Error('repository is not provided')
}
if (isSAPStep && token === '') {
throw new Error('token is not provided')
}
const tag = await getTag(true, version)
const options: OctokitOptions = {}
options.baseUrl = api
if (token !== '') {
options.auth = token
}
const octokit = new Octokit(options)
info(`Getting releases from /repos/${owner}/${repository}/releases/${tag}`)
const response = await octokit.request(
`GET /repos/${owner}/${repository}/releases/${tag}`
)
if (response.status !== 200) {
throw new Error(`can't get commit: ${response.status}`)
}
return response
}

async function getPiperDownloadURL (piper: string, version?: string): Promise<string> {
const response = await fetch(`${GITHUB_COM_SERVER_URL}/SAP/jenkins-library/releases/${await getTag(false, version)}`)
if (response.status !== 200) {
throw new Error(`can't get the tag: ${response.status}`)
}
return await Promise.resolve(response.url.replace(/tag/, 'download') + `/${piper}`)
}

async function getPiperBinaryNameFromInputs (stepName: string, version?: string): Promise<string> {
let piper = 'piper'
if (isEnterpriseStep) {
if (isEnterpriseStep(stepName)) {
piper = 'sap-piper'
}
if (version === 'master') {
Expand All @@ -152,25 +160,24 @@ async function getPiperBinaryNameFromInputs (isEnterpriseStep: boolean, version?
return piper
}

function getTag (version: string): string {
if (version !== '') {
async function getTag (forAPICall: boolean, version?: string): Promise<string> {
let tag
if (version !== undefined) {
version = version.toLowerCase()
}

let tag
if (version === undefined || version === '' || version === 'master' || version === 'latest') {
tag = 'latest'
} else {
} else if (forAPICall) {
tag = `tags/${version}`
} else {
tag = `tag/${version}`
}

return tag
}

// Expects a URL in API form:
// https://<host>/api/v3/repos/<org>/<repo>/contents/<folder>/<filename>
// TODO: remove this function after stage-config file is migrated to release assets
export async function downloadFileFromGitHub (url: string, token: string): Promise<OctokitResponse<any>> {
export async function downloadFileFromGitHub (url: string, token: string): Promise<OctokitResponse<any, number>> {
const host = url.substring(0, url.indexOf('/repos'))
const apiRequest = url.substring(url.indexOf('/repos'))

Expand All @@ -184,11 +191,34 @@ export async function downloadFileFromGitHub (url: string, token: string): Promi
const octokit = new Octokit(options)

const response = await octokit.request(
`GET ${apiRequest}`
`GET ${apiRequest}`
)
if (response.status !== 200) {
throw new Error(`can't get file: ${response.status}`)
}

return response
}

// function getKey (path: string): string {
// return path.split('/').slice(-2).reverse().join('_').replace(/\./g, '_')
// }

// async function savePiper (path: string): Promise<number> {
// const key = getKey(path)
// debug(`Caching with key: ${key}`)
// return await saveCache([path], key)
// }

// async function restorePiper (path: string): Promise<string> {
// const key = getKey(path)
// debug(`Restoring cache with key: ${key}`)
// path = path.split('/').slice(0, -1).join('/')
// debug(`Path: ${path}`)
// const path2 = await restoreCache([path], key)
// debug(`Path is: ${path2}`)
// if (typeof path2 === 'undefined') {
// return ''
// }
// return path
// }
Loading

0 comments on commit 28caec7

Please sign in to comment.