This commit is contained in:
Trym Lund Flogard 2021-06-05 14:11:25 +02:00
parent 7fe0b3a0b9
commit 565777588d
2 changed files with 14 additions and 50 deletions

View File

@ -65,8 +65,8 @@ export class NextcloudArtifact {
name: 'Nextcloud Artifacts', name: 'Nextcloud Artifacts',
status: 'in_progress', status: 'in_progress',
output: { output: {
title: 'Nextcloud Artifacts', title: `Nextcloud (${this.name})`,
summary: '' summary: 'Uploading...'
}, },
...github.context.repo ...github.context.repo
}) })
@ -81,13 +81,14 @@ export class NextcloudArtifact {
try { try {
const shareableUrl = await client.uploadFiles(files.filesToUpload) const shareableUrl = await client.uploadFiles(files.filesToUpload)
core.info(`Nextcloud shareable URL: ${shareableUrl}`)
const resp = await this.octokit.rest.checks.update({ const resp = await this.octokit.rest.checks.update({
check_run_id: createResp.data.id, check_run_id: createResp.data.id,
conclusion: 'success', conclusion: 'success',
status: 'completed', status: 'completed',
output: { output: {
title: 'Nextcloud Artifacts', title: `Nextcloud (${this.name})`,
summary: `${this.name}: ${shareableUrl}` summary: shareableUrl
}, },
...github.context.repo ...github.context.repo
}) })
@ -95,9 +96,8 @@ export class NextcloudArtifact {
core.info(`Check run URL: ${resp.data.url}`) core.info(`Check run URL: ${resp.data.url}`)
core.info(`Check run HTML: ${resp.data.html_url}`) core.info(`Check run HTML: ${resp.data.html_url}`)
} catch (error) { } catch (error) {
core.error(error)
await this.trySetFailed(createResp.data.id) await this.trySetFailed(createResp.data.id)
core.setFailed('Failed to update check') core.setFailed(error)
} }
} }
@ -108,7 +108,7 @@ export class NextcloudArtifact {
conclusion: 'failure', conclusion: 'failure',
status: 'completed', status: 'completed',
output: { output: {
title: 'Nextcloud Artifacts', title: `Nextcloud (${this.name})`,
summary: 'Check failed.' summary: 'Check failed.'
}, },
...github.context.repo ...github.context.repo

View File

@ -43,8 +43,7 @@ export class NextcloudClient {
core.info('Uploading to Nextcloud...') core.info('Uploading to Nextcloud...')
const filePath = await this.upload(zip) const filePath = await this.upload(zip)
core.info(`File path: ${filePath}`) core.info(`Remote file path: ${filePath}`)
core.info('Sharing file...')
return await this.shareFile(filePath) return await this.shareFile(filePath)
} }
@ -56,57 +55,25 @@ export class NextcloudClient {
if (!fsSync.lstatSync(this.rootDirectory).isDirectory()) { if (!fsSync.lstatSync(this.rootDirectory).isDirectory()) {
throw new Error(`this.rootDirectory ${this.rootDirectory} is not a valid directory`) throw new Error(`this.rootDirectory ${this.rootDirectory} is not a valid directory`)
} }
// Normalize and resolve, this allows for either absolute or relative paths to be used
let root = path.normalize(this.rootDirectory) let root = path.normalize(this.rootDirectory)
root = path.resolve(root) root = path.resolve(root)
/*
Example to demonstrate behavior
Input:
artifactName: my-artifact
rootDirectory: '/home/user/files/plz-upload'
artifactFiles: [
'/home/user/files/plz-upload/file1.txt',
'/home/user/files/plz-upload/file2.txt',
'/home/user/files/plz-upload/dir/file3.txt'
]
Output:
specifications: [
['/home/user/files/plz-upload/file1.txt', 'my-artifact/file1.txt'],
['/home/user/files/plz-upload/file1.txt', 'my-artifact/file2.txt'],
['/home/user/files/plz-upload/file1.txt', 'my-artifact/dir/file3.txt']
]
*/
for (let file of files) { for (let file of files) {
if (!fsSync.existsSync(file)) { if (!fsSync.existsSync(file)) {
throw new Error(`File ${file} does not exist`) throw new Error(`File ${file} does not exist`)
} }
if (!fsSync.lstatSync(file).isDirectory()) { if (!fsSync.lstatSync(file).isDirectory()) {
// Normalize and resolve, this allows for either absolute or relative paths to be used
file = path.normalize(file) file = path.normalize(file)
file = path.resolve(file) file = path.resolve(file)
if (!file.startsWith(root)) { if (!file.startsWith(root)) {
throw new Error(`The rootDirectory: ${root} is not a parent directory of the file: ${file}`) throw new Error(`The rootDirectory: ${root} is not a parent directory of the file: ${file}`)
} }
// Check for forbidden characters in file paths that will be rejected during upload
const uploadPath = file.replace(root, '') const uploadPath = file.replace(root, '')
/*
uploadFilePath denotes where the file will be uploaded in the file container on the server. During a run, if multiple artifacts are uploaded, they will all
be saved in the same container. The artifact name is used as the root directory in the container to separate and distinguish uploaded artifacts
path.join handles all the following cases and would return 'artifact-name/file-to-upload.txt
join('artifact-name/', 'file-to-upload.txt')
join('artifact-name/', '/file-to-upload.txt')
join('artifact-name', 'file-to-upload.txt')
join('artifact-name', '/file-to-upload.txt')
*/
specifications.push({ specifications.push({
absolutePath: file, absolutePath: file,
uploadPath: path.join(this.artifact, uploadPath) uploadPath: path.join(this.artifact, uploadPath)
}) })
} else { } else {
// Directories are rejected by the server during upload
core.debug(`Removing ${file} from rawSearchResults because it is a directory`) core.debug(`Removing ${file} from rawSearchResults because it is a directory`)
} }
} }
@ -133,7 +100,6 @@ export class NextcloudClient {
const archivePath = path.join(artifactPath, `${this.artifact}.zip`) const archivePath = path.join(artifactPath, `${this.artifact}.zip`)
await this.zip(path.join(artifactPath, this.artifact), archivePath) await this.zip(path.join(artifactPath, this.artifact), archivePath)
core.info(`archive stat: ${(await fs.stat(archivePath)).size}`)
return archivePath return archivePath
} }
@ -151,14 +117,12 @@ export class NextcloudClient {
private async upload(file: string): Promise<string> { private async upload(file: string): Promise<string> {
const remoteFileDir = `/artifacts/${this.guid}` const remoteFileDir = `/artifacts/${this.guid}`
core.info('Checking directory...')
if (!(await this.davClient.exists(remoteFileDir))) { if (!(await this.davClient.exists(remoteFileDir))) {
core.info('Creating directory...')
await this.davClient.createDirectory(remoteFileDir, { recursive: true }) await this.davClient.createDirectory(remoteFileDir, { recursive: true })
} }
const remoteFilePath = `${remoteFileDir}/${this.artifact}.zip` const remoteFilePath = `${remoteFileDir}/${this.artifact}.zip`
core.info(`Transferring file... (${file})`) core.debug(`Transferring file... (${file})`)
const fileStat = await fs.stat(file) const fileStat = await fs.stat(file)
const fileStream = fsSync.createReadStream(file) const fileStream = fsSync.createReadStream(file)
@ -174,11 +138,11 @@ export class NextcloudClient {
fileStream.pipe(remoteStream) fileStream.pipe(remoteStream)
// see: https://github.com/nodejs/node/issues/22088
const timer = setTimeout(() => {}, 20_000); const timer = setTimeout(() => {}, 20_000);
await fileStreamPromise await Promise.all([fileStreamPromise, remoteStreamPromise])
await remoteStreamPromise
// Wait for file to be processed // HACK: Nextcloud has not fully processed the file, despite returning 200.
// Waiting for 1s seems to do the trick.
await new Promise(resolve => setTimeout(resolve, 1_000)); await new Promise(resolve => setTimeout(resolve, 1_000));
clearTimeout(timer); clearTimeout(timer);