Skip to content

Commit c4222cd

Browse files
authored
Shared GitHub Actions for CNB Releases (#1)
* Shared GitHub Actions for CNB Releases Initial commit of shared workflows and actions for release automation tasks for Cloud-native Buildpacks.
1 parent a6bfe81 commit c4222cd

File tree

39 files changed

+14764
-0
lines changed

39 files changed

+14764
-0
lines changed

.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
root = true
2+
3+
[*]
4+
insert_final_newline = true
5+
trim_trailing_whitespace = true

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @heroku/languages
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Generate Buildpack Matrix
2+
description: "Generates a list of buildpacks containing id and path keys for use in a matrix strategy `include` list"
3+
4+
outputs:
5+
buildpacks:
6+
description: The list of buildpack (id, path) keys formatted as a JSON array
7+
8+
runs:
9+
using: node16
10+
main: index.js
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
require('../../bootstrap').invokeWith(() => {
2+
return ['generate-buildpack-matrix']
3+
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Generate Changelog
2+
description: "Generates a changelog from one or more buildpacks in a project"
3+
4+
inputs:
5+
unreleased:
6+
description: If the changelog should be generated from the unreleased section
7+
required: false
8+
version:
9+
description: If the changelog should be generated from a version section
10+
required: false
11+
12+
outputs:
13+
changelog:
14+
description: Markdown content listing the changes
15+
16+
runs:
17+
using: node16
18+
main: index.js
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require('../../bootstrap').invokeWith(({ getInput }) => {
2+
const args = ['generate-changelog'];
3+
4+
if (getInput('unreleased')) {
5+
args.push('--unreleased')
6+
} else if (getInput('version')) {
7+
args.push('--version')
8+
args.push(getInput('version'))
9+
}
10+
11+
return args
12+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Prepare Buildpack Release
2+
description: "Prepares a buildpack release by bumping the fixed version and updating changelogs"
3+
4+
inputs:
5+
bump:
6+
description: Which coordinate should be incremented? (major, minor, patch)
7+
required: true
8+
repository_url:
9+
description: The URL of the repository (e.g.; https://github.com/octocat/Hello-World)
10+
default: https://github.com/${{ github.repository }}
11+
12+
outputs:
13+
from_version:
14+
description: The previous version
15+
to_version:
16+
description: The next version
17+
18+
runs:
19+
using: node16
20+
main: index.js
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
require('../../bootstrap').invokeWith(({ getInput }) => {
2+
return [
3+
'prepare-release',
4+
5+
'--bump',
6+
getInput('bump', { required: true }),
7+
8+
'--repository-url',
9+
getInput('repository_url')
10+
]
11+
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Update Builder
2+
description: "Prepares a buildpack release by bumping the fixed version and updating changelogs"
3+
4+
inputs:
5+
buildpack_id:
6+
description: The id of the buildpack
7+
required: true
8+
buildpack_version:
9+
description: The version of the buildpack
10+
required: true
11+
buildpack_uri:
12+
description: The URI of the published buildpack
13+
required: true
14+
builders:
15+
description: A comma-separated list of builders to update
16+
required: true
17+
path:
18+
description: Relative path under $GITHUB_WORKSPACE to execute in
19+
20+
runs:
21+
using: node16
22+
main: index.js
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require('../../bootstrap').invokeWith(({ getInput }) => {
2+
return [
3+
'update-builder',
4+
5+
'--path',
6+
getInput('path', { required: true }),
7+
8+
'--buildpack-id',
9+
getInput('buildpack_id', { required: true }),
10+
11+
'--buildpack-version',
12+
getInput('buildpack_version', { required: true }),
13+
14+
'--buildpack-uri',
15+
getInput('buildpack_uri', { required: true }),
16+
17+
'--builders',
18+
getInput('builders', { required: true }),
19+
]
20+
})

.github/bootstrap/bootstrap.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* IMPORTANT! If you change this file be sure to regenerate the compiled version with `npm run build`
3+
*/
4+
5+
"use strict";
6+
7+
import { readFileSync } from "node:fs"
8+
import { join } from "node:path"
9+
import { parse as urlParse } from "node:url"
10+
11+
import { setFailed, getInput, getBooleanInput, getMultilineInput, startGroup, endGroup, info } from "@actions/core"
12+
import { exec } from "@actions/exec"
13+
import { find, cacheFile, downloadTool, extractTar } from "@actions/tool-cache"
14+
import { parse as tomlParse } from 'toml'
15+
16+
type GetArguments = (inputs: {
17+
getInput: typeof getInput,
18+
getBooleanInput: typeof getBooleanInput,
19+
getMultilineInput: typeof getMultilineInput
20+
}) => string[]
21+
22+
export function invokeWith(getArgs: GetArguments) {
23+
executeRustBinaryAction(getArgs).catch(e => {
24+
if (e instanceof Error) {
25+
setFailed(e.message)
26+
}
27+
})
28+
}
29+
30+
async function executeRustBinaryAction(getArgs: GetArguments) {
31+
startGroup('Bootstrapping');
32+
33+
const { platform, env } = process
34+
const tempDirectory = env.RUNNER_TEMP
35+
36+
if (platform !== 'win32' && platform !== 'darwin' && platform !== 'linux') {
37+
throw new Error(`Unsupported platform: ${platform}`)
38+
}
39+
40+
const toml = tomlParse(readFileSync(join(__dirname, "../../Cargo.toml"), 'utf-8'))
41+
42+
const { name } = toml.bin[0]
43+
info(`name: ${name}`)
44+
45+
const { repository, version } = toml.package
46+
info(`version: ${version}\nrepository: ${repository}`)
47+
48+
const binaryName = platform === 'win32' ? `${name}.exe` : name;
49+
info(`binaryName: ${binaryName}`)
50+
51+
const githubOrgAndName = urlParse(repository).pathname
52+
.replace(/^\//, '')
53+
.replace(/\.git$/, '')
54+
55+
// now we should be able to build up our download url which looks something like this:
56+
// https://github.com/heroku/languages-github-actions/releases/download/v0.0.0/actions-v0.0.0-darwin-x64.tar.gz
57+
const releaseUrl = `https://github.com/${githubOrgAndName}/releases/download/v${version}/${name}-v${version}-${platform}-x64.tar.gz`;
58+
info(`releaseUrl: ${releaseUrl}`)
59+
60+
let cachedPath = find(githubOrgAndName, version)
61+
info(`is cached: ${cachedPath ? true : false}`)
62+
if (!cachedPath) {
63+
const downloadPath = await downloadTool(releaseUrl)
64+
info(`downloadPath: ${downloadPath}`)
65+
66+
const extractPath = await extractTar(downloadPath, tempDirectory)
67+
info(`extractPath: ${extractPath}`)
68+
69+
const extractedFile = join(extractPath, binaryName)
70+
info(`extractedFile: ${extractedFile}`)
71+
72+
cachedPath = await cacheFile(extractedFile, binaryName, githubOrgAndName, version)
73+
}
74+
info(`using cache path: ${cachedPath}`)
75+
76+
const rustBinary = join(cachedPath, name);
77+
info(`using binary: ${rustBinary}`)
78+
79+
const args = getArgs({ getInput, getBooleanInput, getMultilineInput });
80+
info(`using args: ${args.join(" ")}`)
81+
82+
endGroup()
83+
84+
await exec(rustBinary, args);
85+
}

0 commit comments

Comments
 (0)