diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..2db156a --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,44 @@ +name: Release + +on: + push: + tags: [ 'v*' ] + +jobs: + upkg-bundle: + uses: ./.github/workflows/upkg-bundle.yaml + secrets: inherit + create-release: + needs: [upkg-bundle] + runs-on: ubuntu-latest + name: Create μpkg GitHub release + environment: release + steps: + - id: program_version + uses: orbit-online/program-version@v1.0.0 + - uses: actions/checkout@v4 + with: + ref: ${{ steps.program_version.outputs.version }} + - name: Get release notes from tag + id: tag-message + run: | + eof="$(openssl rand -hex 8)" + msg=$(git tag -l --format='%(contents)' "${{ steps.version.outputs.tag }}") + msg=${msg%%'-----BEGIN'*} + printf "message<<%s\n%s\n%s\n" "$eof" "$msg" "$eof" >> $GITHUB_OUTPUT + env: + REF: ${{ github.ref }} + - name: Download package + uses: actions/download-artifact@v4 + with: + name: upkg-bundle.tar.gz + - name: Create Release + uses: ncipollo/release-action@v1 + with: + name: ${{ steps.program_version.outputs.version }} + body: ${{ steps.tag-message.outputs.message }} + draft: false + prerelease: false + artifacts: upkg-bundle.tar.gz + artifactErrorsFailBuild: true + artifactContentType: application/gzip diff --git a/.github/workflows/upkg-bundle.yaml b/.github/workflows/upkg-bundle.yaml new file mode 100644 index 0000000..ac1ed9e --- /dev/null +++ b/.github/workflows/upkg-bundle.yaml @@ -0,0 +1,20 @@ +name: Create μpkg package + +on: + push: + branches: ['*'] + tags: ['!v*'] + workflow_call: {} + +jobs: + upkg-bundle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./../../action.yaml + - name: Upload upkg-bundle.tar.gz + uses: actions/upload-artifact@v4 + with: + name: upkg-bundle.tar.gz + path: upkg-bundle.tar.gz + retention-days: 1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..df84f3f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Orbit Online A/S + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/action.yaml b/action.yaml new file mode 100644 index 0000000..3b913a0 --- /dev/null +++ b/action.yaml @@ -0,0 +1,40 @@ +name: μpkg bundle +description: Creates a μpkg tarball package +inputs: + version: + description: The version to write to upkg.json. Defaults to using orbit-online/program-version + default: "" + required: false + dest: + description: The package destination. Defaults to using `name` from upkg.json with the .tar.gz extension + default: "" + required: false + paths: + description: |- + Argument list (i.e. space separated) of relative paths to files and directories to include in the package. + upkg.json must not be specified and is assumed to be located in the working directory. + Defaults to 'bin/'. + default: bin/ + required: false + working-directory: + description: The working directory to change to before bundling. + default: "" + required: false +runs: + using: composite + steps: + - id: program_version + uses: orbit-online/program-version@v1.0.0 + if: ${{ inputs.version == "" }} + - id: pkgname + shell: bash + run: printf "dest=%s.tar.gz\n" "$(jq -r .name upkg.json)" >> $GITHUB_OUTPUT + if: ${{ inputs.dest == "" }} + - name: Create μpkg tarball package + shell: bash + run: > + bin/upkg-bundle.sh + "${{ inputs.version == "" && steps.version.outputs.version || inputs.version }}" + "${{ inputs.dest == "" && steps.pkgname.outputs.dest || inputs.dest }}" + ${{ inputs.paths }} + diff --git a/bin/upkg-bundle.sh b/bin/upkg-bundle.sh new file mode 100755 index 0000000..61bad0a --- /dev/null +++ b/bin/upkg-bundle.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# shellcheck source-path=.. +set -Eeo pipefail; shopt -s inherit_errexit nullglob + +main() { + # Ensure stable file sorting + export LC_ALL=C + # Don't include atime & ctime in tar archives (https://reproducible-builds.org/docs/archives/) + unset POSIXLY_CORRECT + # Fixed timestamp for reproducible builds. 2024-01-01T00:00:00Z + export SOURCE_DATE_EPOCH=1704067200 + + local version=$1 dest=$2 tarout + [[ -n $version && -n $dest && $# -ge 3 ]] || fatal "Usage: upkg-bundle.sh VERSION DEST PATHS..." + shift 2 + + # tmpfile for upkg.json + upkgjson=$(mktemp) + jq --arg version "$version" '.version=$version' upkg.json >"$upkgjson" + trap 'rm "$upkgjson"' EXIT + + # Create the archive + # Set the version in upkg.json by redirecting jq output + if ! tarout=$(tar \ + --sort=name \ + --mode='u+rwX,g-w,o-w' \ + --mtime="@${SOURCE_DATE_EPOCH}" \ + --owner=0 --group=0 --numeric-owner \ + --transform="s#${upkgjson#\/}#upkg.json#" \ + -cvaf "$dest" "$@" "$upkgjson" 2>&1); then + rm "$dest" + fatal "Failed to bundle. tar output (the \"Removing leading \`/'\" is from adding upkg.json from \$TMPDIR\):\n%s" "$tarout" + fi +} + +fatal() { + local tpl=$1; shift + printf -- "%s: $tpl\n" "$(basename "${BASH_SOURCE[0]}")" "$@" >&2 + return 1 +} + +main "$@" diff --git a/upkg.json b/upkg.json new file mode 100755 index 0000000..a2f667a --- /dev/null +++ b/upkg.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://schemas.orbit.dev/upkg/upkg-ft-deduplicate.json", + "name": "upkg-bundle" +}