Skip to content

Commit

Permalink
Shared GitHub Actions for CNB Releases (#1)
Browse files Browse the repository at this point in the history
* Shared GitHub Actions for CNB Releases

Initial commit of shared workflows and actions for release automation tasks for Cloud-native Buildpacks.
  • Loading branch information
colincasey authored Jun 20, 2023
1 parent a6bfe81 commit c4222cd
Show file tree
Hide file tree
Showing 39 changed files with 14,764 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root = true

[*]
insert_final_newline = true
trim_trailing_whitespace = true
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @heroku/languages
10 changes: 10 additions & 0 deletions .github/actions/generate-buildpack-matrix/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Generate Buildpack Matrix
description: "Generates a list of buildpacks containing id and path keys for use in a matrix strategy `include` list"

outputs:
buildpacks:
description: The list of buildpack (id, path) keys formatted as a JSON array

runs:
using: node16
main: index.js
3 changes: 3 additions & 0 deletions .github/actions/generate-buildpack-matrix/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require('../../bootstrap').invokeWith(() => {
return ['generate-buildpack-matrix']
})
18 changes: 18 additions & 0 deletions .github/actions/generate-changelog/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Generate Changelog
description: "Generates a changelog from one or more buildpacks in a project"

inputs:
unreleased:
description: If the changelog should be generated from the unreleased section
required: false
version:
description: If the changelog should be generated from a version section
required: false

outputs:
changelog:
description: Markdown content listing the changes

runs:
using: node16
main: index.js
12 changes: 12 additions & 0 deletions .github/actions/generate-changelog/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require('../../bootstrap').invokeWith(({ getInput }) => {
const args = ['generate-changelog'];

if (getInput('unreleased')) {
args.push('--unreleased')
} else if (getInput('version')) {
args.push('--version')
args.push(getInput('version'))
}

return args
})
20 changes: 20 additions & 0 deletions .github/actions/prepare-release/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Prepare Buildpack Release
description: "Prepares a buildpack release by bumping the fixed version and updating changelogs"

inputs:
bump:
description: Which coordinate should be incremented? (major, minor, patch)
required: true
repository_url:
description: The URL of the repository (e.g.; https://github.com/octocat/Hello-World)
default: https://github.com/${{ github.repository }}

outputs:
from_version:
description: The previous version
to_version:
description: The next version

runs:
using: node16
main: index.js
11 changes: 11 additions & 0 deletions .github/actions/prepare-release/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require('../../bootstrap').invokeWith(({ getInput }) => {
return [
'prepare-release',

'--bump',
getInput('bump', { required: true }),

'--repository-url',
getInput('repository_url')
]
})
22 changes: 22 additions & 0 deletions .github/actions/update-builder/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Update Builder
description: "Prepares a buildpack release by bumping the fixed version and updating changelogs"

inputs:
buildpack_id:
description: The id of the buildpack
required: true
buildpack_version:
description: The version of the buildpack
required: true
buildpack_uri:
description: The URI of the published buildpack
required: true
builders:
description: A comma-separated list of builders to update
required: true
path:
description: Relative path under $GITHUB_WORKSPACE to execute in

runs:
using: node16
main: index.js
20 changes: 20 additions & 0 deletions .github/actions/update-builder/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require('../../bootstrap').invokeWith(({ getInput }) => {
return [
'update-builder',

'--path',
getInput('path', { required: true }),

'--buildpack-id',
getInput('buildpack_id', { required: true }),

'--buildpack-version',
getInput('buildpack_version', { required: true }),

'--buildpack-uri',
getInput('buildpack_uri', { required: true }),

'--builders',
getInput('builders', { required: true }),
]
})
85 changes: 85 additions & 0 deletions .github/bootstrap/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* IMPORTANT! If you change this file be sure to regenerate the compiled version with `npm run build`
*/

"use strict";

import { readFileSync } from "node:fs"
import { join } from "node:path"
import { parse as urlParse } from "node:url"

import { setFailed, getInput, getBooleanInput, getMultilineInput, startGroup, endGroup, info } from "@actions/core"
import { exec } from "@actions/exec"
import { find, cacheFile, downloadTool, extractTar } from "@actions/tool-cache"
import { parse as tomlParse } from 'toml'

type GetArguments = (inputs: {
getInput: typeof getInput,
getBooleanInput: typeof getBooleanInput,
getMultilineInput: typeof getMultilineInput
}) => string[]

export function invokeWith(getArgs: GetArguments) {
executeRustBinaryAction(getArgs).catch(e => {
if (e instanceof Error) {
setFailed(e.message)
}
})
}

async function executeRustBinaryAction(getArgs: GetArguments) {
startGroup('Bootstrapping');

const { platform, env } = process
const tempDirectory = env.RUNNER_TEMP

if (platform !== 'win32' && platform !== 'darwin' && platform !== 'linux') {
throw new Error(`Unsupported platform: ${platform}`)
}

const toml = tomlParse(readFileSync(join(__dirname, "../../Cargo.toml"), 'utf-8'))

const { name } = toml.bin[0]
info(`name: ${name}`)

const { repository, version } = toml.package
info(`version: ${version}\nrepository: ${repository}`)

const binaryName = platform === 'win32' ? `${name}.exe` : name;
info(`binaryName: ${binaryName}`)

const githubOrgAndName = urlParse(repository).pathname
.replace(/^\//, '')
.replace(/\.git$/, '')

// now we should be able to build up our download url which looks something like this:
// https://github.com/heroku/languages-github-actions/releases/download/v0.0.0/actions-v0.0.0-darwin-x64.tar.gz
const releaseUrl = `https://github.com/${githubOrgAndName}/releases/download/v${version}/${name}-v${version}-${platform}-x64.tar.gz`;
info(`releaseUrl: ${releaseUrl}`)

let cachedPath = find(githubOrgAndName, version)
info(`is cached: ${cachedPath ? true : false}`)
if (!cachedPath) {
const downloadPath = await downloadTool(releaseUrl)
info(`downloadPath: ${downloadPath}`)

const extractPath = await extractTar(downloadPath, tempDirectory)
info(`extractPath: ${extractPath}`)

const extractedFile = join(extractPath, binaryName)
info(`extractedFile: ${extractedFile}`)

cachedPath = await cacheFile(extractedFile, binaryName, githubOrgAndName, version)
}
info(`using cache path: ${cachedPath}`)

const rustBinary = join(cachedPath, name);
info(`using binary: ${rustBinary}`)

const args = getArgs({ getInput, getBooleanInput, getMultilineInput });
info(`using args: ${args.join(" ")}`)

endGroup()

await exec(rustBinary, args);
}
Loading

0 comments on commit c4222cd

Please sign in to comment.