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 18 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
21 changes: 19 additions & 2 deletions docs/contributing/contrib.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
## PaSh on Docker: A Pocket Guide

This is a pocket guide for running PaSh in a docker container.
This is a pocket guide for running PaSh in a Docker container.

### Loading image

The following will pull and launch the latest image (tag: `pash:latest`) using the name `pash-play`
#### From Docker Hub

The following will pull the latest Docker image (tag: `pash:latest`),
and start a new container using the name `pash-play`.

```sh
docker pull binpash/pash
docker run --name pash-play -it pash
```

This will use `pash-play` for the container (to be able to start/stop it later) and `-it` runs it interactively (subsuming the next command).

To restart after you exit, run `docker start -i pash-play` (flag `-i` starts it interactively.)


#### From source code
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved

If you want to use or develop PaSh for a specific commit, this will
build the latest Docker image.

```sh
git clone git@github.com:binpash/pash.git
cd pash/scripts
docker build -t "pash:latest" .
```


### Customizing image

To be used for continuous integration and testing, this image has been configured to have _read-only_ access to the repo through a different user.
Expand Down
117 changes: 59 additions & 58 deletions docs/tutorial/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,92 +49,93 @@ The new parallel script has POSIX constructs added to explicitly guide paralleli

## Installation

#### Natively on Linux
Regardless of your target platform, PaSh requires the `PASH_TOP`
environment variable to point to a PaSh installation on disk. The
installation method impacts the value of this variable.

_Ubuntu, Fedora, Debian, Arch:_
Use `up`:

```sh
curl up.binpa.sh | sh
```
### Unix-likes

_Other distros_:
Use the system's package manager to install the following packages (some of which might already be installed in your system):
Download your preferred system package (all architectures).

```
git libtool m4 curl automake pkg-config libffi-dev python python3 python3-pip wamerican-insane bc bsdmainutils python3-testresources python3-setuptools locales locales-all wget netcat-openbsd
```
| Package | Install command |
|-----------------------------------|-------------------------------|
| [Red Hat (`pash.rpm`)](#link-tbd) | `yum localinstall ./pash.rpm` |
| [Debian (`pash.deb`)](#link-tbd) | `apt install ./pash.deb` |

Then clone the PaSh repository and run `setup-pash.sh` as follows:

```sh
git clone git@github.com:binpash/pash.git
./pash/scripts/setup-pash.sh
```
Run `pa.sh` to verify installation of the following paths.

As noted at the end of `setup-pash.sh`, make sure you set `PASH_TOP` pointing to the absolute path of the directory `pa.sh` resides (you can optionally place that in your `PATH`).
| Path | Purpose |
|------------------|-----------------------------------------|
| `/usr/bin/pa.sh` | symlink to `/opt/pash/pa.sh` |
| `/usr/lib/pash` | source code (as seen in the repository) |
| `/var/log/pash` | package build logs |

_Installation Flags_:
If something goes wrong, please submit your build logs with a bug
report.

PaSh offers the following installation flags:
* `-p/--prepare` that installs all the required dependencies if your system is supported
* `-o/--opt-agg` that downloads g++-10 and builds an optimized version of some aggregators (not currently implemented in the main PaSh workflow)

To use these flags, see the following installation procedure:
```sh
### Source
[FPM]: https://fpm.readthedocs.io/en/latest/cli-reference.html#general-options

Source deployments start with a clone.

```
git clone git@github.com:binpash/pash.git
cd pash/ && bash scripts/install.sh -p --opti-agg
```

This will install all the dependencies for PaSh on your machine (sudo is used) and the g++-10 toolchain, but also build the respective aggregators.

#### Docker
You can either use the source code to create a Docker image, or deploy
PaSh on the current host. For Docker instructions, see the
[pash-on-docker
guide](../contributing/contrib.md#pash-on-docker-a-pocket-guide).

PaSh on Docker is useful when native installation is not an option -- for example, to allow development on Windows or OS X.
First [make sure you install Docker](https://docs.docker.com/get-docker/) on your machine.
Note that, depending on the configuration, PaSh on Docker may or may not be able to exploit all available hardware resources.
There are two main options for installing PaSh via Docker.
For native deployment, install [FPM][] to prepare native packages. For
a Debian-based distribution (as an example), you can deploy PaSh on
the current host for some label `X`.

_Major Releases:_
The easiest is to `pull` the docker image [from Docker Hub](https://hub.docker.com/r/binpash/pash):
```sh
docker pull binpash/pash
```
We refresh this image (as well as other images) on every major release.
./pash/scripts/package/build-packages.sh X
sudo apt install ./pash/scripts/package/output/pash-X.deb
```

[//]: # "TODO(@nvasilakis, @dkarnikis): Need to automate this per release."
RHEL is no different.

_Latest Commit:_
To built the latest Docker container from scratch, run `docker build` in scripts:
```sh
git clone git@github.com:binpash/pash.git
cd pash/scripts
docker build -t "pash:latest" .
```
This will build a fresh Docker image using the latest commit---recommended for development.

In all the above cases, launching the container is done via:
```sh
docker run --name pash-play -it pash
./pash/scripts/package/build-packages.sh X
sudo yum localinstall ./pash/scripts/package/output/pash-X.rpm
```
PaSh can be found in the container's `/opt/pash` directory, so run `cd pash; git pull` to fetch the latest updates.
More information in the [pash-on-docker guide](../contributing/contrib.md#pash-on-docker-a-pocket-guide).

#### Windows using WSL
[`build-packages.sh`](../../scripts/package/build-packages.sh) defines
supported systems and distribution-specific modifications.


### Docker
[Docker]: https://docs.docker.com/get-docker/

In the context of a [Docker][] container, `PASH_TOP` is `/opt/pash`. The
same directory holds is a copy of the Git repository. Use `git -C
/opt/pash pull` to update the code in a container. PaSh may not be
able to exploit all available hardware resources when used in a
container.

For instructions, see the [pash-on-docker
guide](../contributing/contrib.md#pash-on-docker-a-pocket-guide).

[//]: # "TODO(@nvasilakis, @dkarnikis): Need to automate this per release."


### Windows using WSL

To run PaSh on windows without Docker, install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
A short tutorial is included in the [contributing](../contributing/contrib.md) guide.

## Running Scripts

All scripts in this guide assume that `$PASH_TOP` is set to the top directory of the PaSh codebase (e.g., `/opt/pash` on docker)

**To run scripts in this section of the tutorial, make sure you are in the `intro` directory of the `evaluation`:**
```sh
cd $PASH_TOP/evaluation/intro
```
## Running Scripts

To use this section, run `cd $PASH_TOP/evaluation/intro` first.

> In the following examples, you can avoid including `$PASH_TOP` before `pa.sh` by adding `PASH_TOP` in your `PATH`, which amounts to adding an `export PATH=$PATH:$PASH_TOP` in your shell configuration file.

#### Intro: Hello, Parallel World!

Expand Down
28 changes: 27 additions & 1 deletion pa.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
#!/usr/bin/env bash

export PASH_TOP=${PASH_TOP:-${BASH_SOURCE%/*}}
# Help out with shell configuration
if [ -z "$PASH_TOP" ]; then
me="$(readlink -f "${BASH_SOURCE[0]}")"
export PASH_TOP="$(dirname "$me")"
export PATH="$PASH_TOP:$PATH"
printf '# Add this to your shell configuration.\n\n'
printf " export PASH_TOP='%s'\n" "$PASH_TOP"
printf ' export PATH="$PASH_TOP:$PATH"\n\n'
printf '# If your shell supports process substitution (bash, zsh, etc.),\n'
printf '# then run `. <(%s)` to use this config in your current shell.\n' "$0"
exit 0
fi

# Halt if script was sourced. The above is only a setup aid that
# should not interfere with the script's normal operation.
return 2>/dev/null


rcfile=~/.pash_init
if [ ! -f "$rcfile" ]; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to do those everytime? Or maybe just with a pash-init.sh script? I am afraid that they will add to the overhead of the shell script. Also, I don't think we should print to stdout (see 3 lines below).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: This code is here because it's not suited for system-level deployment. Is it better to use a command line flag here, or ship a configuration helper?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configuration helper is likely the way to go (for now we can have it in setup-pash.sh?), as we're trying to minimize startup overheads.

Copy link
Collaborator Author

@zyrolasting zyrolasting Mar 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configuration helper is likely the way to go (for now we can have it in setup-pash.sh?), as we're trying to minimize startup overheads.

setup-pash.sh is not suitable for post-install steps because it mixes user-level and system-level commands, and starts from the user's perspective. If I did the same:

$ sudo apt install pash # ~ is not correct.
$ pa.sh                 # Not configured for the user

Putting the code in pa.sh was meant to avoid adding an additional setup command, but shell configuration must happen on the user's command. I was going for this:

$ sudo apt install pash # Installs
$ pa.sh                 # Asks for configuration initially, then helps

printf '# Include system-level rules\n' > "$rcfile"
printf ". '%s/scripts/pash-init.sh'\n" "$PASH_TOP" >> "$rcfile"
chmod +x "$rcfile"
printf 'Created %s\n' "$rcfile"
fi


export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/"
# point to the local downloaded folders
export PYTHONPATH=${PASH_TOP}/python_pkgs/
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
13 changes: 13 additions & 0 deletions scripts/distro.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#! /usr/bin/env bash
# Infer Unix-like distribution
#
# TODO: This logic appears verbatim in a few places.
# Deduplicate by having other scripts call this one.
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved

if type lsb_release >/dev/null 2>&1 ; then
distro=$(lsb_release -i -s)
elif [ -e /etc/os-release ] ; then
distro=$(awk -F= '$1 == "ID" {print $2}' /etc/os-release)
fi

printf '%s\n' "$distro" | LC_ALL=C tr '[:upper:]' '[:lower:]'
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
15 changes: 15 additions & 0 deletions scripts/package/after-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#! /usr/bin/env bash
# Called by system package manager to request on-site setup on host.

set -euo pipefail

pashd=/usr/lib/pash
logd=/var/log/pash

say_task() {
printf 'pash: %s (log: %s/%s)\n' "$1" "$logd" "$2"
}

mkdir -vp "$logd"
cd "$pashd/compiler/parser"
ln -fs "$pashd/pa.sh" /usr/bin/pa.sh
33 changes: 33 additions & 0 deletions scripts/package/shell.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#! /usr/bin/env bash
# Launch REPL for building PaSh system packages.

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

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

here="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
PASH_TOP=$(readlink -f "$here/../..")
mkdir -p "$here/output"
echo $here
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved

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

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

# Builds a specific package in the context of FPM's Docker container.
# https://fpm.readthedocs.io/

# Enforce preconditions
set -ex
version="$1"
install_dir=/usr/lib/pash
set +x -u; : "$version"
shift # for remaining $@


print_dotfpm() {
output_format="$1"
output_file="$2"

# I/O rules, with Docker container paths
flag --chdir /src
flag --input-type dir
flag --output-type "$output_format"
flag --package "$output_file"
flag --log info
flag --verbose
flag --force

# Discovery information
flag --name pash
flag --description "Parallelize POSIX shell scripts"
flag --license mit
flag --architecture all
flag --url 'https://github.com/binpash/pash'
flag --version "$version"

zyrolasting marked this conversation as resolved.
Show resolved Hide resolved

# System-level dependencies
flag --depends automake
flag --depends bash
flag --depends bc
flag --depends bsdmainutils
flag --depends curl
flag --depends git
flag --depends g++-10
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved
flag --depends libffi-dev
flag --depends libtool
flag --depends locales
flag --depends locales-all
flag --depends m4
flag --depends netcat-openbsd
flag --depends pkg-config
flag --depends python # Redundant?
flag --depends python3
flag --depends python3-pip
flag --depends python3-setuptools
flag --depends python3-testresources
flag --depends wamerican-insane
flag --depends wget

# Handle requirements.txt with `python3 -m pip`
flag --python-bin /bin/python3
flag --python-obey-requirements-txt
flag --python-internal-pip
zyrolasting marked this conversation as resolved.
Show resolved Hide resolved

# Tell PaSh to set itself up on a target system.
flag --after-install "$PASH_TOP/scripts/package/after-install.sh"

# Map contents from here to target system.
flag --exclude '*.git*'
flag --exclude '*.pyc'
flag --exclude '__pycache__'
flag --exclude '*package/output*'
printf ".=%s\n" "$install_dir"
}

flag() {
if [ "$#" -gt 1 ]; then
printf "%s '%s'\n" "$1" "$2"
else
printf "%s\n" "$1"
fi
}

trap 'rm -f .fpm' EXIT

for output_format in "$@"; do
output_file="/out/pash-${version}"

# Map formats to extensions, when they differ.
case "$output_format" in
*)
output_file="${output_file}.${output_format}"
;;
esac

print_dotfpm "$output_format" "$output_file" > .fpm
set +e
/fpm/bin/fpm && chmod 440 "$output_file"
set -e
printf '\n'
done
Loading