Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: FPM packaging #484

Open
wants to merge 93 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
d3b956b
Add requirements.txt
zyrolasting Mar 2, 2022
71bf2ea
Draft documentation for upcoming changes
zyrolasting Mar 2, 2022
5911c01
Add `scripts/distro.sh`
zyrolasting Mar 2, 2022
b91351b
Help user with setup at entry point
zyrolasting Mar 2, 2022
3a8d913
Draft package build system
zyrolasting Mar 2, 2022
07b3676
Use .pash_init, not .pash-init
zyrolasting Mar 2, 2022
cec3547
Allow shell options for container front end
zyrolasting Mar 2, 2022
102b616
Remove some after-install.sh errors regarding printf and ln
zyrolasting Mar 2, 2022
30c3e44
Exclude '*.git*' and clobber built packages
zyrolasting Mar 2, 2022
170bd2d
Mark distro.sh executable
zyrolasting Mar 2, 2022
47a4a94
Improve config preview
zyrolasting Mar 2, 2022
24abb5d
Rephrase Docker volumes
zyrolasting Mar 2, 2022
39ab2f8
Exclude package build output from future packages
zyrolasting Mar 2, 2022
91851e4
Use PASH_TOP in distro.sh
zyrolasting Mar 2, 2022
7ff2ae0
Exclude python cache files in package builds
zyrolasting Mar 2, 2022
73f04a2
Remove --epoch due to incorrect Debian package specifier
zyrolasting Mar 2, 2022
58be73e
Stop trying to be clever with previews
zyrolasting Mar 2, 2022
0892ad8
Remove unhelpful compilation code
zyrolasting Mar 2, 2022
3191b89
Compile libdash
zyrolasting Mar 3, 2022
70de48c
Draft remainder of C compilation
zyrolasting Mar 3, 2022
848c5b0
Remove extra echo
zyrolasting Mar 3, 2022
87d1835
Add Python install step
zyrolasting Mar 3, 2022
16e27f0
Fix typo in .gitignore
zyrolasting Mar 3, 2022
c79c778
Add pacman support
zyrolasting Mar 4, 2022
05ba208
Expand exclude rules
zyrolasting Mar 4, 2022
c7930d1
Compute package file names differently
zyrolasting Mar 4, 2022
41b4633
Clone fpm to the same place
zyrolasting Mar 4, 2022
9137a17
Use ensurepip in post-install
zyrolasting Mar 4, 2022
f322c41
Warn against system package manager use in build step
zyrolasting Mar 4, 2022
e19bc2b
Add FreeBSD and Python packages
zyrolasting Mar 4, 2022
13ecd37
Announce .fpm deletion
zyrolasting Mar 4, 2022
8b65338
Pull out code for merging later
zyrolasting Mar 5, 2022
964db36
Draft package hooks
zyrolasting Mar 5, 2022
65dbf1e
Pass version information to format hook
zyrolasting Mar 5, 2022
29d671f
Avoid sudo in pacman before-test hook
zyrolasting Mar 5, 2022
c2472a3
Add deploy.sh
zyrolasting Mar 5, 2022
ffaabf7
Use python3 in PATH in after-install
zyrolasting Mar 5, 2022
14c7e92
Avoid sudo in apt test
zyrolasting Mar 5, 2022
acafa81
Fix after-install flow
zyrolasting Mar 5, 2022
de2e77c
Replace extra curl dependency with gcc on Arch
zyrolasting Mar 5, 2022
65900d4
Use old Python package hack
zyrolasting Mar 5, 2022
afbd1f7
Simplify comment about -f
zyrolasting Mar 5, 2022
d616574
Avoid sudo in yum test
zyrolasting Mar 5, 2022
e2f8315
Use known PASH_TOP in post-install context
zyrolasting Mar 5, 2022
60c950c
Progogate exit codes differently in package/tools/build
zyrolasting Mar 5, 2022
836bc6a
Show timing lines
zyrolasting Mar 5, 2022
fe585e1
Remove deploy.sh container after use
zyrolasting Mar 5, 2022
0ae726a
Fix typo in PYTHON_PKG_DIR
zyrolasting Mar 5, 2022
366adef
Add g++-10 for .deb
zyrolasting Mar 5, 2022
a37cb4b
Add iterate.sh
zyrolasting Mar 5, 2022
0029aec
Add gcc10-optimize.sh
zyrolasting Mar 5, 2022
187c675
Use sudo for rpm again
zyrolasting Mar 5, 2022
7a13a37
Revert tutorial until public links are available
zyrolasting Mar 5, 2022
9bb8b8b
Add packaging.md
zyrolasting Mar 5, 2022
0c5dbb6
Revert .gitignore: python_pkg_root
zyrolasting Mar 5, 2022
5d5bc97
Remove duplicate libtool dependency
zyrolasting Mar 5, 2022
27d5b80
Update header comment in after-install/hook
zyrolasting Mar 5, 2022
344ab34
Add comment to before-test hook
zyrolasting Mar 5, 2022
e910fa9
Combine distro.sh and gcc10-optimize.sh into utils.sh
zyrolasting Mar 7, 2022
f93a126
Revert contrib.md
zyrolasting Mar 7, 2022
2e5f9dd
Revert pa.sh
zyrolasting Mar 7, 2022
ee36b6b
Stop destructive Python module movement
zyrolasting Mar 8, 2022
0d820ef
Allow sourcing of after-install hook for debugging
zyrolasting Mar 8, 2022
a3121b1
Make test package deployments non-interactive
zyrolasting Mar 8, 2022
6ff4e01
Ask reader to enable Docker experimental features for packaging
zyrolasting Mar 10, 2022
594dd4c
Merge branch 'main' of https://github.com/binpash/pash into binpash-main
zyrolasting Mar 10, 2022
337389f
Merge branch 'binpash-main' into fpm
zyrolasting Mar 10, 2022
5b885da
Merge branch 'main' into fpm
zyrolasting Jun 15, 2022
42f85dc
Remove pash-init.sh
zyrolasting Jun 15, 2022
0875402
Remove dead code
zyrolasting Jun 23, 2022
d180d2f
Add package.yaml workflow
zyrolasting Jun 23, 2022
677cf54
Patch PASH_TOP after installation
zyrolasting Jun 30, 2022
20179f1
Prepare for GitHub Actions
zyrolasting Jun 15, 2022
eb629de
Try all branches for gui packaging workflow
zyrolasting Jul 11, 2022
bd8a9dd
Use different wd
zyrolasting Jul 11, 2022
e7966b3
Use consistent working directory path for make
zyrolasting Jul 11, 2022
e3c482d
Try removing --squash from fpm Makefile
zyrolasting Jul 11, 2022
6c241f1
Upgrade docker login to v2 and don't logout at end of job
zyrolasting Jul 25, 2022
02019b4
Try manual login in deploy.sh
zyrolasting Jul 25, 2022
c1c4683
Delete trailing whitespace
zyrolasting Jul 25, 2022
d042c5f
Alternative workflow
zyrolasting Jul 25, 2022
2671229
Use the right workflow
zyrolasting Jul 28, 2022
ef6e728
Fix docker command in package-build.yaml
zyrolasting Jul 29, 2022
bdf6367
Add --username
zyrolasting Jul 29, 2022
ec7a45c
Circulate docker credentials
zyrolasting Jul 29, 2022
4511bd3
Remove --squash
zyrolasting Jul 29, 2022
1931a48
Fix yaml
zyrolasting Jul 29, 2022
1de0316
Remove excess quotes
zyrolasting Jul 29, 2022
5131b59
Prep for shipment
zyrolasting Jul 29, 2022
41fb1a9
Update packaging.md
zyrolasting Jul 29, 2022
0ba9784
Add warning
zyrolasting Jul 29, 2022
e30d33a
Reword docs
zyrolasting Jul 29, 2022
f61e80f
Use sed for both clone points
zyrolasting Jul 29, 2022
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
65 changes: 65 additions & 0 deletions .github/workflows/package-build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# This is a reusable workflow, as defined by
# https://docs.github.com/en/actions/using-workflows/reusing-workflows
#
# Maintain this separately as the "meat" of the packaging work. Other
# files of form packaging-*.yaml call this one from a different
# perspective.
#
# To handle the documented limitations of reusable workflows, make
# sure the near the /!\ comments match your intended repository and
# user.

name: Package for publication
on:
workflow_call:
inputs:
fallback_version:
type: string
required: true
git_ref:
type: string
required: true
deb_version:
type: string
required: false
rpm_version:
type: string
required: false
pacman_tgz_version:
type: string
required: false
defaults:
run:
shell: bash
jobs:
package-pash:
runs-on: ubuntu-latest
steps:
- name: Clone PaSh
uses: actions/checkout@v2
with:
ref: ${{ inputs.git_ref }}
- name: Clone FPM
uses: actions/checkout@v2
with:
repository: jordansissel/fpm
token: ${{ secrets.GH_PAT }}
path: scripts/package/fpm
- name: Build packages
run: |
build() {
./deploy.sh "$1" "${2:-${{ inputs.fallback_version }}}" "$3";
}
cd scripts/package
sed -i 's/--squash//g' fpm/Makefile
DOCKERHUB_TOKEN='${{ secrets.DOCKERHUB_TOKEN }}'
DOCKERHUB_USERNAME='${{ secrets.DOCKERHUB_USERNAME }}'
echo "$DOCKERHUB_TOKEN" | docker login --username "$DOCKERHUB_USERNAME" --password-stdin;
build ubuntu '${{ inputs.deb_version }}' deb;
build fedora '${{ inputs.rpm_version }}' rpm;
build archlinux '${{ inputs.pacman_tgz_version }}' pacman;
- name: Upload Packages as Artifacts
uses: actions/upload-artifact@v3
with:
name: Packages
path: scripts/package/output
37 changes: 37 additions & 0 deletions .github/workflows/package-gui.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# For use in GitHub's Actions GUI
# https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/
name: On-demand Packaging
on:
workflow_dispatch:
branches:
- '*'
inputs:
fallback_version:
# TODO: The comment in ./package-pull-requests.yaml
# impacts whether this is good for the user to read.
description: 'What fallback version string can I use for some package format? Compatibility not guarenteed for all package formats.'
default: '0.0.1'
required: true
git_ref:
description: 'Git reference, like a branch name or commit hash'
default: 'main'
required: true
deb_version:
description: "What version string should I use in .deb format packages, if not the fallback?"
required: false
rpm_version:
description: '.rpm?'
required: false
pacman_tgz_version:
description: "pacman's .tar.gz?"
required: false
jobs:
build-packages:
uses: zyrolasting/pash/.github/workflows/package-build.yaml@fpm
with:
fallback_version: ${{ inputs.fallback_version }}
deb_version: ${{ inputs.deb_version }}
rpm_version: ${{ inputs.rpm_version }}
pacman_tgz_version: ${{ inputs.pacman_tgz_version }}
git_ref: ${{ inputs.git_ref }}
secrets: inherit
17 changes: 17 additions & 0 deletions .github/workflows/package-pull-requests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Package Public Pull Requests (always 0.0.0)
on:
pull_request:
branches:
- main
- future
jobs:
build-packages:
if: ${{ github.event.pull_request.draft == false }}
uses: zyrolasting/pash/.github/workflows/package-build.yaml@main
with:
# TODO: consider using version files in the repository
# 0.0.0 has been tested to work in Fedora, Ubuntu, Debian, and Arch,
# which does not imply compatibility with all package formats.
fallback_version: '0.0.0'
git_ref: ${{ github.event.pull_request.head.sha }}
secrets: inherit
27 changes: 27 additions & 0 deletions .github/workflows/package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Packaging
on:
pull_request:
branches:
- main
- future

jobs:
package-pash:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Make .deb
run: bash scripts/package/deploy.sh ubuntu "$GITHUB_HEAD_REF" deb
- name: Make .rpm
run: bash scripts/package/deploy.sh fedora "$GITHUB_HEAD_REF" rpm
- name: Make .tar.gz (Pacman)
run: bash scripts/package/deploy.sh archlinux "$GITHUB_HEAD_REF" pacman
- name: Upload Packages as Artifacts
uses: actions/upload-artifact@v3
with:
name: Packages
path: scripts/package/output
75 changes: 75 additions & 0 deletions docs/tooling/packaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Packaging PaSh

`scripts/package` packages PaSh into various formats. The software inside is a suitable
replacement for deployments depending on `install.sh`,
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved
`setup-pash.sh`, `up.sh`, `distro-deps.sh`, and/or `pkg.sh`.


## Building Packages
[eef]: https://github.com/docker/cli/blob/master/experimental/README.md

```
build.sh VERSION [OUTPUT_FORMAT ...]
```

Creates new package files using the repository's current content, each
with mode 440. All output files appear in `scripts/package/output`.

**Clean up junk files and new test results!** The scripts use a
reasonable ignore list, but otherwise defaults to including files
within the PaSh repository.

Command-line arguments correspond to those found in [FPM's
CLI](https://fpm.readthedocs.io/en/v1.14.2/cli-reference.html):

- `VERSION` is the value of `--version`.
- `OUTPUT_FORMAT` is some value for `--output-type`


## Testing Packages

```
deploy.sh IMAGE VERSION FORMAT
```

Performs a test deployment of PaSh, as follows:

1. Run `build.sh VERSION FORMAT`
2. Start Docker container based on `docker pull IMAGE`
3. Install the package from Step 1 in the container from Step 2.
4. Run the newly-installed `pa.sh` against a bundled `evaluation/intro/hello-world.sh` example.

Here, `deploy.sh` installs a `pacman`/`.tar.gz` package deploys in
Arch, a `.deb` package for Debian and Ubuntu, and an RPM package for
Fedora.

```
$ version=0.0.1
$ PATH="$PASH_TOP/scripts/package:$PATH"
$ deploy.sh archlinux $version pacman
$ deploy.sh debian $version deb
$ deploy.sh ubuntu $version deb
$ deploy.sh fedora $version rpm
```

## Developing Packages

```
iterate.sh IMAGE FORMAT
```

Runs `deploy.sh IMAGE 0.0.1 FORMAT`, then prompts to repeat.


## GitHub Actions

The source code repository defines workflows for GitHub actions. The
workflows for packaging all use `deploy.sh` to build and run PaSh's
"Hello, World" example. One workflow responds to new pull requests.

**On-Demand Packaging** is the only workflow that can be directly
used in the GitHub GUI. You can find it under the **Actions** tab.

![image](https://user-images.githubusercontent.com/1312121/181671950-89ec5f57-5b9f-4fdb-90a2-6d1099257ad1.png)

Click "Run Workflow" and fill out the form. The form defines what commit of PaSh gets packaged, and each package format may have its own version string.
13 changes: 10 additions & 3 deletions pa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

export PASH_TOP=${PASH_TOP:-${BASH_SOURCE%/*}}
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/"
# point to the local downloaded folders
export PYTHONPATH=${PASH_TOP}/python_pkgs/
## Register the signal handlers, we can add more signals here

# Until PaSh is set up in a way that naturally integrates with
# Python's system-level paths, prefer local package installations.
export PYTHONPATH="$(
find "$PASH_TOP" \
-type d \( -name site-packages -or -name dist-packages \) \
-printf '%p:'
)$PASH_TOP/python_pkgs"

trap kill_all SIGTERM SIGINT

## kill all the pending processes that are spawned by this shell
Expand All @@ -14,6 +20,7 @@ function kill_all() {
# kill pash_daemon
kill -s SIGKILL "$daemon_pid"
}

## Save the umask to first create some files and then revert it
old_umask=$(umask)

Expand Down
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
jsonpickle
matplotlib
numpy
pexpect
2 changes: 2 additions & 0 deletions scripts/package/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fpm
output
45 changes: 45 additions & 0 deletions scripts/package/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#! /usr/bin/env bash
# Launch REPL for building PaSh system packages.

here="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
PASH_TOP=$(readlink -f "$here/../..")

# We need FPM's source code to build a key Docker image.
if [ ! -d "$here/fpm" ]; then
git clone --depth 1 git@github.com:jordansissel/fpm.git "$here/fpm"
sed -i 's/--squash//g' "$here/fpm/Makefile"
fi

# Make a Docker image that knows about building packages.
if ! docker image inspect fpm 2>&1 >/dev/null; then
make -C "$here/fpm" docker-release-everything
fi

mkdir -p "$here/output"

main() {
local docker_interactive_flags=''
local entrypoint_interactive_flags=''

if [[ $- == *i* ]]; then
set -x
docker_interactive_flags='--interactive --tty'
entrypoint_interactive_flags='--rcfile'
set +x
fi

docker run \
--entrypoint /bin/bash \
--rm \
--user "$(id -u):$(id -g)" \
--volume "$here/output:/out" \
--volume "$here/tools:/tools" \
--volume "$PASH_TOP:/src" \
$docker_interactive_flags \
fpm \
$entrypoint_interactive_flags \
/tools/start "$@"
}

# Only enter if script was not sourced
(return 2>/dev/null) || main "$@"
61 changes: 61 additions & 0 deletions scripts/package/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#! /usr/bin/env bash

# Build, install, and use PaSh in a new Docker container.
#
# deploy.sh IMAGE VERSION FORMAT
#
# Exit code matches that from running `./tests/$3/main.sh` in the
# container. 0 is a sign of PaSh's functionality in the other
# environment.
#
# Scripts in ./tests may use /package in the container to store
# information on the host, but printing should suffice.
#
# $1 - IMAGE name from Docker Hub to use
# $2 - VERSION of PaSh to install in a container
# $3 - FPM package FORMAT for the named PaSh version

set -euo pipefail

me="$(readlink -f "${BASH_SOURCE[0]}")"
mydirname="$(dirname "$me")"
myname="$(basename "$me")"

if [ -f /.dockerenv ]; then
set +x
# Pass control to vertification script.
target_version="$1"
output_format="$2"

# Keep this here, so tests don't need to keep setting the variable.
export PASH_TOP=/usr/lib/pash

"$mydirname/fire-hook.sh" "before-test" "$output_format" "$target_version"

# Basic example must always work, no matter where we're going.
[ -d "$PASH_TOP" ]
test_script="${PASH_TOP}/evaluation/intro/hello-world.sh"
set -x
time pa.sh "$test_script"
time bash "$test_script"
set +x
else
image="$1"
target_version="$2"
output_format="$3"

# Perform a one-off build for the package.
"$mydirname/build.sh" "$target_version" "$output_format"

# It's important to use Docker hub here because we want to verify
# PaSh's behavior against other people's work, namely official OS
# images.
docker pull "$image"

# Invoke self in the container.
docker run \
--rm \
--volume "${mydirname}:/package" \
"$image" \
"/package/${myname}" "$target_version" "$output_format"
fi
18 changes: 18 additions & 0 deletions scripts/package/fire-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#! /usr/bin/env bash

# Fire hook script in response to an event. Hooks are format-specific,
# so Debian packages can respond differently than Arch packages, for
# example.

set -eu
event_name="$1"; shift

here="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
event="$here/hooks/${event_name}"

if [ -f "$event/hook" ]; then
# Pass directory path so the script don't need to figure out where
# it is. -f implies the script does not have to be Bash, but use
# of non-executables must raise an error.
"$event/hook" "$event" "$@"
fi
Loading