Skip to content

Commit

Permalink
[TASK] Release workflow and scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
gilbertsoft committed Aug 15, 2022
1 parent 77f8ec8 commit 1d6ffa6
Show file tree
Hide file tree
Showing 10 changed files with 638 additions and 3 deletions.
1 change: 1 addition & 0 deletions .ddev/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ omit_containers: [db, dba]
use_dns_when_possible: true
composer_version: "2"
web_environment:
- COMPOSER_ROOT_VERSION=0.6.0
- XDEBUG_MODE=debug,develop,coverage
nodejs_version: "16"

Expand Down
302 changes: 302 additions & 0 deletions .github/actions/dist/release.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
/**
* Core synchronization action.
*
* @param {@actions/github/GitHub} github
* @param {@actions/github/Context} context
* @param {@actions/core} core
* @param {@actions/exec} exec
* @param {string} version
* @param {string} step
* @returns {void}
*/
module.exports = async ({github, context, core, exec}, version, step) => {
/**
* Log a debug message.
*
* core.debug does not recursively resolve all objects so instead we use the
* console.log which behalfs like expected.
*
* @param {...any} data
* @returns {void}
*/
async function debug(
...data
) {
if (!core.isDebug()) {
return
}

console.log(...data)
}

/**
* Executes a command and throws in case of a failure.
*
* @param {string} commandLine
* @param {string[]} args
* @param {ExecOptions} options
* @returns {void}
*/
async function safeExec(
commandLine,
args,
options
) {
const exitCode = await exec.exec(commandLine, args, options)

if (exitCode > 0) {
throw new Error(`"${commandLine}" terminated with exit code ${exitCode}.`)
}
}

/**
* Commits all changes with the given message.
*
* @param {string} message
* @returns {void}
*/
async function commitChange(
message
) {
await safeExec(`git commit -a -m "${message}"`)
}

/**
* Lookups a pending pull request and returns its number or 0 if
* not found.
*
* @param {string} branch
* @returns {number}
*/
async function getPendingPullRequest(
branch
) {
const response = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
head: `${context.repo.owner}:${branch}`,
})

debug(response)

if (response.status !== 200) {
throw new Error(`List pull requests failed (${response.status}).`)
}

var pullRequestNo = 0

if (response.data.length > 0) {
pullRequestNo = response.data[0].number
core.notice(`Pending pull request ${pullRequestNo} found.`)
}

return pullRequestNo
}

/**
* Returns the default branch of the repository.
*
* @returns {string}
*/
async function getDefaultBranch() {
if (context.payload.repository.default_branch !== undefined) {
return context.payload.repository.default_branch
}

const response = await github.rest.repos.get({
owner: context.repo.owner,
repo: context.repo.repo,
})

debug(response)

if (response.status !== 200) {
throw new Error(`Get repository failed (${response.status}).`)
}

return response.data.default_branch
}

/**
* Creates a pull request for the given branch and returns its number.
*
* @param {string} branch
* @param {string} title
* @returns {number}
*/
async function createPullRequest(
branch,
title
) {
const defaultBranch = await getDefaultBranch()

debug(context.repo.owner)
debug(context.repo.repo)
debug(branch)
debug(version)
debug(step)
debug(defaultBranch)

const response = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
head: branch,
base: defaultBranch,
body: ``,
maintainer_can_modify: true,
draft: true,
})

debug(response)

if (response.status !== 201) {
throw new Error(`Create pull request failed (${response.status}).`)
}

core.notice(`Pull request ${response.data.number} created.`)

return response.data.number
}

/**
* Dumps the context if debug mode is enabled.
*
* @returns {void}
*/
async function dumpContext() {
if (!core.isDebug()) {
return
}

core.startGroup(`Dump context attributes`)

try {
console.log(context)
} finally {
core.endGroup()
}
}

/**
* Setups the repository to be able to commit and switches to the
* given branch.
*
* @param {string} branch
* @returns {void}
*/
async function setupRepository(
branch
) {
core.startGroup(`Setup repository`)

try {
await safeExec(`git config user.name github-actions`)
await safeExec(`git config user.email github-actions@github.com`)
await safeExec(`git branch ${branch}`)
await safeExec(`git switch ${branch}`)
} finally {
core.endGroup()
}
}

/**
* Create release or version commit.
*
* @param {string} version
* @param {string} step
* @returns {string}
*/
async function createCommit(
version,
step
) {
core.startGroup('Create release commit')

try {
await safeExec(`composer set-version ${version}`)

let commitMessage = ''
if (step === 'version') {
commitMessage = `[TASK] Set TYPO3 Coding Standards version to ${version}`
} else {
commitMessage = `[RELEASE] Release of TYPO3 Coding Standards ${version}`
}

await commitChange(commitMessage)

return commitMessage
} finally {
core.endGroup()
}
}

/**
* Push changes to the provided branch.
*
* @param {string} branch
* @returns {void}
*/
async function pushChanges(
branch
) {
core.startGroup(`Push changes`)

try {
await safeExec(`git push -f origin ${branch}`)
} finally {
core.endGroup()
}
}

/**
* Create a pull request or update an existing one.
*
* @param {string} branch
* @param {string} title
* @returns {number}
*/
async function createOrUpdatePullRequest(
branch,
title
) {
core.startGroup(`Create pull request`)

try {
let pullRequestNo = await getPendingPullRequest(branch)

if (pullRequestNo !== 0) {
return pullRequestNo
}

pullRequestNo = await createPullRequest(branch, title)

return pullRequestNo
} finally {
core.endGroup()
}
}

try {
dumpContext()

let pullRequestBranch = ''
if (step === 'version') {
pullRequestBranch = 'release/version'
} else {
pullRequestBranch = 'release/release'
}

await setupRepository(pullRequestBranch)

const commitMessage = await createCommit(version, step)

let pullRequestNo = 0
await pushChanges(pullRequestBranch)
pullRequestNo = await createOrUpdatePullRequest(pullRequestBranch, commitMessage)

core.setOutput('pull-request', pullRequestNo)
} catch (err) {
core.setFailed(`Action failed with error ${err}`)
}
}
8 changes: 8 additions & 0 deletions .github/release-drafter-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name-template: 'TYPO3 Coding Standards Package $RESOLVED_VERSION'
tag-template: '$RESOLVED_VERSION'
version-template: '$MAJOR.$MINOR.$PATCH-dev'
prerelease: true
version-resolver:
default: minor
filter-by-commitish: true
template: _⚠⚠⚠ Draft to calculate next release. Will be overwritten with the next release and can be deleted at any time ⚠⚠⚠_
43 changes: 43 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
template: |
## What's Changed Since $PREVIOUS_TAG
$CHANGES
**Full Changelog**: <https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION>
category-template: '### $TITLE'
name-template: 'TYPO3 Coding Standards Package $RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
tag-prefix: 'v'
version-template: '$COMPLETE'
change-template: '- $TITLE by @$AUTHOR in <$URL>'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
categories:
- title: '🚀 Features'
label: 'enhancement'
- title: '🐞 Bug Fixes'
label: 'bug'
- title: '🧰 Maintenance'
label: 'maintenance'
- title: '📖 Documentation'
label: 'documentation'
- title: '🔓 Security'
label: 'security'
- title: '⚠ Breaking'
label: 'breaking'
exclude-labels:
- 'skip-changelog'
version-resolver:
major:
labels:
- 'breaking'
minor:
labels:
- 'enhancement'
patch:
labels:
- 'bug'
- 'documentation'
- 'maintenance'
- 'security'
default: patch
filter-by-commitish: true
Loading

0 comments on commit 1d6ffa6

Please sign in to comment.