Hugo deployed via ssh - how to be sure that what is on web server is the same as on my machine

I write my Hugo site on my main linux laptop, deploy on a hosting site using ssh/rsync - this works really great. However, I have a home git server through which I keep the site development on several other machines too - the main home computer and a laptop handy for lugging around.

My site is for my students and I need to update it from a couple to maybe 10 times a year. So sometimes I am not quite sure if the machine on which I am doing the update is the same from which I deployed the site. And I may not have immediate access to my home git server.

Is there a good scheme how to automatically increase the version number of the site when I deploy it and write it on the website as well. Maybe as a version number on the footer of the site. Or maybe a file that only contains the version number (it would then be in the /public directory). Thus the version number would also be synced via git repo, so whenever in doubt, I could compare the website version to its version on my local-working-directory/public.

I am thinking maybe I should try to write a bash script for deployment. Currently I am doing a one-liner of type hugo && rsync ... Is there an existing good practice how to achieve what I am thinking of?

With Node.js and a release script you could instead of running hugo && rsync add a couple of scripts that increment the version number, put that number into a text file, then sync the public folder up to the server if you wish to know what exact version is on the server.

It’s probably the same with any other scripting language you know better.

You could also work with Git-Branches and “release” by merging into the master branch and then have an action/workflow that creates and uploads the site (via Github or any other Git service provider) on that master branch.

The simplest would be to make sure that your rsync command has a --delete parameter so that files that stopped existing are actually deleted on the server. If you use a pipe for your Javascript and Stylesheet files, then they will have different names per build run (well, when you change their content) so that they will be newly loaded and not accidentally cached.

This all depends on your setup in the end. If you put it all in a bash script, you can comment on each command so you still understand your work a year from now. So, that would probably be the least useful step to add to your current workflow.

1 Like

Thanks, David, that is a helpful reflection. I think I will go the way of making a deploy script. I imagine the last sentence of your post is meant to read not “So, that would probably be the least useful step to add to your current workflow.” but “So, that would probably be the most useful step to add to your current workflow.” - since the script would be in a language I know and there would be comments.

Since you are using git I would also recommend to use tags for a released version and deploy only tagged commits.

In your script check if your current local copy is behind or more recent than the tag.

In general I would recommend to only deploy from your remote

Also automatic tag creation could be done in the deploy script by getting last tag, create a new increased one and push the tag back. Let then the script add the tag name to a eg data file and then call hugo. In your templates use the data file.

More effort in the script but might be better than manually update a version file

1 Like

Thanks @irkode, very useful pointers. I completely agree that more effort upfornt is worth while and saves time later. I have a couple of questions, if I may:

  • you suggest deploying from the remote (probably so that I make sure that remote always contains the latest), but the remote does not have a working directory and I deploy from the /public in working directory
  • With regard to automatic tagging using git tag - would you know if somewhere there is a working sample script that does something similar?

My brain was saying “at least do that, oh wait, let’s sound sophisticated” :smiley: You are right.

2 Likes

In fact I should have said you should only publish a state that is pushed to the remote. (You should always have one repository (usually the remote) that is the only valid source for a release)
So one could do

  • make changes and commits
  • create a tag

If you record the exact version (tag) on the target site you are able to check later. but if you don’t push you cannot get the correct source version from another machine.

All that depends on what you need for updating. I usually do multiple commits and pushes and if all is fine I create a tag and publish. And If you are using branches and merges

you can overcome this by

  • commit&push the final result after calling Hugo. In that case you

    • will have to make sure to tag first
    • have a clean working dir (hugo won’t remove deleted content files when processing)
  • automatically build on the remote using a git-hook for post-update

not really, sequence should be (semicode)

  • git checkout BRANCH
  • git tag | get first tag
  • increase TAG
  • echo TAG > tagfile
  • git add tagfile
  • git commit
  • git tag TAG -m “release TAG”
  • git push

consider that rather off-topic - so you might find better answers for that scripting on eg stackoverflow or similar.

1 Like

Thanks very much @irkode - this gives me a good starting point, I will work on this and perhaps will paste the script here when I get it done.

I came up with something really simple. I changed the template layouts/site_footer.html to include a simple text file from /static/site-version

    {{ with site.Copyright }}
      {{ replace . "{year}" now.Year | markdownify}} 
      · 
      Version: {{- readFile "/static/site-version" | safeHTML -}}
      ·
    {{ end }}

and the version file gets updated just before publishing, using a one-liner:

(echo -n `git rev-parse --short HEAD`; echo -n "  " ; \
echo `date +'%Y-%m-%d'`) > ./static/site-version && hugo && \
rsync -avz --delete -e 'ssh -p 22' public/ me@my.host:/srv-dirs/public_html/

of course, I could have put it in a script, but I quite like one-liners in shell history.

Thanks all for the help!