-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: Bump mix project version | ||
|
||
inputs: | ||
workflow-actor: | ||
required: true | ||
type: string | ||
repository: | ||
required: true | ||
type: string | ||
release-kind: | ||
description: 'Kind of version bump, one of: major, minor, patch.' | ||
type: string | ||
required: true | ||
gh-token: | ||
required: true | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
path: 'main' | ||
- uses: actions/checkout@v4 | ||
with: | ||
repository: 'Byzanteam/jet-actions' | ||
# FIXME: remove | ||
ref: 'chore/fahchen/bump-mix-version' | ||
path: 'jet-actions' | ||
sparse-checkout: | | ||
denoified-actions/ | ||
- uses: denoland/setup-deno@v1 | ||
with: | ||
deno-version: v1.x | ||
|
||
- name: Create PR | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ inputs.gh-token }} | ||
GH_WORKFLOW_ACTOR: ${{ inputs.workflow-actor }} | ||
GH_REPOSITORY: ${{ inputs.repository }} | ||
RELEASE_KIND: ${{ inputs.release-kind }} | ||
working-directory: "./main" | ||
run: | | ||
../jet-actions/denoified-actions/elixir/bump_version/main.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#!/usr/bin/env -S deno run --allow-all | ||
// Bumps the version of a mix project and opens a PR | ||
// Usage: deno run --allow-all bump_version.ts --patch | ||
// Environment variables: | ||
// - GH_TOKEN: the GitHub token | ||
// - GH_WORKFLOW_ACTOR: the GitHub username of the actor | ||
// - GH_REPOSITORY: the GitHub repository in the format "owner/repo" | ||
// - RELEASE_KIND: the kind of release to make (patch, minor, major) | ||
|
||
import { default as $, Path } from "@david/dax"; | ||
|
||
import { MixProject } from "../src/mix_project.ts"; | ||
import { Repo } from "../../fundamental/repo.ts"; | ||
import { | ||
createOctoKit, | ||
getEnvVarOrThrow, | ||
getGitHubRepository, | ||
} from "../../fundamental/utils.ts"; | ||
import { format } from "@std/semver"; | ||
|
||
const rootPath = new Path(Deno.cwd()); | ||
const repo = new Repo(rootPath); | ||
const mixProject = new MixProject(repo); | ||
|
||
// increment the mix project version | ||
const releaseKind = getEnvVarOrThrow("RELEASE_KIND"); | ||
if ( | ||
releaseKind !== "patch" && releaseKind !== "minor" && releaseKind !== "major" | ||
) { | ||
throw new Error("Must specify --patch, --minor, or --major"); | ||
} | ||
$.logStep(`Incrementing version to ${releaseKind}...`); | ||
await mixProject.increment(releaseKind); | ||
|
||
// setup git config | ||
const actor = getEnvVarOrThrow("GH_WORKFLOW_ACTOR"); | ||
await repo.setGitConfig(actor); | ||
|
||
// update the lock file | ||
const newProjectVersion = format(await mixProject.getVersion()); | ||
const originalBranch = await repo.gitCurrentBranch(); | ||
const releaseBranch = `release/${newProjectVersion}`; | ||
const message = `chore: bump to ${newProjectVersion}`; | ||
|
||
// Create and push branch | ||
$.logStep(`Creating branch ${releaseBranch}...`); | ||
await repo.gitBranch(releaseBranch); | ||
await repo.gitAdd(); | ||
await repo.gitCommit(message); | ||
$.logStep("Pushing branch..."); | ||
await repo.gitPush("-u", "origin", "HEAD"); | ||
|
||
// Open PR | ||
$.logStep("Opening PR..."); | ||
const octoKit = createOctoKit(); | ||
const openedPr = await octoKit.request("POST /repos/{owner}/{repo}/pulls", { | ||
...getGitHubRepository(), | ||
base: originalBranch, | ||
head: releaseBranch, | ||
draft: true, | ||
title: message, | ||
body: getPRBody(), | ||
}); | ||
$.log(`Opened PR at ${openedPr.data.url}`); | ||
|
||
function getPRBody() { | ||
return `Bumped ${repo.name} version\n\n` + | ||
`Please ensure:\n` + | ||
`- [ ] Target branch is correct (\`main\`)\n` + | ||
`- [ ] \`${repo.name}\` version is bumped correctly\n` + | ||
`To make edits to this PR:\n` + | ||
"```shell\n" + | ||
`git fetch origin ${releaseBranch} && git checkout -b ${releaseBranch} origin/${releaseBranch}\n` + | ||
"```\n" + | ||
`\ncc @${actor}`; | ||
} | ||
|
||
Deno.exit(0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { format, increment, parse, ReleaseType, SemVer } from "@std/semver"; | ||
import { default as $, Path } from "@david/dax"; | ||
|
||
import { Repo } from "../../fundamental/repo.ts"; | ||
|
||
const VERSION_REGEX = /version: "([0-9]+\.[0-9]+\.[0-9]+)"/gm; | ||
|
||
export class MixProject { | ||
constructor(readonly repo: Repo) {} | ||
|
||
get mixExsPath(): Path { | ||
const repoRootDir = this.repo.rootDir; | ||
return repoRootDir.join("mix.exs"); | ||
} | ||
|
||
async getVersion(): Promise<SemVer> { | ||
const text = await this.mixExsPath.readText(); | ||
console.log(text); | ||
|
||
const version = VERSION_REGEX.exec(text)?.[1]; | ||
|
||
if (version == null) { | ||
throw new Error(`Could not find version in ${this.mixExsPath}`); | ||
} | ||
|
||
return parse(version); | ||
} | ||
|
||
async increment(part: ReleaseType) { | ||
const currentVersion = await this.getVersion(); | ||
const newVersion = increment(currentVersion, part); | ||
return this.setVersion(newVersion); | ||
} | ||
|
||
async setVersion(version: SemVer) { | ||
$.logStep(`Setting ${this.repo.name} to ${format(version)}...`); | ||
|
||
const text = await this.mixExsPath.readText(); | ||
const newText = text.replace( | ||
VERSION_REGEX, | ||
`version: "${format(version)}"`, | ||
); | ||
|
||
await this.mixExsPath.writeText(newText); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { CommandBuilder, Path } from "@david/dax"; | ||
|
||
export class Repo { | ||
constructor(readonly rootDir: Path) { | ||
if (!this.rootDir.exists()) { | ||
throw new Error(`Directory ${this.rootDir} does not exist`); | ||
} | ||
} | ||
|
||
get name() { | ||
return this.rootDir.basename(); | ||
} | ||
|
||
async setGitConfig(actor: string) { | ||
await this.command([ | ||
"git", | ||
"config", | ||
"user.email", | ||
`${actor}@users.noreply.github.com`, | ||
]); | ||
|
||
await this.command([ | ||
"git", | ||
"config", | ||
"user.name", | ||
actor, | ||
]); | ||
} | ||
|
||
gitCurrentBranch() { | ||
return this.command("git rev-parse --abbrev-ref HEAD") | ||
.text(); | ||
} | ||
|
||
async gitBranch(name: string) { | ||
await this.command(["git", "checkout", "-b", name]); | ||
} | ||
|
||
async gitAdd() { | ||
await this.command(["git", "add", "."]); | ||
} | ||
|
||
async gitCommit(message: string) { | ||
await this.command(["git", "commit", "-m", message]); | ||
} | ||
|
||
async gitPush(...additionalArgs: string[]) { | ||
await this.command(["git", "push", ...additionalArgs]); | ||
} | ||
|
||
command(command: string | string[]) { | ||
return new CommandBuilder() | ||
.command(command) | ||
.cwd(this.rootDir); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { Octokit } from "octokit"; | ||
|
||
export function createOctoKit() { | ||
return new Octokit({ | ||
auth: getGitHubToken(), | ||
}); | ||
} | ||
|
||
export function getGitHubRepository() { | ||
const repoEnvVar = getEnvVarOrThrow("GH_REPOSITORY"); | ||
const [owner, repo] = repoEnvVar.split("/"); | ||
return { | ||
owner, | ||
repo, | ||
}; | ||
} | ||
|
||
function getGitHubToken() { | ||
return getEnvVarOrThrow("GH_TOKEN"); | ||
} | ||
|
||
export function getEnvVarOrThrow(name: string) { | ||
const value = Deno.env.get(name); | ||
if (value == null) { | ||
throw new Error( | ||
`Could not find environment variable ${name}. ` + | ||
`Ensure you are running in a GitHub action.`, | ||
); | ||
} | ||
return value; | ||
} |
Empty file.