fix low hanging fruit linter errors
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { publishOCIArtifact } from '../src/ghcr-client'
|
import { publishOCIArtifact } from '../src/ghcr-client'
|
||||||
import axios, { AxiosRequestConfig } from 'axios'
|
import axios from 'axios'
|
||||||
import * as fsHelper from '../src/fs-helper'
|
import * as fsHelper from '../src/fs-helper'
|
||||||
import * as ociContainer from '../src/oci-container'
|
import * as ociContainer from '../src/oci-container'
|
||||||
|
|
||||||
@@ -88,14 +88,12 @@ describe('publishOCIArtifact', () => {
|
|||||||
|
|
||||||
it('publishes layer blobs & then a manifest to the provided registry', async () => {
|
it('publishes layer blobs & then a manifest to the provided registry', async () => {
|
||||||
// Simulate none of the blobs existing currently
|
// Simulate none of the blobs existing currently
|
||||||
axiosHeadMock.mockImplementation(
|
axiosHeadMock.mockImplementation(async (url, config) => {
|
||||||
async (url: string, config: AxiosRequestConfig) => {
|
|
||||||
validateRequestConfig(404, url, config)
|
validateRequestConfig(404, url, config)
|
||||||
return {
|
return {
|
||||||
status: 404
|
status: 404
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
// Simulate successful initiation of uploads for all blobs & return location
|
// Simulate successful initiation of uploads for all blobs & return location
|
||||||
axiosPostMock.mockImplementation(async (url, data, config) => {
|
axiosPostMock.mockImplementation(async (url, data, config) => {
|
||||||
@@ -109,7 +107,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simulate successful reading of all the files
|
// Simulate successful reading of all the files
|
||||||
fsReadFileSyncMock.mockImplementation(async _ => {
|
fsReadFileSyncMock.mockImplementation(() => {
|
||||||
return Buffer.from('test')
|
return Buffer.from('test')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -160,7 +158,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simulate successful reading of all the files
|
// Simulate successful reading of all the files
|
||||||
fsReadFileSyncMock.mockImplementation(async _ => {
|
fsReadFileSyncMock.mockImplementation(() => {
|
||||||
return Buffer.from('test')
|
return Buffer.from('test')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -198,7 +196,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -229,7 +227,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -261,7 +259,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -296,7 +294,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simulate successful reading of all the files
|
// Simulate successful reading of all the files
|
||||||
fsReadFileSyncMock.mockImplementation(async path => {
|
fsReadFileSyncMock.mockImplementation(() => {
|
||||||
return Buffer.from('test')
|
return Buffer.from('test')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -308,7 +306,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -343,7 +341,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simulate successful reading of all the files
|
// Simulate successful reading of all the files
|
||||||
fsReadFileSyncMock.mockImplementation(async path => {
|
fsReadFileSyncMock.mockImplementation(() => {
|
||||||
return Buffer.from('test')
|
return Buffer.from('test')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -362,7 +360,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -397,7 +395,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simulate successful reading of all the files
|
// Simulate successful reading of all the files
|
||||||
fsReadFileSyncMock.mockImplementation(path => {
|
fsReadFileSyncMock.mockImplementation(() => {
|
||||||
throw new Error('failed to read a file: test')
|
throw new Error('failed to read a file: test')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -409,7 +407,7 @@ describe('publishOCIArtifact', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -424,10 +422,10 @@ describe('publishOCIArtifact', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error if one of the layers has the wrong media type', async () => {
|
it('throws an error if one of the layers has the wrong media type', async () => {
|
||||||
let modifiedTestManifest = testManifest
|
const modifiedTestManifest = testManifest
|
||||||
modifiedTestManifest.layers[0].mediaType = 'application/json'
|
modifiedTestManifest.layers[0].mediaType = 'application/json'
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
publishOCIArtifact(
|
publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registry,
|
registry,
|
||||||
@@ -444,11 +442,8 @@ describe('publishOCIArtifact', () => {
|
|||||||
|
|
||||||
// We expect all axios calls to have auth headers set and to not intercept any status codes so we can handle them.
|
// We expect all axios calls to have auth headers set and to not intercept any status codes so we can handle them.
|
||||||
// This function verifies that given an axios request config.
|
// This function verifies that given an axios request config.
|
||||||
function validateRequestConfig(
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
status: number,
|
function validateRequestConfig(status: number, url: string, config: any): void {
|
||||||
url: string,
|
|
||||||
config: AxiosRequestConfig
|
|
||||||
) {
|
|
||||||
// Basic URL checks
|
// Basic URL checks
|
||||||
expect(url).toBeDefined()
|
expect(url).toBeDefined()
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,9 @@ import * as main from '../src/main'
|
|||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
|
|
||||||
import * as fsHelper from '../src/fs-helper'
|
import * as fsHelper from '../src/fs-helper'
|
||||||
import * as ociContainer from '../src/oci-container'
|
|
||||||
import * as ghcr from '../src/ghcr-client'
|
import * as ghcr from '../src/ghcr-client'
|
||||||
|
|
||||||
// Mock the action's main function
|
|
||||||
const runMock = jest.spyOn(main, 'run')
|
|
||||||
|
|
||||||
// Mock the GitHub Actions core library
|
// Mock the GitHub Actions core library
|
||||||
let debugMock: jest.SpyInstance
|
|
||||||
let errorMock: jest.SpyInstance
|
|
||||||
let getInputMock: jest.SpyInstance
|
let getInputMock: jest.SpyInstance
|
||||||
let setFailedMock: jest.SpyInstance
|
let setFailedMock: jest.SpyInstance
|
||||||
let setOutputMock: jest.SpyInstance
|
let setOutputMock: jest.SpyInstance
|
||||||
@@ -38,8 +32,6 @@ describe('action', () => {
|
|||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
||||||
// Core mocks
|
// Core mocks
|
||||||
debugMock = jest.spyOn(core, 'debug').mockImplementation()
|
|
||||||
errorMock = jest.spyOn(core, 'error').mockImplementation()
|
|
||||||
getInputMock = jest.spyOn(core, 'getInput').mockImplementation()
|
getInputMock = jest.spyOn(core, 'getInput').mockImplementation()
|
||||||
setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation()
|
setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation()
|
||||||
setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
|
setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ import { FileMetadata } from '../src/fs-helper'
|
|||||||
|
|
||||||
describe('createActionPackageManigest', () => {
|
describe('createActionPackageManigest', () => {
|
||||||
it('creates a manifest containing the provided information', () => {
|
it('creates a manifest containing the provided information', () => {
|
||||||
let date = new Date()
|
const date = new Date()
|
||||||
let repo = 'test-repo'
|
const repo = 'test-repo'
|
||||||
let version = '1.0.0'
|
const version = '1.0.0'
|
||||||
let tarFile: FileMetadata = {
|
const tarFile: FileMetadata = {
|
||||||
path: '/test/test/test',
|
path: '/test/test/test',
|
||||||
sha256: '1234567890',
|
sha256: '1234567890',
|
||||||
size: 100
|
size: 100
|
||||||
}
|
}
|
||||||
let zipFile: FileMetadata = {
|
const zipFile: FileMetadata = {
|
||||||
path: '/test/test/test',
|
path: '/test/test/test',
|
||||||
sha256: '1234567890',
|
sha256: '1234567890',
|
||||||
size: 100
|
size: 100
|
||||||
}
|
}
|
||||||
|
|
||||||
let expectedJSON: String = `{
|
const expectedJSON = `{
|
||||||
"schemaVersion": 2,
|
"schemaVersion": 2,
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"artifactType": "application/vnd.oci.image.manifest.v1+json",
|
"artifactType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
@@ -63,7 +63,7 @@ describe('createActionPackageManigest', () => {
|
|||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
let manifest = createActionPackageManifest(
|
const manifest = createActionPackageManifest(
|
||||||
{
|
{
|
||||||
path: 'test.tar.gz',
|
path: 'test.tar.gz',
|
||||||
size: 100,
|
size: 100,
|
||||||
@@ -79,7 +79,7 @@ describe('createActionPackageManigest', () => {
|
|||||||
date
|
date
|
||||||
)
|
)
|
||||||
|
|
||||||
let manifestJSON = JSON.stringify(manifest)
|
const manifestJSON = JSON.stringify(manifest)
|
||||||
expect(manifestJSON).toEqual(expectedJSON.replace(/\s/g, ''))
|
expect(manifestJSON).toEqual(expectedJSON.replace(/\s/g, ''))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,6 @@
|
|||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/exec": "^1.1.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"@actions/github": "^6.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
"@types/axios": "^0.14.0",
|
|
||||||
"archiver": "^6.0.1",
|
"archiver": "^6.0.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"axios-debug-log": "^1.0.0",
|
"axios-debug-log": "^1.0.0",
|
||||||
@@ -77,6 +76,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/archiver": "^6.0.1",
|
"@types/archiver": "^6.0.1",
|
||||||
|
"@types/axios": "^0.14.0",
|
||||||
"@types/jest": "^29.5.8",
|
"@types/jest": "^29.5.8",
|
||||||
"@types/node": "^20.9.1",
|
"@types/node": "^20.9.1",
|
||||||
"@types/tar": "^6.1.9",
|
"@types/tar": "^6.1.9",
|
||||||
|
|||||||
+13
-16
@@ -1,14 +1,11 @@
|
|||||||
import * as core from '@actions/core'
|
|
||||||
import * as exec from '@actions/exec'
|
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as tar from 'tar'
|
import * as tar from 'tar'
|
||||||
import * as archiver from 'archiver'
|
import * as archiver from 'archiver'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as zlib from 'zlib'
|
|
||||||
|
|
||||||
export function createTempDir() {
|
export function createTempDir(): string {
|
||||||
const randomDirName = crypto.randomBytes(4).toString('hex')
|
const randomDirName = crypto.randomBytes(4).toString('hex')
|
||||||
const tempDir = path.join(os.tmpdir(), randomDirName)
|
const tempDir = path.join(os.tmpdir(), randomDirName)
|
||||||
|
|
||||||
@@ -19,7 +16,7 @@ export function createTempDir() {
|
|||||||
return tempDir
|
return tempDir
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeDir(dir: string) {
|
export function removeDir(dir: string): void {
|
||||||
fs.rmSync(dir, { recursive: true })
|
fs.rmSync(dir, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +57,7 @@ export async function createArchives(
|
|||||||
archive.finalize()
|
archive.finalize()
|
||||||
}),
|
}),
|
||||||
new Promise<FileMetadata>((resolve, reject) => {
|
new Promise<FileMetadata>((resolve, reject) => {
|
||||||
const tarStream = tar
|
tar
|
||||||
.c(
|
.c(
|
||||||
{
|
{
|
||||||
file: tarPath,
|
file: tarPath,
|
||||||
@@ -77,20 +74,20 @@ export async function createArchives(
|
|||||||
]).then(([zipFile, tarFile]) => ({ zipFile, tarFile }))
|
]).then(([zipFile, tarFile]) => ({ zipFile, tarFile }))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDirectory(path: string): boolean {
|
export function isDirectory(dirPath: string): boolean {
|
||||||
return fs.existsSync(path) && fs.lstatSync(path).isDirectory()
|
return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readFileContents(path: string): Buffer {
|
export function readFileContents(filePath: string): Buffer {
|
||||||
return fs.readFileSync(path)
|
return fs.readFileSync(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a file path to a filemetadata object by querying the fs for relevant metadata.
|
// Converts a file path to a filemetadata object by querying the fs for relevant metadata.
|
||||||
async function fileMetadata(path: string): Promise<FileMetadata> {
|
async function fileMetadata(filePath: string): Promise<FileMetadata> {
|
||||||
const stats = fs.statSync(path)
|
const stats = fs.statSync(filePath)
|
||||||
const size = stats.size
|
const size = stats.size
|
||||||
const hash = crypto.createHash('sha256')
|
const hash = crypto.createHash('sha256')
|
||||||
const fileStream = fs.createReadStream(path)
|
const fileStream = fs.createReadStream(filePath)
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fileStream.on('data', data => {
|
fileStream.on('data', data => {
|
||||||
hash.update(data)
|
hash.update(data)
|
||||||
@@ -98,9 +95,9 @@ async function fileMetadata(path: string): Promise<FileMetadata> {
|
|||||||
fileStream.on('end', () => {
|
fileStream.on('end', () => {
|
||||||
const sha256 = hash.digest('hex')
|
const sha256 = hash.digest('hex')
|
||||||
resolve({
|
resolve({
|
||||||
path: path,
|
path: filePath,
|
||||||
size: size,
|
size,
|
||||||
sha256: 'sha256:' + sha256
|
sha256: `sha256:${sha256}`
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
fileStream.on('error', err => {
|
fileStream.on('error', err => {
|
||||||
|
|||||||
+16
-19
@@ -2,9 +2,6 @@ import * as core from '@actions/core'
|
|||||||
import { FileMetadata } from './fs-helper'
|
import { FileMetadata } from './fs-helper'
|
||||||
import * as ociContainer from './oci-container'
|
import * as ociContainer from './oci-container'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { fieldEnds } from 'tar'
|
|
||||||
import * as fs from 'fs'
|
|
||||||
import { promiseHooks } from 'v8'
|
|
||||||
import * as fsHelper from './fs-helper'
|
import * as fsHelper from './fs-helper'
|
||||||
import axiosDebugLog from 'axios-debug-log'
|
import axiosDebugLog from 'axios-debug-log'
|
||||||
|
|
||||||
@@ -18,7 +15,7 @@ export async function publishOCIArtifact(
|
|||||||
zipFile: FileMetadata,
|
zipFile: FileMetadata,
|
||||||
tarFile: FileMetadata,
|
tarFile: FileMetadata,
|
||||||
manifest: ociContainer.Manifest,
|
manifest: ociContainer.Manifest,
|
||||||
debugRequests: boolean = false
|
debugRequests = false
|
||||||
): Promise<URL> {
|
): Promise<URL> {
|
||||||
if (debugRequests) {
|
if (debugRequests) {
|
||||||
configureRequestDebugLogging()
|
configureRequestDebugLogging()
|
||||||
@@ -43,7 +40,7 @@ export async function publishOCIArtifact(
|
|||||||
`Creating GHCR package for release with semver:${semver} with path:"${zipFile.path}" and "${tarFile.path}".`
|
`Creating GHCR package for release with semver:${semver} with path:"${zipFile.path}" and "${tarFile.path}".`
|
||||||
)
|
)
|
||||||
|
|
||||||
let layerUploads: Promise<void>[] = manifest.layers.map(layer => {
|
const layerUploads: Promise<void>[] = manifest.layers.map(async layer => {
|
||||||
switch (layer.mediaType) {
|
switch (layer.mediaType) {
|
||||||
case 'application/vnd.github.actions.package.layer.v1.tar+gzip':
|
case 'application/vnd.github.actions.package.layer.v1.tar+gzip':
|
||||||
return uploadLayer(
|
return uploadLayer(
|
||||||
@@ -98,7 +95,7 @@ async function uploadLayer(
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${b64Token}`
|
Authorization: `Bearer ${b64Token}`
|
||||||
},
|
},
|
||||||
validateStatus: function (status: number) {
|
validateStatus: () => {
|
||||||
return true // Allow non 2xx responses
|
return true // Allow non 2xx responses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,12 +121,12 @@ async function uploadLayer(
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${b64Token}`
|
Authorization: `Bearer ${b64Token}`
|
||||||
},
|
},
|
||||||
validateStatus: function (status: number) {
|
validateStatus: () => {
|
||||||
return true // Allow non 2xx responses
|
return true // Allow non 2xx responses
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (initiateUploadResponse.status != 202) {
|
if (initiateUploadResponse.status !== 202) {
|
||||||
core.error(
|
core.error(
|
||||||
`Unexpected response from upload post ${uploadBlobEndpoint}: ${initiateUploadResponse.status}`
|
`Unexpected response from upload post ${uploadBlobEndpoint}: ${initiateUploadResponse.status}`
|
||||||
)
|
)
|
||||||
@@ -139,17 +136,17 @@ async function uploadLayer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const locationResponseHeader = initiateUploadResponse.headers['location']
|
const locationResponseHeader = initiateUploadResponse.headers['location']
|
||||||
if (locationResponseHeader == undefined) {
|
if (locationResponseHeader === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`No location header in response from upload post ${uploadBlobEndpoint} for layer ${layer.digest}`
|
`No location header in response from upload post ${uploadBlobEndpoint} for layer ${layer.digest}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let pathname = (locationResponseHeader as string) + '?digest=' + layer.digest
|
const pathname = `${locationResponseHeader}?digest=${layer.digest}`
|
||||||
const uploadBlobUrl = new URL(pathname, registryURL).toString()
|
const uploadBlobUrl = new URL(pathname, registryURL).toString()
|
||||||
|
|
||||||
// TODO: must we handle the empty config layer? Maybe we can just skip calling this at all
|
// TODO: must we handle the empty config layer? Maybe we can just skip calling this at all
|
||||||
var data: Buffer
|
let data: Buffer
|
||||||
if (file.size === 0) {
|
if (file.size === 0) {
|
||||||
data = Buffer.alloc(0)
|
data = Buffer.alloc(0)
|
||||||
} else {
|
} else {
|
||||||
@@ -163,12 +160,12 @@ async function uploadLayer(
|
|||||||
'Accept-Encoding': 'gzip', // TODO: What about for the config layer?
|
'Accept-Encoding': 'gzip', // TODO: What about for the config layer?
|
||||||
'Content-Length': layer.size.toString()
|
'Content-Length': layer.size.toString()
|
||||||
},
|
},
|
||||||
validateStatus: function (status: number) {
|
validateStatus: () => {
|
||||||
return true // Allow non 2xx responses
|
return true // Allow non 2xx responses
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (putResponse.status != 201) {
|
if (putResponse.status !== 201) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unexpected response from PUT upload ${putResponse.status} for layer ${layer.digest}`
|
`Unexpected response from PUT upload ${putResponse.status} for layer ${layer.digest}`
|
||||||
)
|
)
|
||||||
@@ -187,27 +184,27 @@ async function uploadManifest(
|
|||||||
Authorization: `Bearer ${b64Token}`,
|
Authorization: `Bearer ${b64Token}`,
|
||||||
'Content-Type': 'application/vnd.oci.image.manifest.v1+json'
|
'Content-Type': 'application/vnd.oci.image.manifest.v1+json'
|
||||||
},
|
},
|
||||||
validateStatus: function (status: number) {
|
validateStatus: () => {
|
||||||
return true // Allow non 2xx responses
|
return true // Allow non 2xx responses
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (putResponse.status != 201) {
|
if (putResponse.status !== 201) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unexpected response from PUT manifest ${putResponse.status}`
|
`Unexpected response from PUT manifest ${putResponse.status}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureRequestDebugLogging() {
|
function configureRequestDebugLogging(): void {
|
||||||
axiosDebugLog({
|
axiosDebugLog({
|
||||||
request: function (debug, config) {
|
request: (debug, config) => {
|
||||||
core.debug(`Request with ${config}`)
|
core.debug(`Request with ${config}`)
|
||||||
},
|
},
|
||||||
response: function (debug, response) {
|
response: (debug, response) => {
|
||||||
core.debug(`Response with ${response}`)
|
core.debug(`Response with ${response}`)
|
||||||
},
|
},
|
||||||
error: function (debug, error) {
|
error: (debug, error) => {
|
||||||
core.debug(`Error with ${error}`)
|
core.debug(`Error with ${error}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+3
-4
@@ -4,14 +4,13 @@ import * as fsHelper from './fs-helper'
|
|||||||
import * as ociContainer from './oci-container'
|
import * as ociContainer from './oci-container'
|
||||||
import * as ghcr from './ghcr-client'
|
import * as ghcr from './ghcr-client'
|
||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
import { url } from 'inspector'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
* @returns {Promise<void>} Resolves when the action is complete.
|
* @returns {Promise<void>} Resolves when the action is complete.
|
||||||
*/
|
*/
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
let tmpDir: string = ''
|
let tmpDir = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Parse and validate Actions execution context, including the repository name, release name and event type
|
// Parse and validate Actions execution context, including the repository name, release name and event type
|
||||||
@@ -29,7 +28,7 @@ export async function run(): Promise<void> {
|
|||||||
|
|
||||||
// Strip any leading 'v' from the tag in case the release format is e.g. 'v1.0.0' as recommended by GitHub docs
|
// Strip any leading 'v' from the tag in case the release format is e.g. 'v1.0.0' as recommended by GitHub docs
|
||||||
// https://docs.github.com/en/actions/creating-actions/releasing-and-maintaining-actions
|
// https://docs.github.com/en/actions/creating-actions/releasing-and-maintaining-actions
|
||||||
let targetVersion = semver.parse(releaseTag.replace(/^v/, ''))
|
const targetVersion = semver.parse(releaseTag.replace(/^v/, ''))
|
||||||
if (!targetVersion) {
|
if (!targetVersion) {
|
||||||
core.setFailed(
|
core.setFailed(
|
||||||
`${releaseTag} is not a valid semantic version, and so cannot be uploaded as an Immutable Action.`
|
`${releaseTag} is not a valid semantic version, and so cannot be uploaded as an Immutable Action.`
|
||||||
@@ -62,7 +61,7 @@ export async function run(): Promise<void> {
|
|||||||
new Date()
|
new Date()
|
||||||
)
|
)
|
||||||
|
|
||||||
let packageURL = await ghcr.publishOCIArtifact(
|
const packageURL = await ghcr.publishOCIArtifact(
|
||||||
token,
|
token,
|
||||||
registryURL,
|
registryURL,
|
||||||
repository,
|
repository,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Tracing } from 'trace_events'
|
|
||||||
import { FileMetadata } from './fs-helper'
|
import { FileMetadata } from './fs-helper'
|
||||||
|
|
||||||
export interface Manifest {
|
export interface Manifest {
|
||||||
@@ -7,14 +6,14 @@ export interface Manifest {
|
|||||||
artifactType: string
|
artifactType: string
|
||||||
config: Layer
|
config: Layer
|
||||||
layers: Layer[]
|
layers: Layer[]
|
||||||
annotations: {}
|
annotations: { [key: string]: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Layer {
|
export interface Layer {
|
||||||
mediaType: string
|
mediaType: string
|
||||||
size: number
|
size: number
|
||||||
digest: string
|
digest: string
|
||||||
annotations: {}
|
annotations: { [key: string]: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a name and archive metadata, creates a manifest in the format expected by GHCR for an Actions Package.
|
// Given a name and archive metadata, creates a manifest in the format expected by GHCR for an Actions Package.
|
||||||
|
|||||||
Reference in New Issue
Block a user