Featured image of post Project Management

Project Management

The first “real” week of FabAcademy. This week focusses on setting up our personal documentation space. FabAcademy provided us with a Gitlab repository that we will use for this. By default this repository uses markdown for content and mkdocs to convert this to a website.

If you are reading this it means that I succeeded in getting this flow to work and you have reached my personal documentation space.

to learn / to do

looking ahead

what I (think I) already know

As a web/app developer, this week’s goals are comfortably in my comfort zone. I am used to working with git (and its predecessors cvs and subversion) so I think I can skip “Work through a git tutorial” . “Upload it” to the class Archive will also not be a problem.

The “build a personal site” step does not specify how, so I guess all solutions are on the table as long as they result in a static site that can be viewed offline. By default, our personal respository is setup to use Markdown and Mkdocs for this.

Markdown

Markdown is a lightweight markup language for creating formatted texts in a plain-text editor (https://en.wikipedia.org/wiki/Markdown) and optionally convert it to HTML . Although I know what it is, I have never used it.

MkDocs

MkDocs is a static site generator that is geared towards building project documentation (https://www.mkdocs.org/). It uses Markdown files as input and generates a in HTML/CSS website. I am familiar with the concept, but have never used it.

Gitlab

Gitlab is an online git manager, much like Github but open-source. Since I work a lot with Github it’s easy for me to use.

what I want to learn

generating

I am very interested in the static site generator concept. I am used to using frameworks like Vue.js to create apps, or hack something together in WordPress when I need to make a website. But both solutions are not ideal for simple websites that do not need a lot of content updates. I sometimes code those by myself from scratch, but I am looking for a more formalised setup, and I think a static site generator might just solve that problem.

publishing

After every push to the git repository, a job is started on Gitlab that converts the markdown files in the folder “docs” to a website that somehow end up in the right location to be served with my personal web url. I have seen this before on Github with Vue.js but never got to set it up myself. So I am really interested in figuring out how this actually works.

Hugo

I want to replace MkDocs with Hugo as a static site generator, because, well, it looks pretty. It looks pretty on the Hugo website, and I also saw some documentation examples from former students that looked good. It will force me to dive into the publishing part as I have to make the switch from MkDocs to Hugo and therefor break the current working setup.

In the process I expect to learn a lot about Hugo so I can use it in my own practice.

the process

replacing MkDocs with Hugo

First of all I was curious how I could integrate Hugo with our current Gitlab setup. After all, this is a critical part of my plan and it’s best to tackle the critical unknowns first.

I decided to just dive in by figuring out how other students (in earlier years) did this. I knew both Erwin Kooi and Nadieh Bremer used Hugo last year and so I started to browse the repository of Erwin Kooi. Soon enough I found a commit named “Migrated from MkDocs to Hugo as site generator” and found he changed .gitlab-ci.yml :

image: registry.gitlab.com/pages/hugo/hugo_extended

variables:
  GIT_SUBMODULE_STRATEGY: recursive

test:
  script:
  - hugo
  except:
  - master

pages:
  script:
    - hugo -F
  artifacts:
    paths:
    - public
  only:
  - master

This .gitlab-ci.yml is where you can tell Gitlab to run a process. I am not yet sure if it runs by default or that it is something FabAcademy has set up. What I gather from reading it is that it loads an image to perform the listed tasks. For MkDocs this was Python, but as I want to use Hugo I need to load a Hugo image.

Then there are two sections: test and pages. From fellow student Bas I learned that this is where the actual scripts get executed, and that it serves much like a cli (commandline interface, like for example Terminal). By the looks of it, the test script executed always except in the master branch. And the pages script executed only in the master branch. That’s nice, as it meant I could use a separate branch to get Hugo to work, without risking to leave current working website in an unusable state.

So I created a development branch to test it all out:

git checkout -b development 

Then I changed my .gitlab-ci.yml file and pushed it to the development branch.

you got mail!

I immediately got an email from gitlab that the pipeline failed. The pipeline is the process where the scripts run, and when they fail you can see what happened in the CI/CD section in the Gitlab online repository. I found this message:

Error: Unable to locate config file or config directory. Perhaps you need to create a new site.
       Run `hugo help new` for details.

Aha, so that’s what that config.yaml in Erwin’s commit was for! Hugo needs a config file. It specifies the general settings that Hugo needs to run, like what theme to use when generating the site, or the default site language. It also lists the theme specific settings.

I copied the contents of his config.yaml and changed the obvious parameters (name, site url and replaced his hedgehog avatar with my own avatar). I left the references to the geekdoc theme he used, knowing that would probably cause an error as I did not have this theme installed. Then I pushed the changes and waited.

As expected, Hugo now complained about Geekdoc:

Error: module "hugo-geekdoc" not found; either add it as a Hugo Module or store it in "/builds/academany/fabacademy/2022/labs/waag/students/bente-vanbourgondien/themes".: module does not exist

By this little dialog with Hugo I started to understand better how the pipeline worked. In the .gitlab-ci.yaml file, I (or rather, Erwin) specified to load a Hugo image that would handle the parsing of the .md files and converting them to a static site. So the error messages were from Hugo, who was complaining about understandable issues like not having a config file or not finding the theme specified in the config file.

I decided to leave this part of the process here. I got Hugo to work with Gitlab, which was my first goal. The theme could come later, I still had to choose one I liked.

local Hugo

To test out different themes without having to push my changes to the repsoitory to be able to view them, I installed Hugo locally. This was easy to do with Homebrew, that I already had up and running:

brew install Hugo 

I played around with some commands and had a default site running relatively easy.

selecting a theme

I started looking for a theme. I wanted a simple looking clean theme, that could automatically generate a table of contents. It took me quite a while to check out the various themes. In hindsight maybe even a bit too long. Time spent on investigating themes was much longer than the time I spent installing Hugo and getting the hang of it.

Although I tried to avoid it, in the end I settled for the same theme that 2021 alumni Nadieh Bremer used: Stack. Because it was relatively light: about 1mb. And I really liked her navigation: to the left always just the main menu. To the right subnavigation that depended on the subject at hand: a list of all the assignments when viewing the assignments, a list of all the paragraphs when viewing an individual assignment.

This was not a default behaviour of the theme, She modified it herself to make it behave that way. Since I wanted to learn to work with Hugo I decided to make these modifications myself, without using her code. I learn mostly by doing, so I added the theme as a git submodule in the theme directory, browsed the directory structure, fired up the Hugo server and started modifying parts to see what happened.

git submodule

First I had some troubles with the Hugo theme being a submodule, as I was not used to working with submodules in git. Since I wanted to change the theme I thought it needed to be a part of my own repository so I could push my changes.

As I had installed the theme as a git submodule, I wanted to get rid of the submodule part of the theme. First I tried to cheat my way out of it by trying to remove .gitmodules and hoping GitLab would buy that and think that the whole theme was part of my own repository. That failed in the Pipeline:

fatal: No url found for submodule path 'documentation/themes/hugo-theme-stack' in .gitmodules 

I googled a bit around to see if I could delete more files to completely get rid of all the references, but realised that it was probably better to just learn to work with submodules. That turned out to be the better decision. I found out that Hugo just let me override the necessary theme files in my own repository, leaving the whole submodule/theme intact and maintainable.

its own directory

I started working on changing the layout of the theme. Most changes that I made were relatively easy after some digging around. Hugo has a clear structure that is nice to work with. When I was happy with the overall look and functionality, I merged my development branch into the master branch and pushed to master to the Gitlab repository.

Another pipeline error! It seemed that Hugo was running fine, but did not generate the files to upload:

The problem is that I have my Hugo site in a separate directory documentation but want to publish to a directory public that is on the same level. I had gotten to run Hugo by cd-ing into the documentation directory before running Hugo:

script:
    - cd documentation
    - hugo -F

That ran fine on the development branch, where there was no upload step. But on the master it failed. It looked like the generated files did not end up in the public folder that GitLab is using. This is because Hugo by default publishes to a public folder inside it’s own folder.

Let’s see if specifying the path to Hugo’s public folder would fix that (see artifacts section)

pages:
  script:
    - cd documentation
    - hugo -F
  artifacts:
    paths:
    - documentation/public
  only:
  - master

Yes! No pipeline errors.

Let’s see the site online \o/

:-(

Turnes out that this setup actually creates a a structure documentation/public in the publish directory.

I looked into the documentation of Hugo and found some switches for —source and —destination that looked promising.

first up:

hugo -F --source documentation --destination public 

But that didn’t work. Hugo ran fine again, but still an empty public folder

It took me a few tries to figure out that Hugo calculated the destination directory relative to the source directory, and I ended up with:

hugo -F --source documentation --destination ../public 

Yes, the pipeline passed! But… are the files in the correct public folder??

YES!

documentation structure

Although the overall design still needed some tweaks, I now had a functioning structure that would enable me to document the steps I took in the assessments for each week. Maybe now is a good moment to start documenting!

I came up with the following setup for my documentation:

intro

  • a short description of the assignment for that week
  • describing the mandatory steps that are listed in the Fabacademy assignment texts for every week

focus / looking ahead

  • describing what I already know
  • describing what I want to learn

process

  • describing the process and the steps I took

debrief / looking back

  • describing what went wrong, what went well,
  • lessons learned
  • room for improvement

The looking ahead part is important to me. I have found many times that it helps to be aware of where you want to go, to formulate it and to write it down.

archetypes

Hugo works with Archetypes, that function as a blueprint for creating pages and articles. I created a week-bundle archetype that creates a folder with a placeholder image a an index.md The index.md is structured in the way I described earlier.

So now I can create an entry for a new week in the following way:

hugo new --kind week-bundle week/week_01 

And that’s that! Now let’s write it all down :-)

looking back

I certainly learned a lot this week! I learned how to use Hugo as a static site generator. I learned how to configure it, how its templating system works, what partials are, why archetypes come in handy. I learned how to list files and what goes where.

I also got a good idea of how publishing with GitLab works. Where the pipelines come in, how to figure out what went wrong with publishing. What .gitlab-ci.yml is for. How executing commands work in it.

I learned something new with git: using submodules, proving that there is also something to learn when you don’t expect it.

Overall I am happy with how this week went. I ran into issues here and there, but that’s exactly where I learned the most.

I could have worked much faster by using other people’s work. Especially when it comes to kind of ‘cloning’ the functionality of Nadieh’s documentation site. But then I would have learned a lot less about how Hugo works.

I documented a lot this week. Maybe too much. I described almost every step, and my original documentation included even more. Writing this article took me about 4 hours. So I think there is room for improvement there.

I am not yet satisfied by the look and feel of the site. It’s small things, like line spacing in the menu’s and the width of the content part in an article. I hope I will find time to tweak this.

gotcha’s

Here are some things that I learned along the way, that might be useful to remember

  • How you get a list of pages from a folder

    {{ $pages := where .Site.RegularPages "Type" "in" "weeks" }}
    
  • How to prevent the baseurl from config.yaml to be repeated

    add canonifyURLs: true to config.yaml

  • How to have Hugo in its own subfolder and publish to a public folder on the same level

    hugo -F --source documentation --destination ../public 
    
  • How to figure out what is going on in the public folder on GitLab

    Check the pipeline overview and look for a download button to the right of the failed pipeline. This downloads the public folder, so you can see what goes on or wrong in there

Built with Hugo , based on Theme Stack designed by Jimmy , modified for personal use by Bente van Bourgondiën