Skip to content

Commit

Permalink
Refactor git-push-service action
Browse files Browse the repository at this point in the history
  • Loading branch information
int128 committed Jan 7, 2025
1 parent 05ab919 commit 76d29e2
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 141 deletions.
82 changes: 0 additions & 82 deletions git-push-service/src/application.ts

This file was deleted.

81 changes: 52 additions & 29 deletions git-push-service/src/arrange.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { promises as fs } from 'fs'
import * as core from '@actions/core'
import * as fs from 'fs/promises'
import * as io from '@actions/io'
import * as path from 'path'
import { Application, generateApplicationManifest } from './application.js'
import * as yaml from 'js-yaml'

type Inputs = {
workspace: string
Expand All @@ -13,48 +13,71 @@ type Inputs = {
branch: string
applicationAnnotations: string[]
destinationRepository: string
currentRef: string
currentSha: string
}

export const arrangeManifests = async (inputs: Inputs): Promise<void> => {
return await arrangeServiceManifests(inputs)
export const writeManifests = async (inputs: Inputs): Promise<void> => {
await writeServiceManifest(inputs.manifests, `${inputs.workspace}/services/${inputs.service}/generated.yaml`)
await writeApplicationManifest(inputs)
}

const arrangeServiceManifests = async (inputs: Inputs): Promise<void> => {
core.info(`arrange the manifests of the service`)
await concatServiceManifests(inputs.manifests, `${inputs.workspace}/services/${inputs.service}/generated.yaml`)
const writeServiceManifest = async (sourcePaths: string[], destinationPath: string) => {
const sourceContents = await Promise.all(
sourcePaths.map(async (manifestPath) => await fs.readFile(manifestPath, 'utf-8')),
)
const concatManifest = sourceContents.join('\n---\n')
core.info(`Writing the service manifest to ${destinationPath}`)
await io.mkdirP(path.dirname(destinationPath))
await fs.writeFile(destinationPath, concatManifest)
}

await putApplicationManifest(
{
const writeApplicationManifest = async (inputs: Inputs) => {
const application = {
apiVersion: 'argoproj.io/v1alpha1',
kind: 'Application',
metadata: {
name: `${inputs.namespace}--${inputs.service}`,
namespace: 'argocd',
finalizers: ['resources-finalizer.argocd.argoproj.io'],
annotations: {
...parseApplicationAnnotations(inputs.applicationAnnotations),
'github.ref': inputs.currentRef,
'github.sha': inputs.currentSha,
'github.action': 'git-push-service',
},
},
spec: {
project: inputs.project,
source: {
repository: inputs.destinationRepository,
branch: inputs.branch,
repoURL: `https://github.com/${inputs.destinationRepository}.git`,
targetRevision: inputs.branch,
path: `services/${inputs.service}`,
},
destination: {
server: `https://kubernetes.default.svc`,
namespace: inputs.namespace,
},
annotations: inputs.applicationAnnotations,
syncPolicy: {
automated: {
prune: true,
},
},
},
inputs.workspace,
)
}
}

const concatServiceManifests = async (manifestPaths: string[], destinationPath: string) => {
const manifestContents = await Promise.all(
manifestPaths.map(async (manifestPath) => (await fs.readFile(manifestPath)).toString()),
)
const concatManifest = manifestContents.join('\n---\n')
core.info(`writing to ${destinationPath}`)
await io.mkdirP(path.dirname(destinationPath))
await fs.writeFile(destinationPath, concatManifest)
await io.mkdirP(`${inputs.workspace}/applications`)
const destination = `${inputs.workspace}/applications/${application.metadata.name}.yaml`
core.info(`Writing the application manifest to ${destination}`)
await fs.writeFile(destination, yaml.dump(application))
}

const putApplicationManifest = async (application: Application, workspace: string) => {
await io.mkdirP(`${workspace}/applications`)
const destination = `${workspace}/applications/${application.name}.yaml`
core.info(`writing to ${destination}`)
const content = generateApplicationManifest(application)
await fs.writeFile(destination, content)
const parseApplicationAnnotations = (applicationAnnotations: string[]): Record<string, string> => {
const r: Record<string, string> = {}
for (const s of applicationAnnotations) {
const k = s.substring(0, s.indexOf('='))
const v = s.substring(s.indexOf('=') + 1)
r[k] = v
}
return r
}
31 changes: 13 additions & 18 deletions git-push-service/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import * as git from './git.js'
import * as glob from '@actions/glob'
import { arrangeManifests } from './arrange.js'
import { writeManifests } from './arrange.js'
import { retry } from './retry.js'
import { updateBranchByPullRequest } from './pull.js'

Expand Down Expand Up @@ -54,7 +54,7 @@ export const run = async (inputs: Inputs): Promise<Outputs> => {

const push = async (manifests: string[], inputs: Inputs): Promise<Outputs | Error> => {
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'git-push-service-action-'))
core.info(`created workspace at ${workspace}`)
core.info(`Created a workspace at ${workspace}`)

const [owner, repo] = inputs.destinationRepository.split('/')
const project = github.context.repo.repo
Expand All @@ -63,42 +63,37 @@ const push = async (manifests: string[], inputs: Inputs): Promise<Outputs | Erro
branch = inputs.destinationBranch
}

core.startGroup(`checkout branch ${branch} if exist`)
core.startGroup(`Checking out the branch ${branch} if exist`)
await git.init(workspace, owner, repo, inputs.token)
const branchNotExist = (await git.checkoutIfExist(workspace, branch)) > 0
core.endGroup()

const applicationAnnotations = [
...inputs.applicationAnnotations,
`github.ref=${github.context.ref}`,
`github.sha=${github.context.sha}`,
`github.action=git-push-service`,
]

core.startGroup(`arrange manifests into workspace ${workspace}`)
await arrangeManifests({
core.startGroup(`Writing the manifests into workspace ${workspace}`)
await writeManifests({
workspace,
manifests,
service: inputs.service,
namespace: inputs.namespace,
project,
branch,
applicationAnnotations,
applicationAnnotations: inputs.applicationAnnotations,
destinationRepository: inputs.destinationRepository,
currentRef: github.context.ref,
currentSha: github.context.sha,
})
core.endGroup()

const status = await git.status(workspace)
if (status === '') {
core.info('nothing to commit')
core.info('Nothing to commit')
return {}
}
const message = `Deploy ${project}/${inputs.namespace}/${inputs.service}\n\n${commitMessageFooter}`
core.summary.addHeading(`Deploy ${project}/${inputs.namespace}/${inputs.service}`)
await core.group(`create a commit`, () => git.commit(workspace, message))
await core.group(`Creating a commit`, () => git.commit(workspace, message))

if (!inputs.updateViaPullRequest) {
const code = await core.group(`push branch ${branch}`, () => git.pushByFastForward(workspace, branch))
const code = await core.group(`Pushing the branch ${branch}`, () => git.pushByFastForward(workspace, branch))
if (code > 0) {
return new Error(`failed to push branch ${branch} by fast-forward`)
}
Expand All @@ -108,7 +103,7 @@ const push = async (manifests: string[], inputs: Inputs): Promise<Outputs | Erro
}

if (branchNotExist) {
const code = await core.group(`push a new branch ${branch}`, () => git.pushByFastForward(workspace, branch))
const code = await core.group(`Pushing a new branch ${branch}`, () => git.pushByFastForward(workspace, branch))
if (code > 0) {
return new Error(`failed to push a new branch ${branch} by fast-forward`)
}
Expand All @@ -117,7 +112,7 @@ const push = async (manifests: string[], inputs: Inputs): Promise<Outputs | Erro
return {}
}

core.info(`updating branch ${branch} by a pull request`)
core.info(`Updating branch ${branch} by a pull request`)
return await updateBranchByPullRequest({
owner,
repo,
Expand Down
33 changes: 21 additions & 12 deletions git-push-service/tests/arrange.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import * as os from 'os'
import { promises as fs } from 'fs'
import * as fs from 'fs/promises'
import * as path from 'path'
import { arrangeManifests } from '../src/arrange.js'
import { writeManifests } from '../src/arrange.js'

const readContent = async (f: string) => (await fs.readFile(f)).toString()
const readContent = async (f: string) => await fs.readFile(f, 'utf-8')

test('arrange a service manifest', async () => {
it('writes the service and application manifests', async () => {
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'git-push-action-'))

await arrangeManifests({
await writeManifests({
workspace,
manifests: [path.join(__dirname, `fixtures/a/generated.yaml`)],
branch: `ns/project/overlay/namespace`,
namespace: 'namespace',
service: 'a',
project: 'project',
applicationAnnotations: ['github.ref=refs/heads/main'],
applicationAnnotations: ['example=foo'],
destinationRepository: 'octocat/manifests',
currentRef: 'refs/heads/main',
currentSha: '1234567890abcdef',
})

expect(await readContent(path.join(workspace, `applications/namespace--a.yaml`))).toBe(applicationA)
Expand All @@ -25,18 +27,20 @@ test('arrange a service manifest', async () => {
)
})

it('should concatenate service manifests if multiple are given', async () => {
it('concatenates the service manifests if multiple are given', async () => {
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'git-push-action-'))

await arrangeManifests({
await writeManifests({
workspace,
manifests: [path.join(__dirname, `fixtures/a/generated.yaml`), path.join(__dirname, `fixtures/b/generated.yaml`)],
branch: `ns/project/overlay/namespace`,
namespace: 'namespace',
service: 'service',
project: 'project',
applicationAnnotations: ['github.ref=refs/heads/main'],
applicationAnnotations: ['example=foo'],
destinationRepository: 'octocat/manifests',
currentRef: 'refs/heads/main',
currentSha: '1234567890abcdef',
})

expect(await readContent(path.join(workspace, `services/service/generated.yaml`))).toBe(`\
Expand All @@ -45,7 +49,7 @@ ${await readContent(path.join(__dirname, `fixtures/a/generated.yaml`))}
${await readContent(path.join(__dirname, `fixtures/b/generated.yaml`))}`)
})

test('overwrite even if a file exists', async () => {
it('overwrites if a file exists', async () => {
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'git-push-action-'))

// put dummy files
Expand All @@ -55,15 +59,17 @@ test('overwrite even if a file exists', async () => {
await fs.mkdir(path.join(workspace, `services/a`))
await fs.writeFile(path.join(workspace, `services/a/generated.yaml`), 'fixture-generated-manifest')

await arrangeManifests({
await writeManifests({
workspace,
manifests: [path.join(__dirname, `fixtures/a/generated.yaml`)],
branch: `ns/project/overlay/namespace`,
namespace: 'namespace',
service: 'a',
project: 'project',
applicationAnnotations: ['github.ref=refs/heads/main'],
applicationAnnotations: ['example=foo'],
destinationRepository: 'octocat/manifests',
currentRef: 'refs/heads/main',
currentSha: '1234567890abcdef',
})

expect(await readContent(path.join(workspace, `applications/namespace--a.yaml`))).toBe(applicationA)
Expand All @@ -81,7 +87,10 @@ metadata:
finalizers:
- resources-finalizer.argocd.argoproj.io
annotations:
example: foo
github.ref: refs/heads/main
github.sha: 1234567890abcdef
github.action: git-push-service
spec:
project: project
source:
Expand Down

0 comments on commit 76d29e2

Please sign in to comment.