Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: "Release"
# concurrency: Ensures that for one branch the workflow is not running multiple
# times at the same time as we will get trouble with the versions and pushes.
concurrency: ci-${{ github.ref }}

on:
workflow_dispatch:
inputs:
release_type:
description: |
Release Type: "minor" is typical for license update release. More details in README.
required: true
default: "minor"
type: choice
options:
- major
- minor
- patch

run-name: |
${{ github.workflow }} (${{ github.event.inputs.release_type }})

permissions:
contents: write
pull-requests: write

jobs:
release-prepare:
runs-on: ubuntu-latest

outputs:
prev-version: ${{ steps.version.outputs.prev_version }}
next-version: ${{ steps.version.outputs.next_version }}
pull-request-branch: ${{ steps.create-pull-request.outputs.pull-request-branch }}
pull-request-number: ${{ steps.create-pull-request.outputs.pull-request-number }}

steps:
- name: Checkout repository
id: checkout-prepare
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Update Version
id: version
run: |
echo "prev_version=$(cat .version)" >> $GITHUB_OUTPUT
bin/version.sh ${{ github.event.inputs.release_type }}
echo "next_version=$(cat .version)" >> $GITHUB_OUTPUT
- name: Create pull request
id: create-pull-request
# https://github.com/peter-evans/create-pull-request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "ci(release): Update version to ${{ steps.version.outputs.next_version }}"
branch: release/${{ steps.version.outputs.next_version }}
title: "Release ${{ steps.version.outputs.next_version }}"
body: "This pull request updates the version to ${{ steps.version.outputs.next_version }}."
base: main
release-await:
runs-on: ubuntu-latest
needs: release-prepare
steps:
- name: Wait for pull request to be merged
# https://github.com/actions/github-script
uses: actions/github-script@v7
with:
script: |
const pr = await github.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ needs.release-prepare.outputs.pull-request-number }}
});
while (pr.data.merged_at === null) {
await new Promise(resolve => setTimeout(resolve, 10000));
pr = await github.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ needs.release-prepare.outputs.pull-request-number }}
});
}
release-tag:
runs-on: ubuntu-latest
needs:
- release-prepare
- release-await
outputs:
tag-name: ${{ steps.tag-release.outputs.tag_name }}
steps:
- name: Checkout repository
id: checkout-tag
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set Git user
run: |
git config --global user.name "${{ github.actor }}"
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
- name: Tag Release
id: tag-release
run: |
next_version="${{ needs.release-prepare.outputs.next-version }}"
tag_name="v${next_version}"
git tag -a -m "Release ${next_version}" "${tag_name}"
git push origin "${tag_name}"
echo "tag_name=${tag_name}" >> $GITHUB_OUTPUT
release-artifacts:
# The Pull Request is merged. Now we can perform the release.
runs-on: ubuntu-latest
needs:
- release-prepare
- release-tag
outputs:
release-artifacts-url: ${{ steps.upload-artifacts.outputs.artifact-url }}
steps:
- name: Checkout repository
id: checkout-perform
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ needs.release-tag.outputs.tag-name }}
- name: Upload Release Artifacts
id: upload-artifacts
uses: actions/upload-artifact@v4
with:
name: lib-bash-${{ needs.release-prepare.outputs.next-version }}
include-hidden-files: true
path: |
.version
README.md
UNLICENSE
lib_*.sh
release-complete:
runs-on: ubuntu-latest
needs:
- release-tag
- release-artifacts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
release-url: ${{ steps.create-release.outputs.url }}
steps:
- name: Create Release
id: create-release
# https://github.com/softprops/action-gh-release
uses: softprops/action-gh-release@v2
with:
files: |
${{ needs.release-artifacts.outputs.release-artifacts-url }}
tag_name: ${{ needs.release-tag.outputs.tag-name }}
name: ${{ needs.release-tag.outputs.tag-name }}
body: "Release ${{ needs.release-tag.outputs.tag-name }}"
draft: false
prerelease: false
release-summary:
# Output Markdown Report to $GITHUB_STEP_SUMMARY
runs-on: ubuntu-latest
needs:
- release-prepare
- release-tag
- release-complete
steps:
- name: summary
id: summary
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
# ${{ github.workflow }} (${{ github.event.inputs.release_type }})

* **Version**
* Previous Version: ${{ needs.release-prepare.outputs.prev-version }}
* Next Version: ${{ needs.release-prepare.outputs.next-version }}
* [Release ${{ needs.release-tag.outputs.tag-name }}](
${{ needs.release-complete.outputs.release-url }}
)
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

/tmp/

## Build Artifacts

/build/
/dist/

## Logs & Output

*.log
Expand Down
1 change: 1 addition & 0 deletions .version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.1
122 changes: 122 additions & 0 deletions bin/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env bash
###
### Script to build this project.
###
### Creates a ZIP and TAR.GZ archive of the project, that includes the
### relevant artifacts for local usage (if not using as Git submodule or
### subtree).
###
### The archive will contain:
###
### - .version
### - README.md
### - UNLICENSE (thus, the license)
### - lib_*.sh files
###
### within a directory named `lib-bash` within that archive.
###
### The archived will be named `lib-bash-<version>.zip` and
### `lib-bash-<version>.tar.gz`.
###
### Directories:
###
### - build/ - working directory for the build process
### - dist/ - final location of the archives
###

set -o errexit # abort on nonzero exit status
set -o nounset # abort on unbound variable
set -o pipefail # don't hide errors within pipes

MY_PATH="$(realpath "${BASH_SOURCE[0]}")"
readonly MY_PATH
SCRIPT_DIR="$(dirname "${MY_PATH}")"
readonly SCRIPT_DIR

WORKSPACE_ROOT="$(realpath "${SCRIPT_DIR}/..")"
readonly WORKSPACE_ROOT
declare -r VERSION_FILE=".version"
declare -r README_FILE="README.md"
declare -r LICENSE_FILE="UNLICENSE"
declare -r BUILD_DIR="build"
declare -r DIST_DIR="dist"

function main() {
local result_format="${1:-}"
local version=""
local zip_file=""
local tar_file=""

# Validate dependencies
if ! command -v zip &>/dev/null; then
echo "Error: 'zip' is required. Please install it first."
exit 1
fi

if ! command -v tar &>/dev/null; then
echo "Error: 'tar' is required. Please install it first."
exit 1
fi

cd "${WORKSPACE_ROOT}"

# Fail if version file is missing
if [[ ! -f "${VERSION_FILE}" ]]; then
echo "Error: Missing version file '${VERSION_FILE}'."
exit 1
fi

# Read the version from the file
version=$(<"${VERSION_FILE}")

zip_file="${DIST_DIR}/lib-bash-${version}.zip"
tar_file="${DIST_DIR}/lib-bash-${version}.tar.gz"

# Validate the README file
if [[ ! -f "${README_FILE}" ]]; then
echo "Error: Missing README file '${README_FILE}'."
exit 1
fi

# Validate the LICENSE file
if [[ ! -f "${LICENSE_FILE}" ]]; then
echo "Error: Missing LICENSE file '${LICENSE_FILE}'."
exit 1
fi

# Create the build directory
rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}/lib-bash"

# Copy the files to the build directory
cp "${VERSION_FILE}" "${BUILD_DIR}/lib-bash"
cp "${README_FILE}" "${BUILD_DIR}/lib-bash"
cp "${LICENSE_FILE}" "${BUILD_DIR}/lib-bash"

# Copy the library files to the build directory
cp "lib_"*.sh "${BUILD_DIR}/lib-bash"

rm -rf "${DIST_DIR}"
mkdir -p "${DIST_DIR}"

# Create the ZIP archive
rm -f "${zip_file}"
(cd "${BUILD_DIR}" && zip -r9 "../${zip_file}" lib-bash &>/dev/null)

# Create the TAR.GZ archive
rm -f "${tar_file}"
tar -czf "${tar_file}" -C "${BUILD_DIR}" lib-bash

if [[ "${result_format}" == "json" ]]; then
echo "{"
echo " \"zip\": \"${zip_file}\","
echo " \"tar\": \"${tar_file}\""
echo "}"
else
echo "Build successful."
echo "ZIP archive: ${zip_file}"
echo "TAR.GZ archive: ${tar_file}"
fi
}

main "${@}"
71 changes: 71 additions & 0 deletions bin/version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
###
### Script read and update the version of the project.
###
### Usage:
### bin/version.sh
### bin/version.sh <version>
### bin/version.sh major
### bin/version.sh minor
### bin/version.sh patch
###

set -o errexit # abort on nonzero exit status
set -o nounset # abort on unbound variable
set -o pipefail # don't hide errors within pipes

MY_PATH="$(realpath "${BASH_SOURCE[0]}")"
readonly MY_PATH
SCRIPT_DIR="$(dirname "${MY_PATH}")"
readonly SCRIPT_DIR

readonly VERSION_FILE="${SCRIPT_DIR}/../.version"

function main() {
local version_argument="${1:-}"
local version=""
local major=0
local minor=0
local patch=0

# Read the version from the file
if [[ -f "${VERSION_FILE}" ]]; then
version=$(<"${VERSION_FILE}")
major=$(echo "${version}" | cut -d. -f1)
minor=$(echo "${version}" | cut -d. -f2)
patch=$(echo "${version}" | cut -d. -f3)
fi

# Increment the version number
case "${version_argument}" in
major)
major=$((major + 1))
minor=0
patch=0
;;
minor)
minor=$((minor + 1))
patch=0
;;
patch)
patch=$((patch + 1))
;;
"")
# No arguments provided, keep the version number as is
;;
*)
# Set the version number
major=$(echo "${1}" | cut -d. -f1)
minor=$(echo "${1}" | cut -d. -f2)
patch=$(echo "${1}" | cut -d. -f3)
;;
esac

if [[ -z "${version_argument}" ]]; then
echo "Current version: ${version}"
else
echo "New version: ${major}.${minor}.${patch}"
fi
}

main "${@}"