Skip to content
Open
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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ lto = true
codegen-units = 1
opt-level = 3
strip = true
# trim-paths is still nightly-only (rust-lang/cargo#12137); using
# --remap-path-prefix via RUSTFLAGS in CI as the stable workaround.

# When we need a fast binary that compiles slightly faster `release` (useful for CI)
[profile.fast]
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,21 @@ cargo install ouch

Check the [releases page](https://github.com/ouch-org/ouch/releases).

### Reproducing a release build

Release builds are reproducible. Given the source at a tagged commit, anyone can rebuild the same binary and check that it matches what we shipped. Steps:

```
git clone https://github.com/ouch-org/ouch
cd ouch
git checkout <tag>
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
export RUSTFLAGS="--remap-path-prefix=$(pwd)=."
cargo build --locked --release --target <triple>
```

The toolchain version is pinned in `rust-toolchain.toml` and rustup will install it automatically. Cross-compiled targets (anything using `cross-rs/cross`) inherit the cross Docker image's toolchain, which is not pinned by digest yet, so those targets are bit-for-bit reproducible only against the same `cross` image release.

## Compiling from source code

Check the [wiki guide on compiling](https://github.com/ouch-org/ouch/wiki/Compiling-and-installing-from-source-code).
Expand Down
5 changes: 5 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# pinned toolchain for reproducible builds.
# bump deliberately, not on every "stable" release.
[toolchain]
channel = "1.91.0"
profile = "minimal"
23 changes: 21 additions & 2 deletions scripts/package-release-assets.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#!/usr/bin/env bash
set -e

# use the commit timestamp as SOURCE_DATE_EPOCH so packaging is reproducible.
# tar/gzip/zip honour this when set.
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
SOURCE_DATE_EPOCH=$(git -C .. log -1 --pretty=%ct)
export SOURCE_DATE_EPOCH
fi
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"

mkdir output_assets
echo "created folder 'output_assets/'"
ls -lA -w 1
Expand Down Expand Up @@ -40,18 +48,29 @@ for platform in "${PLATFORMS[@]}"; do
mv "$path"/man-page-and-completions-artifacts/* "$path/completions"
rm -r "$path/man-page-and-completions-artifacts"

# normalise mtimes so tar/zip output is reproducible
find "$path" -exec touch -h -d "@${SOURCE_DATE_EPOCH}" {} +

if [[ "$platform" == *"-windows-"* ]]; then
mv "$path/target/$platform/release/ouch.exe" "$path"
rm -rf "$path/target"

zip -r "../output_assets/${path}.zip" "$path"
# -X strips extra fields (uid/gid/timestamps) that vary between runs
(cd "$(dirname "$path")" && find "$(basename "$path")" | LC_ALL=C sort | \
zip -X -@ "../output_assets/${path}.zip")
echo "Created output_assets/${path}.zip"
else
mv "$path/target/$platform/release/ouch" "$path"
rm -rf "$path/target"
chmod +x "$path/ouch"

tar czf "../output_assets/${path}.tar.gz" "$path"
# --sort=name pins file order, --owner/--group/--numeric-owner pin uids,
# --mtime pins timestamps. piping through gzip -n drops the gzip header
# timestamp and original-name field.
tar --sort=name \
--owner=0 --group=0 --numeric-owner \
--mtime="@${SOURCE_DATE_EPOCH}" \
-cf - "$path" | gzip -n -9 > "../output_assets/${path}.tar.gz"
echo "Created output_assets/${path}.tar.gz"
fi
done
Expand Down
Loading