#23 WIP: (do not merge yet) Replace build/preview scripts with improved build script
Merged 2 years ago by ankursinha. Opened 2 years ago by ankursinha.

file removed
-47
@@ -1,47 +0,0 @@ 

- #!/bin/sh

- 

- image="docker.io/antora/antora"

- cmd="--html-url-extension-style=indexify site.yml"

- 

- if [ "$(uname)" == "Darwin" ]; then

-     # Running on macOS.

-     # Let's assume that the user has the Docker CE installed

-     # which doesn't require a root password.

-     echo ""

-     echo "This build script is using Docker container runtime to run the build in an isolated environment."

-     echo ""

-     docker run --rm -it -v $(pwd):/antora $image $cmd

- 

- elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

-     # Running on Linux.

-     # Check whether podman is available, else faill back to docker

-     # which requires root.

- 

-     if [ -f /usr/bin/podman ]; then

-         echo ""

-         echo "This build script is using Podman to run the build in an isolated environment."

-         echo ""

-         podman run --rm -it -v $(pwd):/antora:z $image $cmd --stacktrace

- 

-     elif [ -f /usr/bin/docker ]; then

-         echo ""

-         echo "This build script is using Docker to run the build in an isolated environment."

-         echo ""

- 

-         if groups | grep -wq "docker"; then

-             docker run --rm -it -v $(pwd):/antora:z $image $cmd

-         else

-                 echo ""

-                 echo "This build script is using $runtime to run the build in an isolated environment. You might be asked for your password."

-                 echo "You can avoid this by adding your user to the 'docker' group, but be aware of the security implications. See https://docs.docker.com/install/linux/linux-postinstall/."

-                 echo ""

-                 sudo docker run --rm -it -v $(pwd):/antora:z $image $cmd

-         fi

- 

-     else

-         echo ""

-     echo "Error: Container runtime haven't been found on your system. Fix it by:"

-     echo "$ sudo dnf install podman"

-     exit 1

-     fi

- fi

file added
+218
@@ -0,0 +1,218 @@ 

+ #!/bin/bash

+ 

+ # script to watch source directory for changes, and automatically call build.sh to rebuild as required.

+ 

+ image="docker.io/antora/antora"

+ cmd="--html-url-extension-style=indexify site.yml"

+ srcdir="modules"

+ buildir="public"

+ previewpidfile="preview.pid"

+ inotifyignore=".git*"

+ 

+ watch_and_build () {

+     if ! command -v inotifywait > /dev/null

+     then

+         echo "inotifywait command could not be found. Please install inotify-tools."

+         echo "On Fedora, run: sudo dnf install inotify-tools"

+         stop_preview_and_exit

+     else

+         # check for git

+         # required to get ignorelist

+         if ! command -v git > /dev/null

+         then

+             echo "git command could not be found. Please install git."

+             echo "On Fedora, run: sudo dnf install git-core"

+             stop_preview_and_exit

+         else

+             # Get files not being tracked, we don't watch for changes in these.

+             # Could hard code, but people use different editors that may create

+             # temporary files that are updated regularly and so on, so better

+             # to get the list from git. It'll also look at global gitingore

+             # settings and so on.

+             inotifyignore="$(git status -s --ignored | grep '^!!' | sed -e 's/^!! //' -e 's:/:\*:' | tr '\n' '|')${inotifyignore}"

+         fi

+ 

+         while true

+         do

+             echo "Watching current directory (excluding ${inotifyignore}) for changes and re-building as required. Use Ctrl C to stop."

+             inotifywait -q --exclude "($inotifyignore)" -e modify,create,delete,move -r . && echo "Change detected, rebuilding.." && build

+         done

+     fi

+ }

+ 

+ build () {

+     if [ "$(uname)" == "Darwin" ]; then

+         # Running on macOS.

+         # Let's assume that the user has the Docker CE installed

+         # which doesn't require a root password.

+         echo ""

+         echo "This build script is using Docker container runtime to run the build in an isolated environment."

+         echo ""

+         docker run --rm -it -v $(pwd):/antora $image $cmd

+ 

+     elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

+         # Running on Linux.

+         # Check whether podman is available, else faill back to docker

+         # which requires root.

+ 

+         if [ -f /usr/bin/podman ]; then

+             echo ""

+             echo "This build script is using Podman to run the build in an isolated environment."

+             echo ""

+             podman run --rm -it -v $(pwd):/antora:z $image $cmd --stacktrace

+ 

+         elif [ -f /usr/bin/docker ]; then

+             echo ""

+             echo "This build script is using Docker to run the build in an isolated environment."

+             echo ""

+ 

+             if groups | grep -wq "docker"; then

+                 docker run --rm -it -v $(pwd):/antora:z $image $cmd

+             else

+                     echo ""

+                     echo "This build script is using $runtime to run the build in an isolated environment. You might be asked for your password."

+                     echo "You can avoid this by adding your user to the 'docker' group, but be aware of the security implications. See https://docs.docker.com/install/linux/linux-postinstall/."

+                     echo ""

+                     sudo docker run --rm -it -v $(pwd):/antora:z $image $cmd

+             fi

+ 

+         else

+             echo ""

+         echo "Error: Container runtime haven't been found on your system. Fix it by:"

+         echo "$ sudo dnf install podman"

+         exit 1

+         fi

+     fi

+ }

+ 

+ start_preview () {

+ 

+     # clean up a preview that may be running

+     stop_preview

+ 

+     # always run an initial build so preview shows latest version

+     build

+ 

+     if [ "$(uname)" == "Darwin" ]; then

+         # Running on macOS.

+         # Let's assume that the user has the Docker CE installed

+         # which doesn't require a root password.

+         echo "The preview will be available at http://localhost:8080/"

+         docker run --rm -v $(pwd):/antora:ro -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro -p 8080:80 nginx

+ 

+     elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

+         # Running on Linux.

+         # Fedora Workstation has python3 installed as a default, so using that

+         echo ""

+         echo "The preview is available at http://localhost:8080"

+         echo ""

+         pushd "${buildir}"  > /dev/null 2>&1

+             python3 -m http.server 8080 &

+             echo "$!" > ../"${previewpidfile}"

+         popd > /dev/null 2>&1

+     fi

+ }

+ 

+ stop_preview () {

+     if [ -e "${previewpidfile}" ]

+     then

+         PID=$(cat "${previewpidfile}")

+         kill $PID

+         echo "Stopping preview server (running with PID ${PID}).."

+         rm -f "${previewpidfile}"

+     else

+         echo "No running preview server found to stop: no ${previewpidfile} file found."

+     fi

+ }

+ 

+ stop_preview_and_exit ()

+ {

+     # stop and also exit the script

+ 

+     # if stop_preview is trapped, then SIGINT doesn't stop the build loop. So

+     # we need to make sure we also exit the script.

+ 

+     # stop_preview is called before other functions, so we cannot add exit to

+     # it.

+     stop_preview

+     exit 0

+ }

+ 

+ usage() {

+     echo "$0: Build and preview Fedora antora based documentation"

+     echo

+     echo "Usage: $0 [-awbpkh]"

+     echo

+     echo "-a: start preview, start watcher and rebuilder"

+     echo "-w: start watcher and rebuilder"

+     echo "-b: rebuild"

+     echo "-p: start_preview"

+     echo "-k: stop_preview"

+     echo "-h: print this usage text and exit"

+     echo

+     echo "Maintained by the Fedora documentation team."

+     echo "Please contact on our channels: https://docs.fedoraproject.org/en-US/fedora-docs/#find-docs"

+ }

+ 

+ # check if the script is being run in a Fedora docs repository

+ if [ ! -e "site.yml" ]

+ then

+     echo "site.yml not be found."

+     echo "This does not appear to be a Fedora Antora based documentation repository."

+     echo "Exiting."

+     echo

+     usage

+     exit 1

+ fi

+ 

+ if [ $# -lt 1 ]

+ then

+     echo "No options provided, running preview with watch and build."

+     echo "Run script with '-h' to see all available options."

+     echo

+     echo

+     trap stop_preview_and_exit INT

+     start_preview

+     watch_and_build

+     stop_preview

+ fi

+ 

+ # parse options

+ while getopts "awbpkh" OPTION

+ do

+     case $OPTION in

+         a)

+             # handle sig INT to stop the preview

+             trap stop_preview_and_exit INT

+             start_preview

+             watch_and_build

+             stop_preview

+             exit 0

+             ;;

+         w)

+             watch_and_build

+             exit 0

+             ;;

+         b)

+             build

+             exit 0

+             ;;

+         p)

+             start_preview

+             echo "Please run ./builder.sh -k to stop the preview server"

+             exit 0

+             ;;

+         k)

+             stop_preview

+             exit 0

+             ;;

+         h)

+             usage

+             exit 0

+             ;;

+         ?)

+             usage

+             exit 1

+             ;;

+     esac

+ done

file removed
-18
@@ -1,18 +0,0 @@ 

- #!/bin/sh

- 

- if [ "$(uname)" == "Darwin" ]; then

-     # Running on macOS.

-     # Let's assume that the user has the Docker CE installed

-     # which doesn't require a root password.

-     echo "The preview will be available at http://localhost:8080/"

-     docker run --rm -v $(pwd):/antora:ro -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro -p 8080:80 nginx

- 

- elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then

-     # Running on Linux.

-     # Fedora Workstation has python3 installed as a default, so using that

-     echo ""

-     echo "The preview is available at http://localhost:8080"

-     echo ""

-     cd ./public

-     python3 -m http.server 8080

- fi

The improved script also watches the sources for changes and automatically rebuilds the preview as required.

I'll go discuss this with the docs team, and we can improve it before merging it here (and in other docs projects).

That's a very good idea! Thanks for doing it :)

Now here are a few suggestions & remarks:
The first time I ran the script, it partially failed due to the public dir not being created yet.
Then it complains about inotifywait not being installed, but continues anyway and starts the preview service (in the wrong directory). No build, so the preview showed nothing useful.
I would probably add an exit 1 to the inotify binary check, if not found.
I also think it needs to build a first time before running the inotify loop, and do that before the start_preview so it takes care of the public dir creation if needed.

Then I ran ./builder.sh -b to build. Worked fine.

And finally, ./builder.sh -p to get the preview, which failed (Address already in use) cause there was a rogue python process from the first run.
You should add a check there to make sure there is no pid file existing and a running preview.
The script overwrites the pid file before failing, so at this stage, builder.sh -k was not able to kill the running preview anymore. I had to do that myself.

I liked you give multiple options in the script, but I think it would be much simpler to use if it could do just the build/preview thing by default, without having to run more than one command, which always ends with builder.sh -k (assuming I never forgot to run that).
You could for instance trap the SIGINT signal (ctrl-C) to clean everything up and stop the preview right away.

Last thing, the build/preview scripts were macOS compatible. This one is not.
I don't use macOS myself, so I'm fine with that, but that may not be the case for all doc writers ;)

1 new commit added

  • fix(builder): ensure public exists before running preview
2 years ago

1 new commit added

  • fix(builder): exit if inotifywait is not found
2 years ago

1 new commit added

  • feat(builder): stop preview if running before starting a new one
2 years ago

4 new commits added

  • feat(builder): improve user messages
  • feat(builder): silence popd
  • feat(builder): stop preview and exit if inotifywait not found
  • feat(builder): trap SIGINT to stop preview and kill script
2 years ago

1 new commit added

  • feat(builder): run watch, build, preview if no options provided
2 years ago

1 new commit added

  • feat(builder): do not run if it isn't a Fedora antora docs repo
2 years ago

1 new commit added

  • feat(builder): note how to contact the docs team
2 years ago

Hi @darknao , thanks very much for the review. I think I've addressed all bits. Could you have another look please?

I don't run a mac either, so I really haven't a clue what we need to do for it. I'll post on the discussion asking mac users to please test the script too.

2 new commits added

  • improvement(builder): only trap SIGINT when required
  • fix(builder): correct check for file existence
2 years ago

There is no requirement for antora.yml or the modules directory to be there. Only site.yml is required for Antora. See https://pagure.io/fedora-docs/docs-fp-o or https://gitlab.com/fedora/docs/docs-website/pages for instances.

Since the modules directory is not always there, the inotify could look at the entire root directory instead. That way. if I need to modify the site.yml for instance, it will catch that too.
You can exclude some directories like .git and public to avoid unnecessary rebuilds if you want.

I see you added a rebuild if the public dir doesn't exist.
Let's say I made some changes already, and I want to see the result (This is the primary use case of this script). I run the script, and since the public dir is already there from a previous build, the script will not rebuild anything, and I will only see the preview of an old build, not the new one.
So I think the initial build should happen unconditionally, every time.

4 new commits added

  • fix(builder): always run a build before showing preview
  • improvement(builder): watch root dir but ignore files not tracked by git
  • chore(builder): tweak user message
  • fix(builder): limit check to site.yml only
2 years ago

Thanks. I've made more fixes.

  • only look for site.yml
  • watch root dir, but exclude git directories and files that git is ignoring
  • always run a build before starting a preview

1 new commit added

  • feat(builder): check for git
2 years ago

Looks very good! Great work @ankursinha !

+1

Thanks very much @darknao . I'll leave the PR here open for any more reviews.

Pull-Request has been merged by ankursinha

2 years ago