From a452c453115b02e6de30376b931456b34ba1d953 Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Fri, 19 Jan 2024 16:03:02 -0500 Subject: [PATCH] Add GIT_BUNDLE_OPTS and ZIP_BUNDLE_OPTS variables The former is passed to `git archive` and the latter to `zip`. Add tests to ensure they can be used for including (with Git) and excluding (with Zip) files. Document these new options in the README. Also tweak the messages emitted when bundling by Git an Zip. --- .github/workflows/cicd.yml | 22 ++++++++++------- README.md | 46 +++++++++++++++++++++++++++++++----- bin/pgxn-bundle | 9 +++---- test/runtest.sh | 48 +++++++++++++++++++++++++++++--------- 4 files changed, 96 insertions(+), 29 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index bf370ee..76b6f33 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -15,14 +15,20 @@ jobs: - uses: actions/checkout@v4 - name: Build Image run: docker build -t pgxn-tools-test . - - name: Test as root - run: "docker run -w /repo --rm --volume \"$(pwd):/repo\" pgxn-tools-test ./test/runtest.sh ${{ matrix.pg }}" - - name: Test as non-root - run: "docker run -w /repo --rm --volume \"$(pwd):/repo\" -e AS_USER=worker pgxn-tools-test ./test/runtest.sh ${{ matrix.pg }}" - - name: Test as root without Repo - run: "docker run -w /repo --rm --volume \"$(pwd)/test:/repo\" pgxn-tools-test ./runtest.sh ${{ matrix.pg }} nogit" - - name: Test as non-root without Repo - run: "docker run -w /repo --rm --volume \"$(pwd)/test:/repo\" -e AS_USER=worker pgxn-tools-test ./runtest.sh ${{ matrix.pg }} nogit" + # Test with Git repo + - name: Test Git as root + run: "docker run -w /repo --rm --volume \"$(pwd):/repo\" pgxn-tools-test ./test/runtest.sh ${{ matrix.pg }} git" + - name: Test Git as non-root + run: "docker run -w /repo --rm --volume \"$(pwd):/repo\" -e AS_USER=worker pgxn-tools-test ./test/runtest.sh ${{ matrix.pg }} git" + - name: Test Git with extra file + run: "docker run -w /repo --rm --volume \"$(pwd):/repo\" pgxn-tools-test ./test/runtest.sh ${{ matrix.pg }} git yes" + # Test without Git repo + - name: Test Zip as root + run: "docker run -w /repo --rm --volume \"$(pwd)/test:/repo\" pgxn-tools-test ./runtest.sh ${{ matrix.pg }} zip" + - name: Test Zip as non-root + run: "docker run -w /repo --rm --volume \"$(pwd)/test:/repo\" -e AS_USER=worker pgxn-tools-test ./runtest.sh ${{ matrix.pg }} zip" + - name: Test Zip with zip excluded file + run: "docker run -w /repo --rm --volume \"$(pwd)/test:/repo\" pgxn-tools-test ./runtest.sh ${{ matrix.pg }} zip yes" publish: # Publish for a tag starting with v. diff --git a/README.md b/README.md index dca5976..8799514 100644 --- a/README.md +++ b/README.md @@ -211,8 +211,15 @@ Validates the PGXN `META.json` file and bundles up the repository for release to PGXN. It does so by archiving the Git repository like so: ``` sh -git archive --format zip --prefix=${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}/ \ - --output ${PGXN_DIST_NAME}-${PGXN_DIST_VERSION} HEAD +git archive --format zip --prefix="${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}/" \ + --output "${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}" HEAD +``` + +If `pgxn-bundle` detects no Git repository, it instead uses `zip` to zip up +entire contents of the current directory with a command like this: + +```sh +zip -r "${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}.zip" . ``` If the `$PGXN_DIST_NAME` or `$PGXN_DIST_VERSION` variable is not set, the @@ -225,10 +232,10 @@ file in this format, for use in GitHub Actions such as [upload-release-asset]: echo bundle=${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}.zip >> $GITHUB_OUTPUT ``` -To exclude files from the bundle, add a `.gitattributes` file to the repository -and use the `export-ignore` attribute to identify files and directories to -exclude. This example excludes some typical Git and GitHub files and -directories, as well as a test script: +To exclude Git repository files from the bundle, add a `.gitattributes` file to +the repository and use the `export-ignore` attribute to identify files and +directories to exclude. This example excludes some typical Git and GitHub files +and directories, as well as a test script: ``` .gitignore export-ignore @@ -237,6 +244,33 @@ test.sh export-ignore .github export-ignore ``` +Use the `$GIT_BUNDLE_OPTS` variable to pass options to the `git archive` command +or `$ZIP_BUNDLE_OPTS` to pass options to the `zip` command. + +For example, if a Git repo contains no `META.json`, but generates it via a +`make` command, it will not be included in the zip archive, because `git +archive` archives only committed files. Use the `--add-file` option to tell `git +archive` to add it, like so: + +```sh +make META.json +export GIT_BUNDLE_OPTS="--add-file META.json" +pgxn-bundle +``` + +If, on the other hand, you're not using a Git repository, `pgxn-bundle` will use +the `zip` utility, instead. If there was a file to exclude from the zip file, +use the `$ZIP_BUNDLE_OPTS` variable to pass the `--exclude` option to `zip`, +something like: + +``` sh +export ZIP_BUNDLE_OPTS="--exclude */.dev-only.txt" +pgxn-bundle +``` + +Note the `*/` prefix, required to match a file name under the +`${PGXN_DIST_NAME}-${PGXN_DIST_VERSION}/` directory prefix. + ### [`pgxn-release`] ``` sh diff --git a/bin/pgxn-bundle b/bin/pgxn-bundle index 5c8cd43..188ef2c 100755 --- a/bin/pgxn-bundle +++ b/bin/pgxn-bundle @@ -20,13 +20,14 @@ VERSION=${PGXN_DIST_VERSION:-$(perl -MJSON=decode_json -E 'say decode_json(join # Now bundle up the distribution for release. release=${DISTNAME}-${VERSION} if [ "true" == "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then - echo "Bundling $release.zip from Git repository..." - git archive -v --format zip --prefix=${release}/ --output ${release}.zip HEAD + echo "Bundling $release.zip with git archive..." + git archive -v --format zip --prefix=${release}/ ${GIT_BUNDLE_OPTS:-} --output ${release}.zip HEAD else - echo "Bundling $release.zip with all files..." + echo "Bundling $release.zip with zip utility..." mkdir /tmp/$release cp -rf . /tmp/$release - (cd /tmp && zip -r $release.zip $release) + set -x + (cd /tmp && zip -r $release.zip $release ${ZIP_BUNDLE_OPTS:-}) mv /tmp/$release.zip . fi echo "bundle=$release.zip" >> $GITHUB_OUTPUT diff --git a/test/runtest.sh b/test/runtest.sh index 55c65a5..f146103 100755 --- a/test/runtest.sh +++ b/test/runtest.sh @@ -3,39 +3,65 @@ set -eu pgversion=$1 -expectgit=${2:-yes} +expectutil=${2:-git} +testopts=${3:-} export GITHUB_OUTPUT="/tmp/github_output" -zipfile=widget-1.0.0.zip +prefix=widget-1.0.0 +zipfile="${prefix}.zip" +extrafile=extra.txt cd $(dirname "$0") -pg-start $pgversion -pg-build-test + +if [ -n "$testopts" ]; then + # Use GIT_BUNDLE_OPTS to add an untracked file to the Git archive or + # ZIP_BUNDLE_OPTS to exclude it. + echo extra > "$extrafile" + export GIT_BUNDLE_OPTS="--add-file $extrafile" + export ZIP_BUNDLE_OPTS="--exclude */$extrafile" +fi + +# pg-start $pgversion +# pg-build-test pgxn-bundle -make clean +# make clean -if [ ! -e $zipfile ]; then - echo 'ERROR: No $zipfile file' +# Make sure pgxn-bundle built the zip file. +if [ ! -f "$zipfile" ]; then + echo ERROR: Missing $zipfile ls -lah exit 2 fi -if [ "$expectgit" = "yes" ]; then +# Unzip the zipfile. +unzip "$zipfile" + +if [ "$expectutil" = "git" ]; then # Make sure runtest.sh was omitted thanks to .gitattributes. - if unzip -l $zipfile | grep -F runtest.sh; then + if [ -f "$prefix/runtests.sh" ]; then echo 'ERROR: Zip file contains runtests.sh and should not' echo ' Did pgxn-bundle use `zip` instead of `git archive`?' exit 2 fi + # Make sure the untracked file was added via GIT_BUNDLE_OPTS. + if [ -n "$testopts" ] && [ ! -f "$prefix/$extrafile" ]; then + echo "ERROR $prefix/$extrafile not included in archive" + exit 2 + fi else # Make sure runtest.sh include in the zip file. - if ! unzip -l $zipfile | grep -F runtest.sh; then + if [ ! -f "$prefix/runtest.sh" ]; then echo 'ERROR: Zip file contains runtests.sh and should not' echo ' Did pgxn-bundle use `git archive` instead of `zip`?' exit 2 fi + # Make sure the extra file was excluded via ZIP_BUNDLE_OPTS. + if [ -n "$testopts" ] && [ -f "$prefix/$extrafile" ]; then + echo "ERROR $prefix/$extrafile included in archive but should not be" + exit 2 + fi fi -rm $zipfile +rm -rf "$prefix" "$zipfile" if ! grep -F "bundle=$zipfile" "$GITHUB_OUTPUT"; then echo "ERROR: Output 'bundle' not appended to $GITHUB_OUTPUT"