Skip to content

Commit

Permalink
Merge pull request #70 from github/feelepxyz/extract-container-service
Browse files Browse the repository at this point in the history
Extract container service and helpers from updater
  • Loading branch information
Philip Harrison authored and GitHub committed Jul 28, 2021
2 parents c2aca79 + 3ed9753 commit 043b612
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 71 deletions.
24 changes: 24 additions & 0 deletions __tests__/container-service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Docker from 'dockerode'

import {ContainerService} from '../src/container-service'
import {ImageService} from '../src/image-service'

describe('ContainerService', () => {
const docker = new Docker()
let container: any

beforeAll(async () => {
await ImageService.pull('alpine')
container = await docker.createContainer({
Image: 'alpine',
AttachStdout: true,
AttachStderr: true,
Cmd: ['/bin/sh', '-c', 'echo $VAR'],
Env: ['VAR=env-var']
})
})

test('runs containers', async () => {
await ContainerService.run(container)
})
})
20 changes: 20 additions & 0 deletions __tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {base64DecodeDependencyFile} from '../src/utils'

describe('base64DecodeDependencyFile', () => {
test('clones the dependency file', () => {
const dependencyFile = {
name: 'package.json',
content: 'dGVzdCBzdHJpbmc=',
directory: '/',
type: 'file',
support_file: false,
content_encoding: 'utf-8',
deleted: false,
operation: 'add'
}

const decoded = base64DecodeDependencyFile(dependencyFile)
expect(decoded.content).toEqual('test string')
expect(dependencyFile.content).toEqual('dGVzdCBzdHJpbmc=')
})
})
35 changes: 35 additions & 0 deletions src/container-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as core from '@actions/core'
import {Container} from 'dockerode'
import {pack} from 'tar-stream'
import {FileFetcherInput, FileUpdaterInput} from './file-types'

export const ContainerService = {
async storeInput(
name: string,
path: string,
container: Container,
input: FileFetcherInput | FileUpdaterInput
): Promise<void> {
const tar = pack()
tar.entry({name}, JSON.stringify(input))
tar.finalize()
await container.putArchive(tar, {path})
},

async run(container: Container): Promise<void> {
try {
const stream = await container.attach({
stream: true,
stdout: true,
stderr: true
})
container.modem.demuxStream(stream, process.stdout, process.stderr)

await container.start()
await container.wait()
} finally {
await container.remove()
core.info(`Cleaned up container ${container.id}`)
}
}
}
27 changes: 27 additions & 0 deletions src/file-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {Credential, JobDetails} from './api-client'

export type FetchedFiles = {
base_commit_sha: string
dependency_files: any[]
base64_dependency_files: any[]
}

export type FileFetcherInput = {
job: JobDetails
credentials: Credential[]
}

export type DependencyFile = {
name: string
content: any
directory: string
type: string
support_file: boolean
content_encoding: string
deleted: boolean
operation: string
}

export type FileUpdaterInput = FetchedFiles & {
job: JobDetails
}
92 changes: 21 additions & 71 deletions src/updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ import Docker, {Container} from 'dockerode'
import path from 'path'
import fs from 'fs'
import {Credential, JobDetails, APIClient} from './api-client'
import {pack} from 'tar-stream'
import {ContainerService} from './container-service'
import {base64DecodeDependencyFile} from './utils'
import {DependencyFile, FetchedFiles, FileUpdaterInput} from './file-types'

const JOB_INPUT_FILENAME = 'job.json'
const JOB_INPUT_PATH = `/home/dependabot/dependabot-updater`
const JOB_OUTPUT_FILENAME = 'output.json'
const JOB_OUTPUT_PATH = '/home/dependabot/dependabot-updater/output'
const REPO_CONTENTS_PATH = '/home/dependabot/dependabot-updater/repo'

const decode = (str: string): string =>
Buffer.from(str, 'base64').toString('binary')

export class Updater {
docker: Docker
constructor(
Expand Down Expand Up @@ -47,22 +46,21 @@ export class Updater {
}
}

private decodeBase64Content(file: DependencyFile): string {
const fileCopy = JSON.parse(JSON.stringify(file))
fileCopy.content = decode(fileCopy.content)
return fileCopy
}

private async runFileFetcher(
details: JobDetails,
credentials: Credential[]
): Promise<void | FetchedFiles> {
const container = await this.createContainer('fetch_files')
await this.storeContainerInput(container, {
job: details,
credentials
})
await this.runContainer(container)
await ContainerService.storeInput(
JOB_INPUT_FILENAME,
JOB_INPUT_PATH,
container,
{
job: details,
credentials
}
)
await ContainerService.run(container)

const outputPath = path.join(__dirname, '../output/output.json')
if (!fs.existsSync(outputPath)) {
Expand All @@ -76,7 +74,7 @@ export class Updater {
base_commit_sha: fileFetcherOutput.base_commit_sha,
base64_dependency_files: fileFetcherOutput.base64_dependency_files,
dependency_files: fileFetcherOutput.base64_dependency_files.map(
(file: DependencyFile) => this.decodeBase64Content(file)
(file: DependencyFile) => base64DecodeDependencyFile(file)
)
}

Expand All @@ -95,8 +93,13 @@ export class Updater {
dependency_files: files.dependency_files,
job: details
}
await this.storeContainerInput(container, containerInput)
await this.runContainer(container)
await ContainerService.storeInput(
JOB_INPUT_FILENAME,
JOB_INPUT_PATH,
container,
containerInput
)
await ContainerService.run(container)
}

private async createContainer(updaterCommand: string): Promise<Container> {
Expand Down Expand Up @@ -125,57 +128,4 @@ export class Updater {
core.info(`Created ${updaterCommand} container: ${container.id}`)
return container
}

private async storeContainerInput(
container: Container,
input: FileFetcherInput | FileUpdaterInput
): Promise<void> {
const tar = pack()
tar.entry({name: JOB_INPUT_FILENAME}, JSON.stringify(input))
tar.finalize()
await container.putArchive(tar, {path: JOB_INPUT_PATH})
}

private async runContainer(container: Container): Promise<void> {
try {
await container.start()
const stream = await container.attach({
stream: true,
stdout: true,
stderr: true
})
container.modem.demuxStream(stream, process.stdout, process.stderr)

await container.wait()
} finally {
await container.remove()
core.info(`Cleaned up container ${container.id}`)
}
}
}

type FileFetcherInput = {
job: JobDetails
credentials: Credential[]
}

type FetchedFiles = {
base_commit_sha: string
dependency_files: any[]
base64_dependency_files: any[]
}

type DependencyFile = {
name: string
content: any
directory: string
type: string
support_file: boolean
content_encoding: string
deleted: boolean
operation: string
}

type FileUpdaterInput = FetchedFiles & {
job: JobDetails
}
12 changes: 12 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {DependencyFile} from './file-types'

const base64Decode = (str: string): string =>
Buffer.from(str, 'base64').toString('binary')

export const base64DecodeDependencyFile = (
file: DependencyFile
): DependencyFile => {
const fileCopy = JSON.parse(JSON.stringify(file))
fileCopy.content = base64Decode(fileCopy.content)
return fileCopy
}

0 comments on commit 043b612

Please sign in to comment.