Category Archives: 000GIT

Access Control

Welcome to the NZRT Wiki Podcast. Today we’re looking at 🔐 Access Control.

If you work with the NZRT GitHub organisation, understanding who can do what is essential. GitHub access control comes down to two core ideas: roles and teams. Roles define what a person or group can actually do inside a repository, and teams are groups of users who share those permissions together.

Let me walk you through the five roles NZRT uses, from most powerful to least. At the top you have Admin — that is full access, including deleting repositories and changing settings. Below that is Maintain, which lets you push code, merge pull requests, create releases, and adjust certain settings. Then there is Write, giving you the ability to push commits and create branches. Triage is more limited — it is for managing issues and pull request labels, but you cannot push code. And finally, Pull is read-only: you can clone and view, but nothing more.

Now, how does NZRT map these roles to people? The wiki has a table, so let me walk you through each row. There are five entries. First, xc holds the Admin role — full access across all repositories, sitting in the Admin team. Second, pam, fin, and dan all have the Maintain role, in the Team Leads group, each assigned to their relevant repositories. Third, developers get Write access across all repos. Fourth, cas has Triage access through the Sales team — read-only on code, but able to manage issues and labels. And fifth, dai has Pull access through the Data team, meaning read-only across everything.

The wiki also shows the full organisation structure as a visual tree. Think of it this way. At the top is the NZRT GitHub organisation. Underneath that you have two branches — Teams and Repositories. On the Teams side there are five groups. The Admin team, which is xc, has Admin permissions everywhere. The Product Managers team, which is pam, has Maintain access specifically to the nzrt-scripts repository. The Finance team, which is fin, has Maintain access to the dolibarr-custom repository. The Data team, which is dai, has Pull — read-only — access across all repositories. And the Developers team has Write access to everything. On the Repositories side, there are two private repos listed: dolibarr-custom and nzrt-scripts.

So how do you actually assign access? There are two methods. The first is adding a team to a repository. You go into repository settings, find Collaborators and Teams, click Add Teams, select the team you want such as Product Managers or Finance, set the role, and confirm. The second method is adding an individual user directly. Same starting point — repository settings, Collaborators and Teams — but this time you click Add People, search by GitHub username, set the role, and confirm.

Now let me explain the CODEOWNERS file, which is a really useful automation tool. You create this file inside the dot-github folder of your repository. It maps file paths to teams or people who are automatically requested as reviewers whenever a pull request touches those files. The wiki shows several examples, so let me explain what each one does in plain terms. There is a catch-all pattern that makes the admin team a global reviewer of everything. Then, any changes inside the WordPress plugin folder — specifically the wp-sync-core plugin path — will automatically request the Product Managers team for review. Changes to the ERP customisation module request both Product Managers and Finance. Anything touching dolibarr integration modules routes to Finance only. Changes to the CI/CD workflow files go to the Admin team. And any database scripts in the SQL folder are routed to a DBA team. The core idea is simple: when a pull request touches a specific path, the matching team or person is automatically pulled in to review — no manual assignment needed.

That is it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Agentic Cicd Pipelines

Welcome to the NZRT Wiki Podcast. Today we’re looking at Agentic CI/CD Pipelines.

So what makes these pipelines “agentic”? The short answer is that Claude-powered agents aren’t just passive observers in the pipeline — they actively analyse, verify, make decisions, and execute actions. They’re not scripts that blindly run commands. They think about what’s happening and respond accordingly.

The first thing worth knowing is the design philosophy here: less is best. All pipelines reuse the same three core files from the agents framework — the run script, the agent module, and the configs file. There are no new services to stand up, no new infrastructure to manage.

Now let’s talk about the two types of pipelines NZRT runs.

The first type is called Deploy and Agent Verify. This is triggered whenever code is pushed to the main branch on GitHub. After the deployment happens over SSH, a Claude Haiku model steps in to analyse the deploy state and returns either a pass or a fail result. The second type is called Business Event Pipelines. These are triggered either on a schedule via Windows Task Scheduler or by events coming in through a Nextcloud trigger bus. Named pipelines hand off plain-English goals to existing ReAct loop agents, and those agents figure out which tools to use to complete the goal.

Let’s look at the full pipeline catalogue. There are six pipelines in total. The deploy verify pipeline uses Haiku directly and fires on every push to main, annotating the GitHub Actions run with a pass or fail result. The product sync pipeline uses the pam agent, runs daily at two in the morning and also responds to Dolibarr events, and writes a sync log to the shared marketing folder. The backup verify pipeline uses the dan agent, runs every morning at six, and writes a backup verification file to the shared database folder. The daily finance pipeline uses the fin agent at seven in the morning, writing a finance summary to the shared finance folder. The weekly analytics pipeline uses the dai agent every Monday at eight and produces a weekly report in the shared analytics folder. And finally, the health diagnose pipeline also uses dan, but this one is event-driven — it fires when cPanel reports a failure and writes a diagnostics file to the shared database folder.

Let’s go deeper on the Deploy and Agent Verify flow, because it’s a neat piece of work. After your SSH deploy step completes, GitHub Actions sets up Python, installs the Anthropic library, and runs the verify deploy script from the agents framework folder. That script connects to cPanel over SSH, collects three things — the git log, file permissions, and script timestamps — then passes all of that to Claude Haiku in a single-turn call. The whole thing takes about two seconds and costs roughly a tenth of a cent per deploy. If Haiku is satisfied, the pipeline exits cleanly and GitHub shows a green notice annotation saying agent verification passed. If something looks wrong, it exits with a failure code and GitHub shows a red error annotation with Haiku’s diagnosis text. One thing you’ll need to add is a new secret in the NZRT-Scripts repository — the Anthropic API key — so the runner can authenticate.

Now for Business Event Pipelines. You run these by calling the pipeline runner script with the name of the pipeline you want. For example, you’d call it with product sync, or backup verify, or pass a list flag to see all available pipelines. This runner is a thin wrapper over the existing run script — it doesn’t modify the tested entry point, it just maps pipeline names to agent codes and goal templates, then hands off to the ReAct loop in the agent module.

Scheduling is handled by Windows Task Scheduler, not cPanel cron. The reason for this is that agents need access to the Anthropic API key and other system credentials, and those live locally on the laptop. The laptop is the convergence point. To get everything set up, you navigate to the agents framework folder and run the setup scheduled tasks PowerShell script once as Administrator. After that you can verify the tasks were registered by querying the task scheduler and filtering for NZRT entries — you’ll see the task name, its status, and when it’s next scheduled to run. If you want to test one immediately, you can trigger it manually by name without waiting for its scheduled time.

The last piece of the puzzle is the trigger bus. For events that don’t come from GitHub — things like cPanel failures, new products added in Dolibarr, or files uploaded to Nextcloud — NZRT uses a Nextcloud folder as a lightweight message bus. A polling script in the agents framework checks this folder every five minutes and watches for new trigger files. When it finds one, it fires the appropriate pipeline. No ports to open, no extra infrastructure — Nextcloud’s desktop client is already syncing, so the folder is always available.

To summarise the key files you care about: verify deploy lives in the agents framework folder and handles the GitHub Actions verification. Run pipeline also lives there and is your entry point for named pipelines. Poll triggers handles the Nextcloud event bus. Setup scheduled tasks is the one-time PowerShell setup script. And the deploy workflow file in the dot-github workflows folder is where the GitHub Actions changes live.

The key design decisions worth remembering: Haiku for deploy verification because it’s fast and cheap. The pipeline runner wraps but never modifies the tested run script. Windows Task Scheduler because credentials live locally. And Nextcloud as the message bus because the infrastructure is already there.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Automated Testing

Welcome to the NZRT Wiki Podcast. Today we’re looking at Automated Testing.

So what is automated testing and why does NZRT use it? Put simply, automated tests let you validate code changes quickly and reliably — without manually clicking through everything every time someone pushes an update. At NZRT, testing falls into three main categories, and it’s worth understanding the difference between them.

First, you have unit tests. These test individual functions in isolation, meaning any external dependencies like databases or APIs are swapped out for fakes — called mocks — so you’re only checking one small piece of logic at a time. Then there are integration tests, which go a level up and check how components actually interact with each other — think database calls and API connections working together. Finally, end-to-end tests, or E2E tests, simulate full user workflows either in a browser or a live environment. So where a unit test might check a single calculation, an E2E test walks through an entire user journey from start to finish.

A few other concepts you’ll hear mentioned. Test coverage is the percentage of your code paths that tests actually execute — NZRT aims for above eighty percent. CI integration means tests run automatically whenever you open a pull request or push a commit. And critically, if tests fail, that pull request is blocked — it cannot be merged until everything passes. Test results and coverage data are all visible through GitHub Actions.

Now, the tools NZRT uses depend on the language you’re working in. There are four main stacks. For PHP, the framework is PHPUnit and you run it with the phpunit command. For JavaScript, Jest handles both the assertions and the test run via npm test. For Python, pytest does everything — you just run pytest. And for Bash scripts, there’s a tool called bats, which works the same way — you run bats and it handles the rest.

Let’s talk about the Dolibarr custom test suite specifically. Tests live in a directory called tests, and the PHP file shown as an example is called WpSyncProductTest. It contains three test methods that give you a good picture of how tests are structured. The first checks that a product can be created — it inserts a test product and confirms the returned ID is greater than zero, meaning something was actually saved. The second test creates a product object using a specific ID, retrieves its SKU, and checks two things: that the SKU isn’t empty, and that it starts with the prefix NZRT-dash. The third test takes a product, calls a method that syncs it to Dolibarr, and then checks two outcomes — that the sync returned true, and that the product’s Dolibarr status in the database was set to the word “synced”. Together these three tests cover creation, data integrity, and a cross-system sync operation.

Running tests locally is straightforward. For PHP in the Dolibarr custom project, you change into that directory and run phpunit pointing at the tests folder. For JavaScript, it’s just npm test. For Python in the nzrt-scripts repo, you run pytest against the tests directory. And if you want a full coverage report generated as HTML, you add a coverage flag to the phpunit command and it outputs into a coverage folder you can open in a browser.

Coverage reporting is also wired into the CI pipeline. A workflow step runs phpunit with a flag that outputs coverage data in a format called Clover XML. That file is then uploaded to a service called Codecov using a GitHub Actions step — it’s tagged as unit tests and given the name codecov-umbrella. This means every time tests run in CI, coverage trends are tracked automatically over time.

If you want to dig deeper, the related topics to look at next are the CI CD Overview, GitHub Actions Workflows, and the Code Review Process — all linked from this wiki page.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Branch Protection

Welcome to the NZRT Wiki Podcast. Today we’re looking at ??? Branch Protection.

If you’ve ever pushed a change directly to your main branch and immediately regretted it, branch protection is the feature that’s going to save you from yourself. At NZRT, branch protection rules are applied to two critical branches across our repositories — main, which is production, and develop, which is staging. Let’s walk through what that actually means and why it matters.

The idea behind branch protection is straightforward. You’re preventing accidental or unauthorized changes from landing in places that really count. GitHub gives you a toolkit of rules you can switch on, and NZRT uses most of them. Let’s run through the key ones so you know what you’re working with.

First up, requiring pull request reviews. This means nobody can merge code into a protected branch without it going through a pull request and getting approved. Alongside that, there’s a dismiss stale reviews setting, which means if someone approves your pull request and you then push more commits, that approval gets wiped out. You need a fresh sign-off on what’s actually in the branch right now.

Then there’s requiring code owner review. NZRT uses code owner files to automatically assign the right people to review changes in specific parts of the codebase. If this rule is on, those assigned owners have to approve before anything merges.

Require status checks is another important one. This means your GitHub Actions workflows — things like build jobs, linting, security scans, and tests — all have to pass before the merge button becomes available. Combined with the require branches up to date rule, your branch also has to be current with the base branch before you can merge. There’s also the option to require signed commits, restrict who can push, and auto-delete head branches after a merge to keep things tidy.

Now let’s look at how NZRT actually configures these for a real repository. Taking the Dolibarr Custom repository as an example — for the main branch, which is production, the settings require two approvals before any pull request can merge. Stale reviews are dismissed, code owner review is required, and three status checks must pass: the build job, PHP linting, and a security scan. The branch must be up to date before merging. Only admins can push directly, and only admins can force push. Head branches are automatically deleted after merge.

For the develop branch on that same repository, the rules are a bit more relaxed. You only need one approval instead of two. Stale reviews are still dismissed, but code owner review is not required. All GitHub Actions must still pass and the branch must be up to date, but developers can push small fixes directly without needing admin rights. Auto-delete is still on.

A second repository configuration follows a similar pattern for its main branch — one approval required, stale reviews dismissed, code owner review on. It requires four status checks to pass: PHP linting, PHPStan static analysis, unit tests, and integration tests. Push access is restricted to admins, and head branches auto-delete on merge.

If you need to set up branch protection on a repository yourself, the process is simple. You go to repository settings, find the branches section, and click add rule. You enter the branch name pattern — so that would be something like main, develop, or a wildcard covering all release branches. Then you tick the boxes for the rules you want to apply and save.

Now, what happens if there’s an emergency and you genuinely need to bypass protection? NZRT has a defined hotfix process for exactly that. You create a hotfix branch directly from main, make your critical fix, then request a review from someone with admin rights — that’s the xc role at NZRT. You create a pull request, get at least one approval, and merge using a merge commit so the history is preserved. Then you deploy to production immediately, cherry-pick the fix across to develop, and follow up with a post-incident review.

If a full admin override is truly needed and someone with the xc role needs to push directly to main, they must log the reason in a GitHub issue, create a pull request afterward for the audit trail, and notify the team straight away.

Branch protection is one of those things that feels like overhead until the day it stops a bad deploy from happening. Getting it right across your repositories means your production code stays trustworthy and your team has a clear, consistent process to follow every time.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Branching Strategy

Welcome to the NZRT Wiki Podcast. Today we’re looking at Git Branching Strategy.

If you’ve ever worked on a codebase with more than one person — or even just juggled more than one task at the same time — you’ve probably felt the pain of keeping your code organised. That’s exactly what a branching strategy solves. It’s a set of conventions that define how your team handles parallel development, prepares releases, and deals with those urgent production fixes that always seem to arrive at the worst moment.

Let’s start with the building blocks. At the heart of most branching strategies is the main branch — sometimes called master. This is your production-ready code. Every commit on this branch should be something you could deploy right now. Then there’s the develop branch, which acts as an integration point for work in progress. Think of it as the staging area for your next release.

From there, you branch out — literally. Feature branches are where individual developers do their work. You create one from develop, build your feature, and merge it back in through a pull request. Release branches are for preparing a production release — final testing, version number bumps, and last-minute adjustments. And then there are hotfix branches, for those critical production issues that can’t wait for the next release cycle. You branch a hotfix directly from main, fix the issue, and merge it back into both main and develop so nothing gets lost.

NZRT also uses a consistent naming convention across all branches. You’ll see prefixes like feature, bugfix, hotfix, release, and chore — each followed by a slash and a descriptive name. This means you can tell exactly what a branch is for just by reading its name.

Now, NZRT doesn’t use a single branching model for everything. The approach depends on what you’re working on.

For Dolibarr — that’s the ERP platform — and for Dolibarr custom development, NZRT uses trunk-based development. In this model, the main branch is always production-ready, protected by feature flags that let you deploy code without activating it yet. Feature branches here are short-lived, with a maximum lifespan of three days. The idea is to keep branches small and merge them into main frequently, rather than letting long-running branches drift far from the rest of the codebase. There’s no separate develop branch in this model — everything flows directly to main in small, manageable increments. This suits rapid iteration on ERP features, which is exactly what NZRT needs for Dolibarr work.

One rule applies regardless of which model you’re in: all feature branches require a code review before merging. That means opening a pull request on GitHub and getting at least one reviewer to sign off.

So what does this look like in practice? Imagine you’re working on a WordPress upgrade. You start by switching to the develop branch and pulling down the latest changes, so you’re working from the most current version of the code. Then you create a new branch — something like feature slash wordpress-upgrade. You do your work, commit your changes, and push that branch up to the remote repository. From there, you open a pull request on GitHub so a colleague can review your changes before they’re merged in. That’s the full cycle: branch, build, push, review, merge.

Good branching habits keep your codebase clean, reduce merge conflicts, and make it much easier to trace when and why a change was introduced. Whether you’re in trunk-based development or a more structured flow with a develop branch, the underlying goal is the same — make parallel work manageable and releases predictable.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Cicd Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at CI/CD Overview.

If you’ve ever wondered how code goes from a developer’s laptop to a live production system without someone manually clicking through a checklist at midnight, that’s exactly what CI/CD is all about. CI stands for Continuous Integration, and CD stands for Continuous Deployment. Together, they automate the testing and deployment of your code so that every change is checked, built, and shipped in a reliable, repeatable way.

Let’s break down what each part means. Continuous Integration means that every time a developer pushes a code change or opens a pull request, automated tests kick in immediately. These tests might check code style with a linter, run unit tests to make sure nothing is broken, or even run security scans to catch vulnerabilities early. The idea is that you catch problems at the point of change, not three weeks later when someone is trying to track down a mystery bug.

Continuous Deployment takes it a step further. Once the tests pass, the code is automatically deployed to the right environment. At NZRT, the general pattern is that merging into the develop branch pushes to a staging environment, while merging into main or creating a release tag triggers a production deployment.

There are five main stages in a pipeline. First, lint — which checks that the code is written cleanly and follows style rules. Second, test — which runs all the automated tests. Third, build — which compiles or packages the code into a deployable artifact. Fourth, deploy — which sends that artifact to the target environment. And fifth, verify — which confirms the deployment actually worked, usually through health checks.

There are also a few important supporting concepts to know about. Status checks mean that a pull request is blocked from merging until every pipeline stage passes. Notifications send alerts to Slack or email so the team knows right away if something succeeds or fails. Rollback gives you a quick path back to the previous working version if a deployment goes wrong. And artifacts are the saved build outputs that can be used for release distribution.

Now let’s look at how NZRT specifically uses CI/CD across its two main code areas. For the dolibarr-custom project, which handles WordPress and Dolibarr sync, the pipeline triggers on any push to main or any pull request targeting main. The tests cover PHP linting, a WordPress security scan, and checks for module conflicts. A successful pipeline deploys to the dolibarr-custom staging domain, and when you create a versioned release tag, it goes to production but requires a manual approval step before it does.

For the core Dolibarr ERP project, the setup is similar in terms of triggers and PHP linting, but it also includes unit tests and integration tests. Deployments here go straight to production immediately, but with feature flags turned off by default so new functionality can be controlled after deployment. Health checks and error rate monitoring run continuously to catch anything that slips through.

Let’s walk through the pipeline execution flow, which is shown as a diagram in the wiki. Picture a developer pushing code. That push is detected by GitHub, which triggers GitHub Actions. At that point, the pipeline splits into two parallel tasks running at the same time — the lint check and the test suite. Once both of those finish, the pipeline checks whether everything passed. If yes, it moves on to deploy and then verify, ending in a success state. If either the lint or tests failed, the pipeline stops, marks the build as failed, and automatically posts a comment on the pull request showing what went wrong. That means you get immediate, specific feedback right where you’re working.

Finally, NZRT tracks five key metrics to measure how well the CI/CD system is performing. Build time should be under five minutes for pull request checks. Test coverage should be above eighty percent on any modified code. Deployment frequency for dolibarr-custom is targeted at one to two deployments per day. Lead time — meaning the total time from a commit to it being live in production — should be under thirty minutes. And mean time to recover, which is how long it takes to roll back a bad deployment, should be under five minutes.

Those five numbers give you a clear health picture of your delivery pipeline. If build times start creeping up, or rollback takes longer than expected, those are early signals that something needs attention.

If you want to go deeper on any of this, the wiki links out to three related notes covering GitHub Actions Workflows, Automated Testing, and Deployment Pipelines specifically. Those are worth reading alongside this overview.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Code Review Process

Welcome to the NZRT Wiki Podcast. Today we’re looking at the Code Review Process.

Code review is one of those practices that separates teams that ship quality software from teams that don’t. At NZRT, every code change goes through a structured review process using GitHub pull requests before anything gets merged. Let’s walk through how that works and what’s expected of you whether you’re the person writing the code or the person reviewing it.

First, let’s cover the key roles. There are two main players in every review. You’ve got the author, that’s the person who wrote the code and opened the pull request, and the reviewer, who examines the changes and gives feedback. Reviewers are looking at four main things: correctness, meaning does the code actually do what it’s supposed to do, style, meaning does it follow the team’s conventions, security, meaning does it introduce any vulnerabilities, and maintainability, meaning will future developers be able to understand and change this code without pain.

Now, not all feedback is created equal. Some comments are blocking issues, which are serious enough that the code cannot merge until they’re fixed. Others are suggestions, which are improvements the author can choose to address but aren’t required. Comments happen in threads attached to specific lines of code, so the discussion stays contextual and traceable.

So what does NZRT actually require before a pull request can merge? There are five things. The PR needs at least one approval if it’s targeting the develop branch, or two approvals if it’s going to main. All automated checks must pass, that includes linting, tests, and security scans run by GitHub Actions. The branch must be up to date with the base branch. Every conversation thread must be resolved. And if a CODEOWNER is assigned, they must have approved.

As a reviewer, your job is to genuinely understand the change, check the logic, look for security issues like exposed secrets or improper authentication, verify that edge cases and error handling are covered, confirm that new functionality has tests, and make sure documentation has been updated if needed. You should only approve if you’re actually confident in the quality of what you’re looking at.

As an author, your job starts before the review even begins. Write a clear title and description. Keep your PR focused, one feature or fix per pull request. When feedback comes in, respond to every comment, address it promptly, and request a re-review when you’re ready. Don’t merge without the required approvals, and don’t dismiss someone’s review without discussing it first.

Let’s talk through what good review communication looks like. Imagine a reviewer spots a SQL injection vulnerability. They’d explain the problem, show an example of the problematic pattern, which would be building a query by gluing a variable directly into a string, then show the correct pattern, which uses a parameterized query where a placeholder stands in for the user input and the actual value is passed separately. That separation is what prevents an attacker from manipulating the query.

When the author responds and fixes it, a good response acknowledges the catch, explains what was done to fix it, lists the specific changes made, such as switching to parameterized queries, adding input validation, and adding a unit test, and references the commit where those changes live.

Not every comment is a blocker. A reviewer might suggest extracting some logic into a separate method for reusability and explicitly flag it as not required for merge, just something worth considering for the long run.

The overall flow looks like this. You open a pull request. GitHub Actions run automatically to check lint, tests, and security. If they fail, you fix them before moving forward. If they pass, you request reviewers. Reviewers examine the code and either approve, leave comments, or request changes. If changes are requested, you address them and loop back. Once you have the required approvals and everything is green, a maintainer merges the PR and the branch gets cleaned up.

A few tips to make reviews work well for everyone. Be respectful and focus on the code, not the person. Ask questions instead of making accusations, something like “can you explain why this approach was chosen” is far more useful than just saying “this is wrong.” Suggest solutions, not just problems. Be timely, aim to review within twenty-four hours, same day if you can. Give context when you flag something, explain why it matters whether that’s security, performance, or readability. And don’t forget to call out good work when you see it. Reviews are as much about reinforcing strong patterns as they are about catching problems.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Git Cheatsheet

Welcome to the NZRT Wiki Podcast. Today we’re looking at ?? Git Cheatsheet.

This is a quick reference for the essential Git commands you’ll use day to day at NZRT. Whether you’re just getting started or need a reminder, let’s walk through the key areas together.

First up, setup and configuration. Before using Git on a new machine, you need to tell it who you are. You set your global username and email address — these get attached to every commit you make. Once that’s done, you can view all your configuration settings with a list command. When you’re ready to start a project, you either initialise a new repository from scratch, or clone an existing one from a URL.

Next, the basic daily workflow. You check the status of your working tree to see which files are modified, staged, or untracked. Then you stage the files you want in your next commit — either one at a time, or all changes at once. Once staged, you commit with a message describing what you did. After that, you push your commits up to the remote, and pull down changes your teammates have made.

Branching is how you work on features or fixes without touching the main codebase. You can list your local branches, or all branches including remote ones. You can create a branch and switch to it in one step, or do them separately. When you’re done, you delete it safely — Git warns you if it hasn’t been merged — or force delete if you’re sure. You can also delete a branch from the remote server directly.

For history and inspection, you can view the full commit log or a compact one-line version. You can limit it to the last ten commits, or filter by a specific file. You can show the details of any individual commit, see what’s changed but not yet staged, what’s staged and ready to commit, and even see who changed each line of a file — that last one is called blame.

Merging and rebasing are how you bring branches together. A regular merge combines another branch into your current one. A squash merge does the same but collapses all the incoming commits into a single one, keeping history tidy. Rebasing replays your commits on top of another branch for a clean linear history. Interactive rebase lets you edit, squash, or reorder your recent commits. And if a merge goes wrong mid-way, you can abort it and get back to where you started.

Undoing changes — you’ll need this sooner or later. You can discard changes to a specific file, unstage something you accidentally added, or throw away all local changes with a hard reset back to your last commit. If you need to undo a commit that’s already been pushed, revert is the safe option — it creates a new commit that cancels the old one out. You can also clean out untracked files and directories when your working directory gets messy.

Stashing is your save point for work in progress. If you need to switch context without committing half-finished work, you stash your changes and they’re set aside safely. You can list all your stashes, restore the most recent one with pop, or apply a specific stash by its index number. When you’re done with a stash, you drop it.

Tags and releases give you named markers in your commit history. You can list existing tags, create a lightweight one, or create an annotated tag with a message — annotated tags are the better choice for marking releases. You can push a specific tag to the remote, or push all tags at once.

Remote management covers your connections to remote repositories. You can list your remotes and their URLs, add a new remote, or remove one. Fetch downloads changes from the remote without merging them — handy when you want to inspect before integrating. Fetch with prune also cleans up any remote branches that have been deleted on the server.

And finally, a few advanced commands worth knowing. Cherry-pick lets you apply one specific commit from another branch onto your current one — great for pulling in a single fix. Bisect helps you hunt down which commit introduced a bug by doing a binary search through your history. Reflog shows you a log of everywhere your HEAD has pointed — it’s your safety net when something goes wrong and you need to recover. And filter-branch can rewrite commit history entirely, but that one should be used carefully and deliberately.

That covers the full Git cheatsheet — from first-time setup through to recovery tools for tricky situations.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Git Commands Cheatsheet

Welcome to the NZRT Wiki Podcast. Today we’re looking at the Git Commands Cheatsheet.

Git is the version control system we use across all NZRT repositories, and this cheatsheet covers everything from first-time setup through to advanced recovery operations. Let’s walk through it section by section.

Starting with initial setup. Before you do anything else, you tell Git who you are. There are commands to set your global username, your email address, your preferred text editor, and to switch on coloured output in the terminal. Once those are set, you can list your current configuration at any time to confirm everything looks right.

Next up, creating and cloning repositories. If you’re starting from scratch on a local folder, you initialise Git in that directory, optionally giving the project a name. If you’re pulling down an existing NZRT repo from GitHub, you clone it using its URL. You can also clone into a custom-named folder, or do what’s called a shallow clone, which grabs only the most recent snapshot rather than the full history — useful when you just need the code fast and don’t need every past commit.

Moving on to checking status and history. This is where you spend a lot of your daily Git time. You can check what’s changed right now with the status command, including a short compact version that also shows your branch. For history, you can view the full commit log, or a condensed one-line-per-commit version, limit it to the last five commits, or draw a visual graph showing how branches have diverged and merged. You can filter history by author, by date range, by keywords in commit messages, or even view the actual code changes alongside each commit. You can also view differences — between your working files and the last commit, between staged changes and the last commit, or between any two branches or specific commits.

Branching is next, and it’s one of Git’s most powerful features. You can list all your local branches, all remote branches, or both together. You can create a new branch, switch to an existing one, or create and switch in a single step. Newer versions of Git introduced a cleaner switch command that does the same thing. You can rename branches and delete them — either safely, where Git stops you if the branch hasn’t been merged yet, or forcefully if you’re sure you want it gone. You can also delete branches that exist on the remote server.

Then there’s staging and committing — the core of your daily workflow. You check what’s changed, stage individual files or everything at once, or use interactive mode to choose exactly which chunks of changes to include. You can unstage things if you change your mind. When you commit, you write a short message describing what changed. You can amend your last commit if you forgot something, or add to it without even changing the message. If you want to throw away local changes entirely, there are restore commands that discard them from your working directory.

Merging and rebasing handle bringing branches back together. You can merge a feature branch into your current branch, with options to always create a merge commit or to squash all the feature branch’s commits into one clean commit. Rebasing replays your commits on top of another branch, keeping history linear. Interactive rebase lets you reorder, squash, or edit individual commits — very handy before pushing. Cherry-pick lets you grab one specific commit from anywhere and apply it to your current branch.

Pushing and pulling covers syncing with the remote. You push your local commits up to GitHub, specifying a branch name or using your current branch. The first time you push a new branch, you set the upstream tracking reference at the same time. Force pushing is available but flagged as dangerous — use it carefully. Pulling downloads and merges remote changes in one step, or you can use pull with rebase to keep history cleaner. Fetching downloads changes without merging them, giving you a chance to review before integrating.

Undoing changes is something you’ll need eventually. You can discard file changes, unstage files, or undo entire commits. Revert creates a new commit that cancels out a previous one — the safe option for shared branches. Reset lets you move your branch pointer back one or more commits, with three modes: soft keeps your changes staged, mixed unstages them but keeps the files, and hard discards everything. There’s also a clean command to remove untracked files, with a dry-run option to preview what would be deleted before you commit to it.

Stashing gives you a temporary holding area. If you need to switch context mid-work, you stash your changes, switch branch, do the other work, come back and pop the stash to restore where you were. You can name stashes, list them, apply specific ones, and clear them all at once.

Tags mark release points. Lightweight tags are just pointers to commits. Annotated tags include a message and are the recommended type for releases. You can push individual tags or all tags to the remote, and delete them locally or remotely.

Remote management lets you list, add, rename, or remove the remote servers your repo points to. You can also inspect a remote to see exactly what branches it’s tracking.

Finally, advanced operations. There’s bisect, which helps you find the exact commit that introduced a bug by binary-searching through history. Blame shows you who wrote each line of a file and when. Reflog is your safety net — it records every position your branch pointer has been, so you can recover from almost any mistake. There are also commands to search commit history for specific text, verify signed commits and tags, and view the full change history of a single file.

The cheatsheet ends with a set of useful aliases you can add to your Git configuration — shortcuts like using the letters s t for status, c o for checkout, and a visual alias that draws the full branch graph in one command.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Collaboration Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at GitHub Collaboration Overview.

If you’ve ever wondered how a development team stays coordinated without stepping on each other’s toes, GitHub’s collaboration tools are the answer. Today we’re walking through what those tools are, how NZRT uses them, and what the full workflow looks like from idea to deployment.

Let’s start with the big picture. GitHub gives teams five core collaboration mechanisms. You have pull requests, which are how code gets reviewed before it lands in the main codebase. You have issues, which handle bug tracking and feature planning. You have discussions, which are more open-ended conversations — great for questions, announcements, and ideas that aren’t quite a bug or a feature yet. Then you have project boards, which are essentially a kanban-style way to visualise what work is sitting where. And finally, you have notifications, which keep you informed about mentions, review requests, and assignments. On top of all that, GitHub can sync with tools like Slack, Jira, or Linear, and you can mention teammates directly using the at-sign with their username, or notify an entire team at once using the at-sign with a team name.

Now let’s look at how NZRT actually uses each of these.

Pull requests are where code review happens at NZRT. Before anything gets merged, peers review it. You can leave inline comments on specific lines of code, which makes it easy to point to exactly what you’re discussing. Depending on which branch you’re working with, you’ll need either one or two approvals before a merge can happen. Automated checks also run at this stage — things like linting and tests — so problems get caught before they ever reach the main branch.

Issues are how the team tracks bugs and plans features. When a bug comes in, it gets assigned to a team member and discussed right there in the issue comments. Feature requests get tagged so they can be picked up in future planning cycles. And milestones let you group related issues together — for example, everything targeted for version one-point-one or version two-point-zero lives under its own milestone.

Discussions serve a different purpose. This is where the team announces releases, asks broad questions, shares knowledge, and runs RFCs — which stands for Request for Comments — when an architecture decision needs wider input. It’s also where general troubleshooting conversations happen.

Project boards give you that visual overview of where everything stands. Work items move through four columns: Backlog, In Progress, In Review, and Done. You can drag and drop items as their status changes, and a lot of this can be automated — pull requests can be auto-added to the board when they’re opened, and items can auto-close when a PR gets merged. There are also templates available for issue types that come up repeatedly.

Now let’s talk through the full NZRT collaboration workflow, which runs in five stages.

It starts with planning. A team member creates an issue to describe a feature or bug, adds it to the project board in the Backlog column, assigns it to a developer, and ties it to the relevant milestone.

Stage two is development. The developer creates a feature branch, works locally — in NZRT’s case that means using the Laragon environment — writes commits with descriptive messages, and pushes the branch up to GitHub when ready.

Stage three is code review. The developer opens a pull request from their feature branch and requests between one and two reviewers. Reviewers leave comments, the developer responds and makes any needed changes, pushes those updates, and then waits for approval.

Stage four is merge and deploy. Once the pull request is approved, the maintainer clicks merge. From there, GitHub Actions takes over and automatically deploys to staging. Tests run, and the team gets notified in Slack.

Stage five is the wrap-up. The pull request closes automatically. The feature branch gets deleted automatically. If the pull request was linked to an issue, that issue closes automatically too. And the project board gets updated to reflect that the work is done.

What’s worth noting about this workflow is how much of it is automated. Once the merge happens, you’re not manually chasing down steps — GitHub and the Actions pipeline handle the heavy lifting. That’s what keeps the team moving without communication gaps.

The main takeaway here is that GitHub’s collaboration tools aren’t just about storing code. They’re a full coordination layer for your team — from the moment an idea is captured as an issue, all the way through to it being deployed and confirmed done on the project board.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Commit Message Standards

Welcome to the NZRT Wiki Podcast. Today we’re looking at 💬 Commit Message Standards.

If you’ve ever looked back through a project’s git history and had no idea what anyone was actually doing, this episode is for you. At NZRT, we follow a format called Conventional Commits, and once you get used to it, you’ll wonder how you ever lived without it. It makes your history scannable, your changelogs automatable, and your teammates much happier.

So let’s start with the structure. Every commit message you write follows the same basic shape. You open with a type, then optionally a scope in parentheses, then a colon and a short subject line. Below that, separated by a blank line, you can add a body. And below that, a footer for referencing issues or flagging breaking changes. Think of it as: what kind of change, where it happened, what it does, why it was needed, and what it affects.

Let’s talk about types first. There are ten of them. “feat” is for a new feature. “fix” is a bug fix. “docs” means you’re only touching documentation. “style” is for code formatting changes with no logic impact. “refactor” means you restructured code without changing its behaviour or fixing a bug. “perf” is a performance improvement. “test” is for adding or updating tests. “chore” covers maintenance work like updating dependencies or build config. “ci” is for changes to your continuous integration or deployment setup. And “revert” is for undoing a previous commit.

Now for scope. The scope is optional, but recommended. It goes inside parentheses right after the type, and it tells you which part of the codebase was touched. At NZRT, the approved scopes are: wp-sync for the WordPress and Dolibarr sync module, dolibarr for the ERP integration, api for the REST API, db for database work and migrations, sync for product or data sync, deploy for deployment processes, test for testing infrastructure, and docs for documentation.

Your subject line is the short description that follows the colon. Keep it under fifty characters, write it in imperative mood — so “add” not “added” or “adds” — start it lowercase, and don’t put a period at the end. So you’d write something like: feat wp-sync, colon, add product comparison widget.

The body is where you explain the why. Not what the code does — the code shows that. But why this change was necessary, what problem it solves, or what decision was made. Wrap each line at around seventy-two characters, and leave that blank line between the subject and body.

The footer is for linking to issues. You use “Closes” followed by a hash and issue number to auto-close that issue when the commit merges. “Refs” references an issue without closing it. And if your change breaks something for existing users — like renaming a field in an API response — you add a line starting with BREAKING CHANGE followed by a colon and an explanation. That signals a major version bump is needed.

Let me walk you through a few examples in plain language.

The first example is a feature commit for the wp-sync scope. The subject says “add product comparison widget.” The body explains that a side-by-side comparison feature was implemented for customers, introduces a new shortcode and page template, and includes styling and interactivity. The footer closes issue 42.

The second is a bug fix in the sync scope. The subject is “prevent duplicate product sync.” The body explains that a webhook was firing twice because there was no idempotency check, and that the fix adds signature validation and idempotency key tracking. It closes issue 89 and references issue 87.

There’s also a performance example in the db scope. The subject is “optimize product list query.” The body explains that indexed lookups replace a full table scan for category filtering, cutting query time from five hundred milliseconds down to fifty milliseconds on large catalogs.

And a breaking change example in the api scope. The subject includes an exclamation mark after the scope to flag it as breaking. The footer uses BREAKING CHANGE to explain that a field called product underscore id has been renamed to just id in the response, and tells clients exactly what to update.

Before you commit, run through a quick checklist. Is the type one of the ten approved types? Is the scope lowercase and from the approved list? Is the subject in imperative mood? Is it under fifty characters with no trailing period? Does the body explain why, not what? Are issues referenced properly? And are breaking changes called out in the footer?

Finally, you can enforce all of this automatically with a git hook. You’d create a file called commit-msg inside your dot git hooks folder. The script reads your commit message and checks it against a pattern matching the type, scope, and subject format. If the message doesn’t match, it prints an error, shows you what the expected format looks like, and blocks the commit from going through. You then make the file executable with a chmod command. One-time setup, saves a lot of back-and-forth in code review.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Commits History

Welcome to the NZRT Wiki Podcast. Today we’re looking at Git Commits and History.

If you’ve ever needed to track down exactly when a bug was introduced, or figure out why a piece of code changed three months ago, you already know why commits matter. Commits are the fundamental building blocks of version control. Every time you commit, you’re capturing a snapshot of your project at that moment in time, paired with a descriptive message that explains what changed and why. Get this right consistently, and your commit history becomes a powerful audit trail. Get it wrong, and you’re left staring at a list of messages like “fix stuff” and “more changes” with no idea what happened.

Let’s walk through the key concepts you need to understand.

First, atomic commits. The idea here is simple — one logical change per commit. Not a dozen things bundled together, just one. That way, if something breaks, you can reverse that single commit without pulling apart unrelated work at the same time.

Next, the staging area. Before you commit anything, you use git add to select exactly which changes go into that next commit. Think of it like packing a box before sealing it — you choose what goes in before you close the lid.

Then there’s amending. If you’ve just made a commit and you realise you forgot something or your message has a typo, you can amend that last commit to fix it. Important caveat though — you can only safely do this before you’ve pushed the commit to a shared remote. Once it’s out there, amending rewrites history and causes problems for everyone else on the team.

When you want to look back at what’s happened, you use git log. This shows you all your commits in chronological order, and every single commit has a unique identifier — a SHA-1 hash — which is that long string of letters and numbers you see next to each entry. That hash is how git tracks and references specific points in your history.

Finally, rebasing. This is a more advanced technique that lets you reorder or combine commits. It’s useful for cleaning up a messy local history before you share your work, so the final record looks logical and easy to follow.

Now let’s talk about the NZRT commit message format, because at NZRT this isn’t optional — every commit needs to follow the standard structure.

The format has four parts. You start with a type and a scope in parentheses, followed by a colon and a short subject line. Then you leave a blank line and write a body with more detail. Finally, you add a footer for things like issue references or breaking change notices.

For the type, you choose from a fixed list: feat for a new feature, fix for a bug fix, docs for documentation changes, style for formatting that doesn’t affect logic, refactor for code restructuring, perf for performance improvements, test for adding or updating tests, and chore for maintenance tasks like dependency updates.

The scope is the area of the codebase you’re touching — so something like dolibarr, wp-sync, or scripts depending on what you’re working on.

The subject line should be written in present tense and kept under fifty characters. Think of it like the subject line of an email — short, specific, and descriptive.

To make this concrete, here’s what a real NZRT commit message looks like in plain language. The type is feat, the scope is wp-sync, and the subject says “add product comparison module.” The body then explains that this implements a side-by-side product comparison feature for customers, adds a new shortcode for easy integration, and includes the CSS and JavaScript needed to make it work. The footer closes issue number forty-two.

That structure means anyone reading the history six months from now immediately knows what changed, why it changed, and which issue it was tied to.

In the NZRT context specifically, the Dolibarr custom repository maintains a detailed commit history and every commit needs to be production-ready before it’s pushed. Daily pushes are the norm, so keeping each commit clean and well-described is critical for the team to audit who changed what and when.

There are three git commands worth knowing for navigating that history. The first shows you the last twenty commits in a compact, one-line-per-commit view. The second lets you look at the full details of any specific commit by passing in its hash. The third shows you the full change history for a single file — so if you want to trace every modification ever made to a particular script or config file, that’s the command you reach for.

Taken together, clean atomic commits with descriptive messages, the NZRT type-scope-subject format, and regular use of git log turn your repository’s history into something genuinely useful — not just a backup, but a clear record of your project’s evolution that anyone on the team can read and learn from.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Deployment Pipelines

Welcome to the NZRT Wiki Podcast. Today we’re looking at 🚀 Deployment Pipelines.

If you’ve ever wondered how code travels from a developer’s laptop to a live server without breaking everything, deployment pipelines are the answer. At NZRT, these pipelines automate the process of releasing code to staging and production environments. And depending on which system you’re working with, the approach is a little different.

Let’s start with some key concepts you’ll want to understand.

First, there’s the staging environment. Think of this as a rehearsal space — it mirrors your production server so you can test changes before real users ever see them. The production environment is the live server actually serving customers. A deployment script is an automated script that pulls the latest code and restarts any services that need it. Health checks verify that a deployment actually worked — essentially asking “did everything go okay?” Rollback is your safety net: if something breaks, you revert to the previous working version.

You might also hear about blue-green deployment, where you run two identical production environments and switch traffic between them when you’re ready. Or canary deployment, where you gradually roll out a change to just a percentage of your traffic before going all in. Zero-downtime deployment means handling things like database migrations and cache updates without ever interrupting the live service.

Now let’s look at how NZRT actually deploys its two main systems.

For Dolibarr custom, the process is continuous and triggered daily. A developer creates a feature branch, runs tests, then opens a pull request to the main branch. That pull request needs at least one code review approval before it can be merged. When it’s merged — using a squash merge to keep the history clean — GitHub Actions kicks in automatically. It runs a linter to check code quality, executes tests, performs a security scan, and then deploys directly to the Dolibarr custom environment. Health checks and smoke tests confirm everything is working, and a Slack notification goes out to the team.

The standard Dolibarr deployment follows a similar flow but adds an important safety mechanism: feature flags. A developer creates a short-lived branch, ideally lasting less than three days. Any new feature is wrapped behind a feature flag that starts switched off. After tests pass and the pull request is merged, GitHub Actions runs linting, unit tests, and integration tests, then automatically deploys to production — but the feature flag stays off. The code is live but dormant.

After deployment, the team monitors error logs and performance. When they’re confident everything looks good, they enable the feature flag and monitor again for regressions. If something goes wrong, they can disable the feature flag immediately — that’s the fastest fix — or revert the commit and redeploy.

Now let’s talk about what the actual deployment script does behind the scenes. The script takes two inputs: the environment you’re targeting, either production or staging, and the version number you want to deploy. Based on those inputs, it determines which server to connect to.

It then carries out six steps over a secure connection to the target server. First, it creates a timestamped database backup, so you always have a restore point before anything changes. Second, it checks out the specified version of the code and pulls the latest files. Third, it installs PHP dependencies, skipping anything only needed for development. Fourth, it runs any database migrations that have been queued. Fifth, it flushes the cache so the server isn’t serving stale data. And sixth, it runs a health check by requesting a specific page on the server — if that request fails, the script stops immediately and reports the failure.

If you ever need to roll back, the process is straightforward. You can list all tagged releases to find the version you want to return to, then run the deploy script again pointing at that earlier version tag. If things are really urgent, you can connect directly to the server and revert the most recent commit on the spot.

That covers the full deployment pipeline picture at NZRT — from branching strategies and feature flags all the way through to the step-by-step mechanics of what happens on the server during every release.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Dolibarr Github Integration

Welcome to the NZRT Wiki Podcast. Today we’re looking at 💼 Dolibarr GitHub Integration.

So, what is this integration all about? At NZRT, Dolibarr is the ERP system — the business backbone — and GitHub is where all the code lives. This integration ties the two together in several important ways. You get automatic code deployment from GitHub straight to the Dolibarr server, product and customer data syncing between WordPress and Dolibarr, a feature flag system that lets GitHub Actions turn Dolibarr features on or off, and a full audit trail so every sync event gets logged.

Let’s start with the module structure. The custom Dolibarr code lives in a folder called dolibarr-custom. Inside that, you have a source folder containing a modules directory with three submodules. The first is wp-sync, which handles the WordPress synchronisation and contains class files for products and webhooks, an admin setup file, a triggers file, and the main module file. The second is nzrt-audit, which handles audit logging through a class called AuditLog. The third is nzrt-reports for reporting. Alongside the modules, there’s a shared functions file, a dot-env file for environment variables, and a GitHub Actions workflow file for deployment automation.

Now let’s talk about how WordPress and Dolibarr actually talk to each other. When a product is updated in WordPress, WordPress sends a webhook — essentially a POST request — to a specific endpoint on the Dolibarr server. That request carries a payload containing the event type, the product ID, the product name, the price, the SKU, any image URLs, and a sync key to verify the request is legitimate.

On the Dolibarr side, there’s a PHP handler that receives that incoming data. It reads the raw request body, decodes the JSON payload, and then verifies the request is authentic by computing a cryptographic signature using a secret key and comparing it to the signature sent in the request header. If those don’t match, the handler rejects the request immediately with an unauthorised response. If they do match, it hands the event off to the product sync class, which does the actual synchronisation work, and returns a success or failure response.

Next up is the GitHub Actions deployment workflow. This is what makes sure that whenever you push code to the main branch on GitHub, your Dolibarr customisations get deployed automatically. The workflow runs on a Linux environment and goes through several steps. First it checks out your code, then it sets up PHP version 8.1 with the MySQL, curl, and JSON extensions. After that it installs any Composer dependencies, excluding development ones, and runs your test suite. Once tests pass, it handles the actual deployment. It sets up an SSH key stored as a GitHub secret, scans the Dolibarr host to verify its fingerprint, and then copies the module files from your source folder directly to the custom modules directory on the Dolibarr server. After deploying, it clears the Dolibarr cache by removing temporary cache files over SSH. Finally, regardless of whether the deployment succeeded or failed, it sends a Slack notification so your team knows the outcome straight away.

The last piece to understand is the feature flag system. This is a lightweight way to turn functionality on or off without changing code. There’s a helper function that reads an environment variable called FEATURE FLAGS, which contains a JSON object — a simple list of feature names paired with true or false values. The function looks up any feature by name and returns whether it’s active. For example, the environment variable might have advanced reporting set to false, audit log set to true, and custom export set to false. In practice, code throughout the Dolibarr modules can call that function before loading a feature, so you can safely ship code that’s switched off until you’re ready.

Pulling it all together — you have GitHub as your source of truth for code, an automated pipeline that deploys and tests on every push, a webhook bridge keeping your product data in sync between WordPress and Dolibarr, and a feature flag layer giving you fine-grained control over what’s live at any given time. It’s a clean, auditable setup that keeps your ERP and your codebase tightly coordinated.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Git Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at 📚 Git Overview.

So, what is Git? At its core, Git is a distributed version control system. What that means in practice is that it tracks changes to your files over time, lets you collaborate with other developers, and keeps a complete history of your entire project. Every time something changes, Git knows about it. And at NZRT, Git is the foundation that holds all of our development workflows together, particularly around Dolibarr customisations and the supporting tools that sit alongside them.

Let’s start with the key concepts you need to understand before anything else.

First, distributed version control. Because Git is distributed, every developer working on a project has a full copy of the repository, including its entire history. You’re not dependent on a central server being online to work. You have everything you need locally.

Next up are commits. Think of a commit as a snapshot of your code at a specific point in time. Each one comes with a descriptive message so that you and your teammates know exactly what changed and why. Good commit messages matter a lot at NZRT, and there are specific standards for how they should be written.

Then there are branches. Branches let you work on multiple features at the same time without stepping on each other’s toes. You spin up a new branch, do your work in isolation, and bring it back into the main codebase when it’s ready.

The staging area is something that trips people up early on. Before you actually commit your changes, you stage them. This is your chance to review what you’re about to lock in. You choose what goes into the commit rather than just bundling everything together automatically.

You’ll also encounter merge conflicts at some point. These happen when two branches have both made changes to the same piece of code. Git can’t automatically decide which version wins, so it flags it and asks you to resolve it manually.

And finally, tags. Tags are named snapshots that mark important moments in a project’s life, things like a version one release or a stable milestone. You might see labels like v one point zero point zero attached to specific commits.

Now, how does all of this work specifically at NZRT? The main repository you’ll be working with is Dolibarr-Custom, which lives on the NZRT GitHub account and contains all of the ERP customisations. The team uses trunk-based development with feature flags, which means the main branch is always the source of truth, and new work branches off it, gets reviewed, and comes back in cleanly.

Every commit must follow the NZRT Commit Message Standards format, so make sure you’re familiar with that before you start pushing code. Once your changes are ready, you push your branch to GitHub, open a pull request, and a peer reviews it before anything gets merged. GitHub Actions then automatically runs linting and tests on every pull request, so quality checks happen without anyone having to think about it.

For your local development environment, NZRT uses Laragon, which gives you PHP version eight and above, MySQL, and Python three point thirteen all running together. Deployment flows from GitHub through GitHub Actions and out to the production server.

Now let’s walk through what a typical Git workflow looks like at NZRT. There’s a code example in the wiki that shows the full sequence, so let me walk you through what it’s doing in plain English.

You start by cloning the Dolibarr-Custom repository from GitHub down to your local machine. That pulls down all the code and history. Then you navigate into that project folder. From there, you switch to the main branch and pull the very latest changes from the remote, making sure you’re starting from an up-to-date base.

Next, you create a new branch for the feature you’re about to work on. The branch name starts with the word feature followed by a short description of what you’re building. That naming convention is intentional and makes it easy for the team to see what’s in progress at a glance.

After you’ve made your changes, you stage everything you want to include in your commit. Then you write a commit message. In the example, the message starts with the word feat followed by a colon and a short description. That’s the conventional commits format that NZRT follows. Finally, you push that feature branch back up to GitHub, where it becomes available for review.

And that’s the loop. Clone, branch, code, stage, commit, push, review, merge. Once you’re comfortable with that rhythm, Git starts to feel like a very natural part of how you work rather than an extra layer of complexity.

If you want to go deeper, the wiki has related notes on Repository Structure, Branching Strategy, Commits and History, and a Git Commands Cheatsheet. Those are great next stops after this overview.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Actions Workflows

Welcome to the NZRT Wiki Podcast. Today we’re looking at ⚙️ GitHub Actions Workflows.

If you’ve ever pushed code to a GitHub repository and wondered how tests run automatically, or how your changes end up on a server without anyone manually doing it — that’s GitHub Actions at work. At NZRT, we use it across our repositories to handle linting, testing, and deployment in a consistent, automated way.

So let’s start with the basics. A GitHub Actions workflow is a configuration file written in YAML, and it lives inside a folder called dot-github slash workflows in your repository. The structure of one of these files is straightforward. You give the workflow a name, you tell it what events should trigger it — things like a push to a branch, a pull request, or a scheduled time — and then you define one or more jobs. Each job runs on a virtual machine, typically the latest version of Ubuntu, and contains a series of steps that run in order.

Now let’s look at the main workflows NZRT uses.

The first is the deploy workflow for the Dolibarr custom project. This one triggers in two situations: when you push to either the develop or main branches, or when a release is published. It has three jobs that can run depending on the context.

The first job is called lint-and-test, and it runs every time. It sets up a PHP 8.1 environment with the extensions needed for the project, installs dependencies using Composer, then runs three checks in sequence. First it scans every PHP file in the WordPress content folder to make sure the syntax is valid. Then it runs a security scan. Then it runs the full test suite using PHPUnit. If any of those steps fail, the whole workflow stops there.

The second job, deploy to staging, only runs if the branch being pushed is the develop branch, and it only starts if lint-and-test passed. It connects to the staging server over SSH using a deploy key stored as a secret, pulls the latest code, and flushes the WordPress cache. When it’s done — whether it succeeded or failed — it sends a Slack notification with the status, who triggered it, and what repository it was for.

The third job, deploy to production, works differently. It only runs when you push a version tag — something like v one-point-two-point-zero. It uses GitHub’s deployment API to register a formal deployment event, then connects to the production server via SSH, checks out the tagged version, pulls it down, flushes the cache, and exports a database backup before anything changes. After deploying, it runs two health checks against the live site to confirm it’s responding. Then it sends a Slack notification with the version number and status.

The second workflow is the Dolibarr CI workflow. This one runs on every push and every pull request — so it’s always watching. It has two jobs. The first is a linting job that checks your PHP code against the PSR12 coding standard and runs static analysis to catch type errors and other issues before they become bugs. The second job is a test job, and this one spins up an actual MySQL 8 database as part of the runner environment — it even has a health check to make sure the database is ready before the tests start. Then it installs dependencies and runs the test suite against that live database connection.

The third workflow is the NZRT Scripts deploy workflow. This one is simpler. Any time you push to the main branch of the NZRT-Scripts repository, it SSHes into the cPanel server, goes to the scripts folder, pulls the latest code from the main branch, and makes sure all shell scripts are marked as executable. Then it verifies the deploy worked by logging the most recent commit on the server.

Now, all three of these workflows rely on secrets — sensitive values like SSH keys, usernames, and ports that you never want to hard-code into a file. NZRT manages these at the organisation level in GitHub, which means they’re available to every repository without you needing to set them up repo by repo. There are three org-level secrets you need to know about. The deploy key is the SSH private key used to authenticate with the server. The deploy user is the cPanel SSH username. And the deploy port is the port number used for SSH connections. All three are stored in the organisation secrets settings page on GitHub.

If you want to dig deeper, the wiki has related notes on CI CD Overview, Automated Testing, Deployment Pipelines, and the Git Deployment page which covers cPanel-specific git setup.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Actions

Welcome to the NZRT Wiki Podcast. Today we’re looking at ⚙️ GitHub Actions.

So what is GitHub Actions? Put simply, it’s the built-in automation platform that lives right inside GitHub. When you push code, open a pull request, cut a release, or even just trigger something manually, GitHub Actions can spring into life and do things for you automatically. We’re talking running tests, checking code quality, building your project, and deploying it to a server — all without you having to lift a finger after the initial setup. At NZRT, we use it across our repositories to keep things consistent and reduce the risk of human error slipping into production.

Let’s walk through the core concepts you need to understand before diving into any of this.

First, there’s the workflow. A workflow is a YAML configuration file that you place inside a special folder in your repository — specifically a folder called dot-github, then workflows inside that. Each file in there defines a piece of automation: what triggers it, what it does, and how it does it.

Speaking of triggers — those are the events that kick a workflow off. You can trigger on a push to a branch, on a pull request being opened, on a schedule like a nightly cron job, on a release being published, or manually via something called a workflow dispatch. That last one is useful when you want a button you can press yourself from the GitHub interface.

Inside a workflow, you have jobs. Jobs are the big chunks of work. By default they run in parallel, but you can chain them so one waits for another to finish. Inside each job, you have steps — these are the individual commands or actions that run in sequence. Think of a job as a recipe, and the steps as each line in that recipe.

Now, actions themselves — with a lowercase a — are reusable blocks of code you can drop into your steps. A huge library of these exists on the GitHub Marketplace. Instead of writing a script to install a specific version of PHP or Node, you just pull in an action someone else has already written and maintained. It saves a lot of time.

Jobs run on runners. A runner is basically a server — GitHub provides hosted ones running Ubuntu, Windows, or macOS, or you can bring your own self-hosted runner if you need more control or specific hardware.

Two more important concepts: artifacts and secrets. Artifacts are outputs from your build — compiled files, test reports, things like that — which you can save and either download later or pass between jobs. Secrets are encrypted environment variables where you store sensitive things like SSH keys, API tokens, and passwords. You configure these in your repository settings, and then reference them safely inside your workflows without ever exposing the actual values in your code.

Now let’s look at two real examples from NZRT’s own workflows.

The first is a PHP lint check that runs on every pull request. When someone opens a pull request, GitHub spins up a fresh Ubuntu server, checks out the code from the repository, installs PHP version 8.1, and then runs a syntax check across all PHP files in the source folder. If any file has a syntax error, the job fails and the pull request gets flagged. This is a simple but powerful quality gate — it stops broken PHP from ever making it into the main branch through a pull request.

The second example is a deployment workflow that fires when a release is published. Again it starts on Ubuntu, checks out the code, and then runs a deployment step. That step does a few things in sequence: it creates an SSH configuration directory, writes a private deploy key — pulled securely from GitHub Secrets, so it’s never visible in the code — into a key file, locks down the file permissions on that key so SSH will accept it, and then connects to the production server via SSH. Once connected, it navigates to the Dolibarr custom code directory on that server and pulls the latest changes from the main branch. So publishing a release in GitHub automatically ships the code to production. Clean, auditable, and no manual SSH session required.

Those two examples give you a good feel for the range GitHub Actions covers — from lightweight code checks all the way through to full deployments. The same mental model applies regardless of complexity: define your trigger, define your jobs, break each job into steps, and use secrets to handle anything sensitive.

If you want to go deeper, the NZRT wiki has related notes on GitHub Actions Workflows, Automated Testing, and Deployment Pipelines — worth a read once you’ve got the fundamentals down.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Cli Cheatsheet

Welcome to the NZRT Wiki Podcast. Today we’re looking at 🖥️ GitHub CLI Cheatsheet.

If you’ve ever wished you could do everything GitHub-related without leaving your terminal, the GitHub CLI tool, known as gh, is exactly what you need. It lets you manage repositories, pull requests, issues, releases, and more, all from the command line.

Let’s start with getting it installed. On Windows, you can install it using either Chocolatey or winget by running the install command for GitHub dot cli. On a Mac, Homebrew handles it with a simple brew install. On Linux, you can use apt. Once installed, you can verify everything worked by checking the version. Then you authenticate by running gh auth login, which walks you through an interactive setup where you choose GitHub dot com, pick SSH or HTTPS, and generate an access token. If you already have a token in a file, you can pipe that file directly into the login command to skip the prompts.

To check your current login state, you run gh auth status. To log out, gh auth logout. Simple.

Now, working with repositories. You can clone any repo by passing the owner and repo name to gh repo clone. You can even specify a destination folder as a second argument. To view information about a repo, you use gh repo view, either for your current directory or by naming the owner and repo. Tacking on the web flag opens it straight in your browser. You can list all repos under an organisation, filter for archived ones, or cap the results with a limit flag. Creating a new repo is just gh repo create, with options to make it private and add a description. Forking works similarly with gh repo fork, and adding the clone flag pulls it down to your machine at the same time.

Pull requests are where the CLI really shines. You create one with gh pr create, and you can specify a title, a body description, a base branch, a head branch, or mark it as a draft, all as flags on that same command. To see what’s open, gh pr list, filtered by state, author, or base branch as needed. You can view a specific PR by number, check its CI status with gh pr checks, request a review, approve it, request changes with a comment, or leave a comment yourself. Merging is flexible too: you can squash, rebase, or create a standard merge commit, and you can automatically delete the branch after merging. Closing or reopening a PR is just one command each.

Issues follow the same pattern. You create them with a title, body, and labels. You list them filtered by state, assignee, or label. You view, close with an optional comment, reopen, comment on, or edit them to change titles or add and remove labels.

For GitHub Actions, gh run list shows your recent workflow runs. You can view details and logs for a specific run by its ID, download artifacts, trigger a workflow manually if it supports that, and list all available workflows in your repository.

Releases are just as straightforward. You can list them, view a specific one by tag, create a new release with a title, or let GitHub auto-generate release notes from your merged pull requests. You can mark a release as a draft or a pre-release, upload assets like zip files to an existing release, edit it later, or delete it entirely.

Branch operations in the CLI lean on the gh api command, which lets you talk directly to the GitHub REST API. You can list branches, create one by passing a reference name and a commit hash, or delete one by sending a delete request to the reference endpoint.

For discussions, you can create one with a title, body, and category, then list discussions filtering for answered or unanswered ones, or view a specific discussion by its ID.

Label management is clean: list labels, create one with a name, a hex colour code, and a description, edit an existing label, or delete it.

You can also set up aliases in your git config to shortcut common gh commands. For example, mapping pr-create to gh pr create, or status to gh pr checks, so your muscle memory works even faster.

Finally, a few handy one-liners worth knowing. You can open your current repo in the browser with a single command. You can push a branch and immediately create a pull request in one chained command. You can merge and delete the branch in one go. You can create a release from your latest git tag and auto-generate the notes. And you can list all pull requests waiting specifically for your review by searching for your username in the reviewer-requested filter.

That covers the full GitHub CLI toolkit, from setup and authentication through to repos, pull requests, issues, actions, releases, branches, labels, and discussions.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Discussions

Welcome to the NZRT Wiki Podcast. Today we’re looking at ?? GitHub Discussions.

If you’ve spent any time in GitHub, you’re probably familiar with issues and pull requests. But there’s a third space in GitHub that NZRT uses just as actively, and that’s Discussions. Think of it as the team’s open conversation floor, a place where you can ask questions, float ideas, share news, or just check in with each other, all without cluttering up the issue tracker.

So let’s talk about what GitHub Discussions actually are and how NZRT uses them.

At the heart of it, Discussions are organised into categories. NZRT uses four main ones. There’s Questions, for when you need an answer from the team. There’s Ideas, for proposing features or improvements. There’s Announcements, for sharing important updates like releases or policy changes. And there’s General, for everything else, think project updates, team celebrations, onboarding, retrospectives, that kind of thing.

One of the most useful features in the Questions category is solution marking. When someone asks a question and another team member gives a helpful answer, the original author can mark that reply as the solution. This means the next person with the same question can find the answer instantly, without reading through a whole thread.

You can also upvote discussions and individual answers. So if someone asks a question you’ve been wondering about too, or if an idea resonates with you, a quick upvote lets the team know without needing a reply.

Now let’s look at some real examples of how NZRT actually formats these discussions, and I’ll walk you through what they look like without reading out any of the formatting characters.

The first example is a question post. It opens with a clear heading asking how to run tests locally. The person explains they’re trying to set up tests for a new WordPress plugin and want to know what command to use. Then they list their environment details, which include Windows 10 with Laragon, PHP version 8.1, and WordPress version 6.1. That’s a great example of a well-structured question. You’re telling the team what you’re trying to do, why you’re stuck, and exactly what your setup looks like. That context makes it much easier for someone to give you a useful answer.

The second example is an announcement post. The heading identifies it as a release, specifically version 2.1.0 of the dolibarr-custom package going to production. It then lists what’s new, in this case a product comparison widget, an advanced reporting dashboard, and a Dolibarr inventory sync. It notes the exact date and time of deployment, names the person who deployed it, and links to the full changelog on GitHub. That’s the kind of announcement that keeps everyone aligned. Anyone who needs to know what changed and when can find it right there in the discussion.

The third example is much simpler. It shows how you’d reference a discussion from inside a pull request or an issue comment. You simply write something like “Related discussion, number 5, how to set up the development environment.” GitHub will turn that into a clickable link automatically. This is how you connect conversations across the different parts of GitHub without losing context.

Now let’s talk about best practices, because how you use Discussions matters just as much as what you post.

The most important rule is to keep Discussions and Issues separate. Discussions are for conversation. Issues are for tracked work with assignees, labels, and milestones. If an idea in Discussions gains enough traction and the team reaches consensus, you convert it into an issue so it can be planned and implemented properly. That’s the intended flow: discuss, agree, track.

Before you post a question, do a quick search. Duplicate questions slow the team down, and the answer might already be there waiting for you. When you do post, give as much context as you can, including your environment, any error messages you’ve seen, and what you’ve already tried.

Keep the tone professional. GitHub Discussions are company communication, so treat them that way. That said, you can still use emoji reactions for quick feedback. A thumbs up, a rocket, a heart, these are all valid ways to respond when you don’t need to add words.

And finally, make sure you mark solutions when you get a good answer. It’s a small action that has a big payoff for everyone who comes after you.

Discussions also connect to the broader GitHub ecosystem. They’re referenced in the Collaboration Overview and the Issues and Projects notes in the wiki, so if you want to understand how all these pieces fit together, those are worth a look.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at the GitHub Overview.

If you’ve spent any time in software development, you’ve probably heard of GitHub. But let’s make sure we’re all on the same page about what it actually is and how NZRT uses it day to day.

GitHub is a cloud-based platform built on top of Git, which is a version control system. In plain terms, that means GitHub gives you a place to store your code, track every change ever made to it, and collaborate with other people without stepping on each other’s work. It also adds a layer of DevOps tooling on top, so you can automate testing, deployment, and all sorts of other workflows right from the same platform.

Now let’s walk through the key concepts you’ll encounter when working with GitHub.

First up, you have repositories. A repository is essentially a storage container for a project. It holds all the code, all the files, and the entire history of every change ever made. Repositories can be public, meaning anyone on the internet can see them, or private, meaning only people you grant access to can view them.

Next, there are forks. When you fork a repository, you create your own independent copy of it. This is really useful if you want to experiment with changes without affecting the original project, or if you’re contributing to someone else’s work and need your own space to develop.

Then you have pull requests. This is the formal process for getting your changes reviewed before they get merged into the main codebase. You make your changes on a separate branch, open a pull request, and other team members can review the code, leave comments, and approve or request changes before anything goes live.

GitHub Actions is the built-in automation engine. You can set up workflows that trigger automatically based on events, for example when someone pushes new code, opens a pull request, or on a regular schedule. This is how you handle things like running automated tests or deploying to a server without doing it manually every time.

Issues are how GitHub handles bug tracking, feature requests, and project planning. You can label issues, assign them to people, and group them into milestones to track progress toward a goal.

Releases let you package up specific versions of your software with release notes and downloadable files, so users or other systems always know exactly what version they’re working with.

GitHub Pages is a handy feature that lets you host static websites directly from a repository. It’s commonly used for documentation sites, project landing pages, or blogs.

And finally, webhooks. A webhook is a way for GitHub to send a real-time notification to another service whenever something happens in your repository. For example, you could have GitHub notify Slack every time a pull request is opened.

Now let’s talk about how NZRT specifically uses GitHub. All NZRT repositories live under the organisation at github dot com slash nzrtnetwork. The general approach is to keep documentation public so it’s accessible, while production code stays in private repositories.

For authentication, NZRT uses SSH keys alongside personal access tokens for command-line work. The preferred tool for local automation and CLI tasks is the GitHub CLI, known as gh. So if you’re scripting something GitHub-related at NZRT, that’s the channel to use.

GitHub Secrets are used to store sensitive information like API tokens and deployment credentials, keeping them out of the codebase but still available to automated workflows.

On the integration side, NZRT has connected GitHub to Slack notifications and email alerts, so the right people hear about pull request reviews and other key events without having to check GitHub manually.

One workflow worth highlighting is the Dolibarr-Custom repository, which is actively monitored by GitHub Actions. That means changes there can trigger automated processes, which is a good example of how GitHub sits at the centre of NZRT’s development pipeline rather than just being a place to store code.

So to pull it all together, GitHub at NZRT is not just a code host. It’s the central coordination point for version control, code review, automation, and integration with the wider toolset. Whether you’re pushing a small fix or managing a full deployment pipeline, GitHub is where it all comes together.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Packages

Welcome to the NZRT Wiki Podcast. Today we’re looking at GitHub Packages.

So what is GitHub Packages? Put simply, it’s a package registry built right into GitHub. Instead of relying on a completely separate service to host your libraries and containers, you can publish and install packages directly from the same platform where your code already lives. That tight integration with GitHub repositories, GitHub Actions, and GitHub authentication is what makes it particularly useful for teams already working in that ecosystem.

Let’s talk about what kinds of packages GitHub Packages actually supports, because it covers a lot of ground. If you’re working with JavaScript, you can use it as an npm registry. If you’re in the Java world, it supports Maven and Gradle. For dotnet developers, there’s NuGet. If you’re building and deploying containers, Docker images are supported. And if you’re in the Ruby ecosystem, RubyGems are covered too. So whatever stack you’re working with, there’s a good chance GitHub Packages has you covered.

Now, a few key concepts worth understanding before you dive in. First is scoping. When you publish a package, you namespace it to either your organisation or your user account. For NZRT, that means packages are published under the nzrtnetwork organisation scope. This keeps things organised and makes it clear who owns and maintains a given package.

Next is visibility. Packages can be either public or private, just like repositories. Public packages can be installed by anyone, while private packages require authentication and appropriate access.

Speaking of authentication, you’ll need a GitHub token to both publish and install packages. This ties into GitHub’s permissions model, where package access is inherited from repository access. If you have read access to a repository, you can install its packages. If you have write access, you can publish.

And then there’s CI and CD integration, which is where things get really powerful. GitHub Actions can automatically publish packages as part of your workflow, so every time you push a release, your package is built and published without any manual steps.

Let me walk you through how NZRT handles npm package publishing via GitHub Actions. The workflow step is straightforward. There’s an action step that runs npm publish, and it passes in an environment variable called NODE AUTH TOKEN, which is automatically set to the built-in GitHub token that Actions provides. You don’t need to manually create or store that token — GitHub injects it securely at runtime. That’s the publish side sorted.

On the install side, it’s just as clean. If you want to install one of NZRT’s npm packages from the command line, you run npm install followed by the package name under the nzrtnetwork scope. For example, there’s a package called wp-sync-sdk published under that scope, and installing it looks exactly like any other npm install command — the only difference is the scoped name tells npm to look at the GitHub registry rather than the default public registry.

Now let’s go through the four supported registry types NZRT is using, because it’s worth knowing what’s available. First, Docker, which is used for container images. The NZRT Docker images are hosted on the GitHub Container Registry, and there’s a WordPress base image there as an example. Second, Maven, which handles Java libraries. NZRT uses this for a Dolibarr API library under the co.nzrt group. Third, npm, which as we just covered is for JavaScript libraries. The nzrt-utils package is one example published under the nzrtnetwork scope. And fourth, NuGet, which is for dotnet packages. NZRT has a Dolibarr integration package published there.

So to bring it all together — GitHub Packages gives you a single, integrated place to host your libraries and containers, authenticate using the same tokens and permissions you already have set up in GitHub, and automate publishing through Actions. For a team like NZRT that’s already leaning heavily on the GitHub ecosystem, it removes a lot of friction that comes with managing separate registries for different package types.

If you want to go deeper, the related wiki notes on GitHub Overview and GitHub Actions are worth checking out — they’ll give you the broader picture of how all these pieces connect.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Github Pages

Welcome to the NZRT Wiki Podcast. Today we’re looking at ?? GitHub Pages.

So what exactly is GitHub Pages? Put simply, it’s a feature built right into GitHub that lets you host a static website directly from one of your repositories. You don’t need a separate server, you don’t need to manage hosting accounts, and you don’t need to worry about uptime. GitHub handles all of that for you. It’s particularly well suited for project documentation, development blogs, and public portfolios.

Let’s start with the concept of a source. When you set up GitHub Pages, you tell GitHub where to find your website content. You have a few options here. You can point it at a folder called docs inside your main branch, you can use your main branch directly, or you can use a dedicated branch called gh-pages. Whichever you choose, that’s where GitHub looks when it builds your site.

Now, speaking of building, GitHub Pages has a built-in static site generator called Jekyll. Jekyll is what takes your Markdown files and turns them into proper HTML pages. So if you’re writing documentation in Markdown, you don’t have to manually convert anything. You just write your content, push it to your repository, and Jekyll does the rest. You can also skip Jekyll entirely if you prefer to write your own HTML directly.

One of the nicest things about GitHub Pages is that deployment is fully automatic. Every time you push an update to your source branch, GitHub picks it up and rebuilds your site. You do need to factor in a short wait though. Build times typically run somewhere between one and five minutes, so don’t expect changes to appear instantly. Give it a few minutes and then refresh.

Let’s talk about your web address. By default, your site will be available at a github dot io URL based on your username and repository name. But you can also connect a custom domain if you want something more professional. To do that, you point your domain’s DNS records to GitHub Pages’ IP addresses, then configure the custom domain inside your repository settings. Once that’s done, your site is reachable at whatever domain you’ve set up. And on the security side, GitHub Pages automatically provides SSL certificates for github dot io domains, so you get HTTPS without any extra setup.

For NZRT specifically, GitHub Pages opens up some interesting possibilities. There are three potential sites worth thinking about. First, an API documentation site, which would sit at api dot nzrt dot io and could be auto-generated directly from the codebase. Second, an internal docs and guides site at docs dot nzrt dot io. And third, a development blog at blog dot nzrt dot io. All three of these could be maintained as GitHub repositories and deployed automatically whenever content is updated.

So how do you actually get started? There are five steps. First, you go into your repository’s settings on GitHub and enable the GitHub Pages feature. Second, you select your source, so that’s either your main branch with a docs folder, or the gh-pages branch. Third, you either pick one of GitHub’s built-in themes or supply your own custom HTML. Fourth, once it’s live, you access it at the github dot io URL that GitHub assigns you, or at your custom domain if you’ve set one up. And fifth, from that point on, any time you push a change to your source branch, the site redeploys automatically. You don’t need to do anything else.

That’s the core of GitHub Pages. It’s a lightweight, low-maintenance way to get a professional-looking static site live quickly, backed by the same version control workflow you’re already using for your code. For a consultancy like NZRT, it makes a lot of sense as a way to publish API docs or internal guides without adding another tool to the stack.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Gitignore Templates

Welcome to the NZRT Wiki Podcast. Today we’re looking at .gitignore Templates.

So, what is a .gitignore file? Put simply, it is a file you place in your Git repository that tells Git which files and folders to leave alone — to never track, never commit, and never push. At NZRT, every repository uses a .gitignore tailored to the language or framework being used, and today we are going to walk through all of them.

Let us start with WordPress. The WordPress .gitignore is one of the more detailed ones, because WordPress installations have a lot of moving parts you do not want in version control. It excludes the WordPress core folders and files — the admin panel, the includes directory, and the main PHP files — since those are installed separately. It also excludes your WordPress configuration files, including any environment files, because those contain sensitive local settings. User uploads are excluded too, since binary media files have no place in a code repository. Here is the interesting part: all plugins and all themes are excluded by default, except for the ones NZRT actually builds and maintains — the custom sync plugin and the custom NZRT theme are specifically allowed back in. Third-party packages, IDE configuration folders, and common operating system files like the Mac finder metadata file and the Windows thumbnail database file are also excluded.

Next up is PHP. The PHP template is simpler. It excludes your vendor dependencies folder, environment files, IDE settings, test coverage reports, log files, temporary files, and your build output folders. If you are building a standalone PHP project or a Dolibarr module, this is your starting point.

For Node.js and JavaScript projects, the template covers the node modules folder — which you never want in Git because it can contain thousands of files — along with lock files for npm, Yarn, and pnpm. Build output directories, test coverage, log files, caches, and framework-specific folders like the Next.js output directory are all excluded.

For Python, the list is longer because Python generates quite a few artefacts. Virtual environment folders are excluded — these are your isolated Python installations and should never be committed. Compiled Python files and bytecode caches are excluded. Distribution and packaging folders are excluded. Test tooling outputs, IDE settings, environment files, log files, and local database files like SQLite databases round out the list.

The Docker template is short and focused. It excludes Docker secret files, any override files for Docker Compose — which are typically used for local development overrides — and log files.

There are also two cross-language sections. One covers compiled binaries and executables: things like Windows DLL files, Mac dynamic libraries, Linux shared object files, and compiled object files. These are outputs of a build process and should never live in source control. The other covers database exports: SQL dump files, compressed SQL files, and SQLite database files. Importantly, there is an exception carved out — SQL files inside a migrations folder are allowed, because those are intentional schema version files you do want to track.

The secrets and credentials section is one of the most important. It excludes entire folders like a secrets directory or private directory, SSH key files and certificate files, credential JSON files, token files, and all environment configuration files. There is one deliberate exception: files named with the word example are allowed through, so you can commit an example key file as a template for other developers to follow.

All of these patterns are combined into the NZRT Standard .gitignore, which is the catch-all template used across repositories. It brings together environment and secrets exclusions, dependency folders for both PHP and Node, build and distribution output, logs, test coverage, IDE files, operating system noise, WordPress-specific paths, Python virtual environments, and temporary files. If you are starting a new NZRT repository and you are not sure which template to use, start here.

Finally, let us talk about verifying and maintaining your .gitignore. There are a few commands worth knowing. You can ask Git to explain exactly why a particular file is being ignored, and it will tell you which rule in which .gitignore file is responsible. You can also do a dry run that lists everything Git would remove if you cleaned untracked files — useful for checking your rules are working without actually deleting anything. If you need to force-add a file that is being ignored, you can override the ignore rule for that one file. And if a file is already being ignored but it is already tracked by Git — meaning it was committed before the rule existed — you can remove it from Git’s tracking without deleting it from disk.

On that last point: if you add new rules to an existing repository, files that were already committed will not automatically be excluded. You need to remove everything from Git’s cache, re-add all files so Git picks up the new rules, and then commit that change. A commit message like “chore: update .gitignore” is the conventional way to label that housekeeping commit.

That covers the full set of .gitignore templates NZRT uses across its repositories, why each section exists, and how to verify things are working correctly.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Integrations Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at GitHub Integrations Overview.

If you’ve ever wondered how GitHub connects to all the other tools in your development workflow, this episode is for you. GitHub doesn’t just sit on its own as a code repository. It’s designed to talk to a wide range of external services, and understanding how those connections work will help you make sense of how NZRT’s systems stay in sync.

Let’s start with the big picture. There are a few different ways GitHub can integrate with other tools, and each one works a little differently depending on what you need.

First up, you have webhooks. Think of a webhook as GitHub tapping another service on the shoulder the moment something happens. When a developer pushes code, opens a pull request, or publishes a release, GitHub sends a real-time notification to an external service of your choice. That could be Slack, Discord, or even a custom server you’ve built yourself. The notification arrives as an HTTP POST request, which means GitHub is essentially packaging up the event details and delivering them straight to wherever you’re listening.

Next, there are OAuth Apps. These are third-party applications that can access your GitHub data, but only after a user explicitly authorises them. You’ve probably seen this pattern before when a website asks you to sign in with GitHub and then lists what permissions it’s requesting. That’s OAuth in action.

Then you have GitHub Apps, which are a more modern and fine-grained option. Instead of acting on behalf of a user, a GitHub App operates with its own identity and can be granted very specific permissions over your repositories. This makes them more suitable for automation and backend tooling.

There’s also the GitHub Marketplace, which is an official catalogue of integrations covering things like continuous integration and deployment, security scanning, and project management. And finally, GitHub supports status checks, which let external services report back on whether a pull request is safe to merge. If your test suite fails, for example, the status check can actually block the merge until things are fixed.

Now let’s talk about what NZRT is actually using. There are six services in the current integration picture. Starting with the active ones, you have the WordPress GitHub Integration, which handles product synchronisation and deployment. Alongside that is the Dolibarr GitHub Integration, which keeps the ERP system in sync and also handles deployment. Slack is also active, receiving build notifications and alerts. And VS Code connects directly to GitHub, giving developers an IDE integration that lets them work with repositories without leaving their editor.

Two more services are planned but not yet active. Codecov will handle code coverage reporting, giving the team visibility into how much of the codebase is covered by tests. And DataDog will come in for performance monitoring once it’s set up.

Now let’s look at the types of events that GitHub sends out via webhooks, because understanding these helps you know what can trigger activity in those connected services.

There are six common event types NZRT works with. The first is a push event, which fires whenever new commits land on any branch. The second is a pull request event, and this one is quite broad. It triggers when a pull request is opened, when new commits are added to it, when it’s reopened after being closed, when it’s closed without merging, and when it’s actually merged. So there’s a lot of useful information flowing through that single event type.

The third event is a release event, which fires when a release is published. This is useful for triggering deployment pipelines or notifying the team that a new version is available. Fourth is the issues event, which covers when an issue is opened, closed, or labelled. Fifth is the issue comment event, which triggers whenever a comment is added to an issue. And sixth is the workflow run event, which fires when a GitHub Actions workflow finishes. This is particularly useful if you want to notify Slack, for example, whether your automated build passed or failed.

If you want to go deeper on any of the specific integrations mentioned today, there are related notes covering the WordPress GitHub Integration, the Dolibarr GitHub Integration, the VS Code and GitHub setup, and GitHub Actions. Each of those gives you a much more detailed look at how those individual connections are configured and maintained within the NZRT environment.

So to bring it all together, GitHub’s integration layer is what turns a code repository into a connected part of your broader development and operations ecosystem. Webhooks push events out in real time, OAuth and GitHub Apps control how external tools access your data, the Marketplace gives you off-the-shelf options, and status checks help enforce quality gates on your pull requests. NZRT is actively using several of these today and has more on the roadmap.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Issues Projects

Welcome to the NZRT Wiki Podcast. Today we’re looking at ?? Issues & Projects.

If you’ve ever wanted a way to track bugs, plan features, and keep your development work organised in one place, GitHub Issues and Projects are exactly what you need. Let’s walk through how they work and how NZRT uses them day to day.

So, what is a GitHub Issue? Think of it as a conversation-backed task card. You create one with a title, a description, and a few extra details, and from that point on it becomes the single place where everything related to that task lives. Issues come in a few flavours at NZRT. You might open one for a bug someone found, a new feature the team wants to build, or a piece of documentation that needs writing. The type of issue is communicated through labels. Labels are just tags you attach to an issue to categorise it. You might have labels for priority, for which system is affected, for which team owns it, or for where it sits in the process.

Alongside labels, you have milestones. A milestone groups a set of issues together under a shared goal, like a release or a sprint. When you look at a milestone, you can see at a glance how many issues are closed versus still open, which gives you a quick health check on whether you’re on track. Then there are assignees, which is simply the person or people responsible for getting that issue done.

Now, one of the most useful things you can do with issues is link them directly to your code. When you’re writing a commit message or describing a pull request, you can reference an issue by its number, and if you use the word “Closes” before that number, GitHub will automatically close the issue the moment that pull request is merged. This keeps your board clean without any manual housekeeping.

To make sure issues are reported consistently, NZRT uses issue templates. Templates are pre-filled forms that guide whoever is opening the issue through what information to include. Let’s look at the two main ones.

The bug report template asks you to fill in four things. First, a brief description of what the bug is. Second, the steps to reproduce it, written out as a numbered sequence so someone else can follow along and see the same problem. Third, what you expected to happen, and fourth, what actually happened instead. There’s also a section for environment details, things like which browser you’re using, which version of PHP is running, what your Laragon environment looks like, and which versions of WordPress or Dolibarr are involved. That context is often what makes the difference between a bug that gets fixed quickly and one that takes days to pin down.

The feature request template is a bit different. It starts with a description of the feature itself, then asks you to explain the use case, meaning why this feature is actually needed and what problem it solves. Finally, there’s an acceptance criteria section where you list out the specific conditions that need to be true for the feature to be considered complete. This is really valuable because it means everyone, developers, testers, and stakeholders, agrees upfront on what done actually looks like.

Now let’s talk about GitHub Projects. Where issues are the individual task cards, a Project is the board that holds them all. NZRT uses a board called the Dolibarr-Custom Board, and it’s organised into six columns that represent the life of a piece of work from start to finish. Something lands in Backlog when it’s identified but not yet started. It moves to Design when it’s in the design review stage. Once someone picks it up and starts building, it moves to Development. From there it goes to Testing, which is your QA phase. Once testing passes, it moves to Deployment, meaning it’s ready to go live. And finally, when it’s out in the world, it lands in Done.

Projects also support automation, so you can set rules that move cards between columns automatically based on events, like an issue being closed or a pull request being merged. That saves a lot of manual drag-and-drop work and keeps the board accurate without relying on everyone to remember to update it.

If you want to dig deeper into the GitHub ecosystem, this topic connects closely with the GitHub Overview, Pull Requests, and Collaboration Overview pages in the wiki. Those will give you more context on how issues and projects fit into the wider workflow of code review and team collaboration at NZRT.

In short, Issues give you a structured, consistent way to capture and track work, and Projects give you the visual layer to see how all that work is progressing. Together they make it a lot easier to stay on top of what’s happening across your repositories without things slipping through the cracks.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Merging Rebasing

Welcome to the NZRT Wiki Podcast. Today we’re looking at Git Merging and Rebasing.

If you’ve ever worked on a team codebase, you’ve probably hit the moment where two people have been working on the same project at the same time, and now you need to bring that work together. That’s exactly what merging and rebasing are for — and understanding when to use each one makes a real difference to how clean and manageable your code history stays.

Let’s start with the basics. A merge is when Git takes two branches and combines them into one. The most common type is called a merge commit — Git creates a brand new commit that joins the two branches together, and crucially, it keeps the full history of both. You can see exactly what happened and when. There’s also something called a fast-forward merge, which only happens when there’s no divergence between branches — Git just moves the pointer forward in a straight line, keeping everything linear without needing an extra commit.

Rebasing works differently. Instead of joining branches together, rebasing takes your commits and replays them on top of a new base point. The result is a much cleaner, linear history — it looks like everything happened in a straight line, even if the work was happening in parallel. The trade-off is that rebasing rewrites history, which means you need to be careful about using it on shared branches.

Then there are merge conflicts. These happen when the same section of code has been changed in both branches, and Git can’t figure out which version to keep. When that happens, Git adds conflict markers directly into the file. You’ll see a section marked as coming from your current branch, a dividing line, and then the incoming changes below. You have to open the file, read both versions, decide what the final code should look like, and save it manually.

Another strategy worth knowing is a squash merge. Instead of bringing in every individual commit from a feature branch, squash merge collapses all of those commits into a single one. This keeps your main branch history very tidy — one feature, one commit.

Now, how does NZRT actually handle this? For the Dolibarr Custom project, the approach is squash merges into main, following what’s called a trunk-based development model. Before any merge happens, the branch gets rebased so that the history is perfectly linear. This makes rollbacks much simpler — if something goes wrong after a release, you can pinpoint exactly which change to undo.

Importantly, all of this happens through GitHub’s pull request interface, not the command line. You raise a PR, get it approved, and hit the merge button. The squash and rebase settings are configured at the repository level, so the right strategy is applied automatically.

Let’s talk through what that looks like in practice. Imagine you’ve finished a feature branch. First, you switch to the develop branch and run a squash merge of your feature branch into it. That collapses all your feature commits into one clean commit, which you then label with a meaningful message like “feat: my feature.” Before that merge, if you want to avoid any merge commits at all, you rebase your branch on top of develop first, then use a fast-forward-only merge. Fast-forward-only means Git will refuse to merge if it can’t do it in a straight line — a useful safety check.

To bring it all together: use merge commits when you want to preserve the full history of how branches came together. Use rebase when you want a clean, linear history before merging. Use squash merge when you want one tidy commit per feature on your main branch. And always resolve conflicts carefully, reading both sides before deciding what stays.

At NZRT, the decision is already made for you on Dolibarr Custom — squash and linear, always via GitHub. But understanding the mechanics underneath means you’ll know exactly what’s happening when you click that merge button.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Nzrt Repositories Overview

Welcome to the NZRT Wiki Podcast. Today we’re looking at NZRT Repositories Overview.

Let’s set the scene. NZRT maintains a portfolio of GitHub repositories, and each one has a clear purpose, an assigned owner, and a deployment path. All of these repositories are cloned locally on the development machine under a single parent folder, and there’s a home file in that folder that gives you a full directory index whenever you need it.

One important thing to note upfront: back in May 2026, the entire repository structure was reorganised. Some older named repositories and a legacy scripts repo were dissolved, and everything was consolidated into what are called service-code repositories — one per NZRT system. So if you’re familiar with the old layout, things have moved.

Before diving into the individual repos, let’s cover three key concepts.

First, ownership. Every repository is assigned to a specific NZRT role. You’ll encounter codes like xc, fin, pam, and aba — these represent the team members and agents responsible for each repo’s content.

Second, the branch model. NZRT uses trunk-based development, meaning the main branch always reflects the current state of the system. There are no long-lived feature branches to track.

Third, access control. The GitHub organisation admin is xc. Agents don’t hold their own GitHub personal access tokens, so all GitHub operations run through xc.

Now let’s walk through the repository portfolio. There are thirteen repositories in total, and each one has a name, a visibility setting of either public or private, a primary technology, an owner, a service code, a local path, and a link on GitHub. Let me take you through the key ones.

Starting with 000AGT — this is the AI agents framework. It’s private, written in Python, and owned jointly by xc and cla. You’ll find the run scripts, the core agent file, and the tools folder here.

000API is the x402 Knowledge Base API — a public Python Flask application owned by xc. This one actually deploys to production.

000CLA is public, written in Markdown, and owned by xc. It holds Claude and cla agent configuration.

000CPL is private, uses Python and Bash, and is owned by xc. It contains cPanel scripts and deploy configuration, and it also has an automated deployment pipeline.

000DOL is private, uses Python and PHP, and is owned by fin. This repo covers Dolibarr customisations — including modules, triggers, and custom PHP.

000FLA is public and Python-based, owned by xc — that’s the Flarum forum configuration and plugins.

000NCL is public, Python, owned by xc — Nextcloud configuration and apps.

000NCS is private, Python, owned by xc — the NZRT Charitable Services site and configuration.

000OBS is public, Markdown, owned by xc — Obsidian vault configuration.

000TOG is private, Python, and owned by aba — the TOGAF documentation repository.

000WIN is private, uses both PowerShell and Python, and is owned by xc — Windows tooling and scripts.

000WOR is private, Python, owned by pam — WordPress theme, plugins, and custom code.

And finally, the dot-github repository — that’s the public org profile, written in Markdown, owned by xc, and not cloned locally.

Now let’s look at deployment pipelines. Most repositories don’t have automated continuous deployment — they contain scripts or templates that are deployed manually as needed. But two repos do have pipelines.

000API pushes from main through GitHub Actions, which triggers a cPanel deployment. The Flask application ends up running live at the API subdomain for nzrtnetwork dot com.

000CPL also pushes from main through GitHub Actions, but it uses cPanel’s built-in Git Version Control feature to deploy scripts into a dedicated scripts folder on the server.

The dot-github repository is a static organisation profile with no deployment involved at all.

That covers the full picture of how NZRT’s repositories are structured — what each one is for, who owns it, whether it’s public or private, and how the ones that do deploy actually get shipped. It’s a clean one-system-one-repo model, which makes it straightforward to know exactly where to look whenever you need to make a change.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Pull Requests

Welcome to the NZRT Wiki Podcast. Today we’re looking at Pull Requests.

If you’ve ever worked on a codebase with other developers, you’ve probably come across pull requests. But what exactly are they, and how do they work at NZRT? Let’s walk through everything you need to know.

A pull request — or PR for short — is the main way code changes get reviewed and merged into a shared codebase on GitHub. When you’ve been working on a feature or a fix in your own branch, a pull request is how you say “hey, I’ve got some changes here — can someone check them over before we bring them in?” It creates a structured, documented process around that conversation.

When you open a PR, a few things happen automatically. First, GitHub shows a visual diff — that’s a line-by-line comparison of everything you’ve changed. Anyone reviewing can see exactly what was added, removed, or modified. Second, all the commits you made on your feature branch are listed, so reviewers can follow the history of your work. Third, GitHub Actions kicks off — those are automated workflows that run checks like linting, testing, and security scans. These have to pass before the PR can be merged.

Then comes the human part. One or two of your peers — depending on how the repository is set up — will review your code. They can leave comments, ask questions, or request changes. If changes are needed, you push additional commits to address the feedback, and those appear in the PR automatically. Once a reviewer is satisfied, they approve, and a maintainer can merge it in.

Let’s talk about how NZRT specifically handles this. It follows a ten-step flow. You start by creating a feature branch with a descriptive name. You make your changes and commit them with clear messages. Then you push that branch up to GitHub and open the pull request with a title and description. You wait for GitHub Actions to pass — that covers linting, testing, and a security scan. Then you request a review from one or two developers. You address any feedback, push more commits if needed, get an approval, and finally a maintainer merges the PR — usually using a squash merge into the develop branch. After that, the branch is automatically deleted, which keeps things tidy.

Now let’s cover PR title format. The title follows a short, structured pattern. You start with a type — for example, feat for a new feature, fix for a bug fix, docs for documentation, style for formatting changes, refactor for restructuring code, perf for performance improvements, test for anything test-related, or chore for maintenance tasks. After the type, you put the scope in parentheses — that’s the area of the codebase you’re touching, such as dolibarr, wp-sync, or scripts. Then a colon, followed by a brief description. So as a spoken example, a PR adding a product comparison widget to the WordPress sync area would read something like: feat, wp-sync scope, add product comparison widget.

PR descriptions follow a standard template with four sections. The first is a plain description of what the PR does. The second links to a related issue — if the work closes a tracked issue, you reference it there. The third section covers testing — you explain how someone can verify the changes work correctly. And the fourth is a checklist: does the code follow the style guide, were tests added or updated, was documentation updated, and are there any breaking changes? Having this template means every PR carries the same core information, making review faster and more consistent.

One more thing worth knowing: NZRT supports draft PRs. If you’re still working on something and not ready for review, you can open it as a draft. That signals to the team it’s a work in progress, so nobody jumps in to review before you’re ready.

There are also three ways a PR can actually be merged. A merge commit preserves all your individual commits as-is. A squash merge combines everything into one clean commit — this is the most common approach at NZRT. And a rebase replays your commits on top of the target branch. Each repository can be configured to support one or more of these strategies depending on what works best for that codebase.

Pull requests aren’t just a gate before merging — they’re a collaboration tool. They create a record of why changes were made, who approved them, and what feedback was exchanged. Over time, that history becomes genuinely valuable for anyone working in the same codebase.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Repositories

Welcome to the NZRT Wiki Podcast. Today we’re looking at 📦 Repositories.

So let’s start with the basics. A GitHub repository is essentially a project container. Think of it as a single organised folder that holds everything related to a project — your code, your documentation, your issue tracker, and the full history of every change ever made. Whether you’re building a web app, managing config files, or storing deployment scripts, the repository is where it all lives.

Now, repositories come with a lot of settings, and understanding those settings is really what separates a well-managed project from a chaotic one. Let’s walk through the key concepts you need to know.

First up is visibility. A repository is either public or private. Public means anyone on the internet can view it — that’s typical for open source projects. Private means only people you’ve explicitly invited can see it. At NZRT, most repositories are private, which makes sense for business tooling and client work.

Next is the default branch. This is the branch that GitHub treats as the source of truth for the project. You’ll often see it called main or develop. It’s also usually the branch that gets deployed, so it matters a lot. Whatever goes into the default branch is what ends up in production.

Then there’s branch protection. This is a set of rules you apply to important branches — usually the default branch — to stop people from accidentally pushing directly to it. You might require that all changes come in through a pull request, that at least one other person reviews and approves that pull request, and that any automated checks or tests pass before the merge goes through. Branch protection is one of those things that feels like overhead until the day it saves you from a very bad situation.

Moving on — collaborators and teams. Collaborators are individual users you’ve given explicit access to a repository. There are five permission levels to know about. Pull access means someone can read and clone the repo. Triage lets them manage issues and pull requests. Write means they can push code. Maintain gives broader project management control. And Admin is full control — settings, access, the works. Teams work similarly, but instead of assigning permissions to individuals one by one, you group users into a team and assign permissions to the whole group. Much easier to manage at scale.

You should also know about the README file. When someone lands on your repository’s home page on GitHub, the first thing they see is the README. It’s your project’s front door — it should explain what the project is, how to set it up, and how to use it. A good README saves everyone time.

And finally, the license. If your repository is public and you want to let others use your code, you need a license. The most common ones at NZRT are MIT, Apache, and GPL. Each has different rules about how people can use, modify, and distribute your work. Without a license, legally speaking, no one has permission to use your code at all.

Now let’s look at a real example from NZRT. There’s a repository called Dolibarr-Custom. It’s private, which makes sense because it holds ERP customisations and modules — internal business logic you wouldn’t want exposed publicly. The default branch is main, and the main branch has protection rules in place: you need at least one review before anything merges, and all status checks must pass. Two collaborators are set up — fin with Maintain access, and xc with Admin access.

If you’re ever setting up a new repository at NZRT, there’s a handy checklist to work through. You want to confirm the visibility is correct, the default branch is set, and branch protection is enabled. Make sure collaborators are invited with the right permission level — not too much, not too little. Set up any webhooks you need for notifications. Add secrets for deployments so credentials never end up in the codebase. Write a README, add a license if it’s open source, and configure a gitignore file so the right files get excluded from version control. And if the project needs a public-facing site, consider whether GitHub Pages should be enabled.

If you want to go deeper, the related wiki notes on GitHub Overview, Branch Protection, and Secrets and Tokens are good next reads.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Repository Structure

Welcome to the NZRT Wiki Podcast. Today we’re looking at 📁 Repository Structure.

If you’ve ever opened a project folder and had no idea where anything lives, you’ll know why this matters. At NZRT, all repositories follow consistent directory patterns so that whether you’re navigating a WordPress project or a Dolibarr customisation, you always know where to look. Let’s walk through what that looks like.

Every NZRT repository starts with a set of root-level files. At the very top of any repo, you’ll find things like a README, a dot-gitignore file, and a license. These sit right at the base of the project — they’re the first things you see when you open the folder, and they tell you what the project is, what files Git should ignore, and how the code is licensed.

From there, the structure branches out depending on what the project does. Source code lives in a dedicated directory — usually called “src”, though for WordPress projects you’ll find it under “wp-content”, which then splits into a “plugins” folder and a “themes” folder. That’s the WordPress way of organising things, and NZRT follows it.

Documentation has its own home too — a “docs” folder at the project root. This is where you’d put architecture notes, API specs, anything that explains how the project works rather than being the project itself. Tests sit in a “tests” or “test” folder, covering unit tests, integration tests, and end-to-end tests. Configuration files — environment configs, deployment configs, CI/CD pipelines — are also kept in clearly named locations so you’re never hunting for them.

For assets like images and static media, there are designated folders depending on the project type. And dependency files sit right at the root: for PHP projects that’s a “composer dot json” file, for Node projects it’s “package dot json”, and for Python it’s “requirements dot txt”.

Now let’s look at what this means in practice for the two main NZRT repository layouts.

The first is the WordPress and Dolibarr sync repository. When you open that folder, at the top level you’ll see a README file, a dot-git folder which is Git’s internal data, and a dot-gitignore. The main working folder is “wp-content”, and inside that you’ll find two subfolders: one called “plugins” containing a plugin called “wp-sync-core”, and another called “themes” containing the NZRT theme. There’s also a “docs” folder at the top level for project documentation.

The second layout is for Dolibarr customisations specifically. This one follows a slightly different pattern. At the top level you’ve got a “src” folder, a “tests” folder, a “docs” folder, a “composer dot json” for PHP dependencies, a dot-env-dot-example file which is a template for your local environment variables, and a dot-gitignore. Inside the “src” folder you’ll find three subfolders: “modules” for custom Dolibarr modules, “includes” for shared PHP includes, and “htdocs” for any web-facing files.

So to summarise the difference: the WordPress sync repo is organised around WordPress conventions, with the “wp-content” folder as the main container. The Dolibarr customisations repo is more of a traditional PHP project structure, with source code under “src” and a clear separation between code, tests, and docs.

In terms of NZRT context, “dolibarr-custom” is the primary repository. All custom code lives in those “src” directories we just talked about. Development happens locally in the Laragon environment first, and then gets pushed up to GitHub once it’s ready.

If you want to go deeper on any of this, the wiki links out to three related topics: Git Overview, which covers the basics of how Git works at NZRT; Branching Strategy, which explains how branches are named and used; and dot-gitignore Templates, which gives you ready-made ignore files for different project types.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Secrets Tokens

Welcome to the NZRT Wiki Podcast. Today we’re looking at Secrets and Tokens.

If you’ve spent any time working with GitHub Actions at NZRT, you’ve probably heard the term secrets thrown around. So let’s break down what they actually are, how NZRT uses them, and what you need to know to keep things secure.

At the most basic level, GitHub Secrets are encrypted environment variables. Think of them as a secure vault that GitHub Actions can reach into during a workflow run. Once a secret is stored, you can never read it back out through the GitHub interface — it’s write-only. The only time it appears is when a workflow actively uses it, and even then, GitHub automatically masks the value in your logs, replacing it with three asterisks so nothing sensitive ever gets printed.

Now, secrets come in three flavours. Repository secrets are encrypted and tied to a single repository. Organization secrets sit at the org level and can be shared across multiple repos. And environment secrets are scoped to specific deployment environments, like staging or production. This gives you a layered system where sensitive values live exactly where they need to be and nowhere else.

Here’s what NZRT currently has set up at the repository level. There are six secrets in use. The first two are SSH private keys — one called STAGING DEPLOY KEY for the staging server, and PROD DEPLOY KEY for production. Both are used by the deploy workflow. Then there’s the DOLIBARR API KEY, which sync workflows use to talk to the Dolibarr REST API. There’s a SLACK WEBHOOK secret for sending notifications from within jobs. A CODECOV TOKEN for coverage reporting during test runs. And finally, GITHUB TOKEN, which GitHub generates automatically and is available to all workflows.

At the organization level, NZRT shares two secrets across multiple repos. PROD DEPLOY KEY covers both the dolibarr-custom and nzrt-scripts repositories. And GITHUB TOKEN is available to everything in the org.

So how do you actually use a secret inside a workflow? The example in the wiki shows a deployment job where secrets are mapped to environment variables within a step. The deploy key and the API key are pulled in by name, and the shell script then references those environment variables. You’re never hard-coding the actual values — the workflow just knows to look for them by name and GitHub injects them at runtime. If you accidentally tried to print one of these values, GitHub would replace it with asterisks automatically. But the best practice is to simply not log secrets at all, even though masking protects you.

Let’s talk about how you create these secrets in the first place. For a GitHub personal access token, you go into your account settings, then Developer Settings, then Personal Access Tokens. You generate a new classic token, select the scopes you need — typically repo, admin repo hook, workflow, and read org — then copy the token and store it in your repository secrets.

For SSH deployment keys, the process is a two-step command-line workflow. First, you generate a new RSA key pair at 4096 bits with no passphrase — the no passphrase part matters because automation can’t type a password interactively. Then you take the private key, encode it in base64, and store that encoded value in GitHub Secrets. The matching public key goes onto the production server’s list of authorized keys. That way, GitHub Actions can authenticate over SSH without the actual private key ever appearing in a script.

NZRT also follows a naming convention for custom tokens. The pattern is a prefix, then the environment, then the type — so for example NZRT STAGING DEPLOY KEY or NZRT PROD DEPLOY KEY. This makes it immediately clear what each secret does and where it belongs.

Now, secrets don’t last forever — and they shouldn’t. The wiki includes a rotation checklist you should keep in mind. SSH deploy keys should be rotated every six months. API tokens every three months. Database passwords quarterly. You should also regularly review secret access in the GitHub audit log, remove secrets tied to anyone who leaves the team, and revoke anything that gets accidentally exposed the moment you discover it. That last point is non-negotiable — treat a leaked secret as fully compromised from the instant you find out.

One final thing worth remembering: secrets are only accessible during a workflow run. They’re never embedded in your code, never visible in the repository, and never returned through the GitHub API once stored. That’s the whole point — they stay in the vault until Actions needs them, and then they’re gone again.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Security Best Practices

Welcome to the NZRT Wiki Podcast. Today we’re looking at Security Best Practices.

Security is everyone’s responsibility at NZRT, and today we’re walking through the core principles and practices that protect our code, credentials, and data — whether you’re a developer, a team lead, or just getting started.

Let’s start with the big ideas. At NZRT, security thinking is built around a handful of key concepts. First is the principle of least privilege — you only get the access you actually need to do your job, nothing more. Next is defense in depth, which means we don’t rely on just one security measure. We layer authentication, encryption, and logging so that if one control fails, others are still protecting you. Then there’s secret hygiene — never commit secrets to code, and rotate them regularly. We also insist on code review, audit trails, supply chain security for your dependencies and third-party code, and a clear incident response plan so you can act quickly when something goes wrong.

Now let’s talk about what that looks like day to day. NZRT has a security checklist covering five areas: repository setup, credentials and secrets, access control, code quality, and deployment.

Starting with your repository. Every repo should be private, with branch protection turned on for the main and develop branches. You need a CODEOWNERS file, a README with security instructions, and a gitignore that excludes things like dot-env files, secrets folders, and key files. And critically — no sensitive data should ever appear in your commit history.

On credentials and secrets: no API keys, tokens, or passwords go in the code. Full stop. Secrets live in GitHub Secrets, not in files. Database credentials go in a dot-env file, not in the example version that gets committed. You rotate credentials every three months, and you watch the audit log for unusual access.

For access control, team members get only the roles they need. Inactive users get removed. Admin access is limited to essential people. Two-factor authentication is on every account, SSH keys are registered and verified on GitHub, and personal access tokens are scoped as narrowly as possible.

On code quality: GitHub Actions runs on every pull request — linting, tests, and security scanning. You’re targeting test coverage above eighty percent. No hardcoded credentials. Dependencies are checked for vulnerabilities using Dependabot.

And for deployment: production uses SSH keys, not passwords. Deployments only go through GitHub Actions so they’re reproducible and audited. Status checks must pass before any merge, deployments are logged with timestamps and version numbers, and your rollback procedure is documented and tested.

Now for the secret management policy. NZRT tracks five categories of secrets. Think of it as a table with four columns — the type, some examples, how often you rotate, and where they’re stored. Database passwords like your MySQL credentials rotate quarterly and live in GitHub Secrets. API tokens — things like your Dolibarr or Slack tokens — also rotate quarterly and also go in GitHub Secrets. SSH deploy keys rotate every six months, again in GitHub Secrets. OAuth tokens like your GitHub token rotate quarterly. And SSL certificate private keys rotate annually and live in the server keystore.

What if a credential gets leaked? There’s a clear six-step response. First, immediately disable that credential at the source system. Second, use a tool called BFG Repo-Cleaner to scrub every occurrence from git history. Third, force-push the cleaned history. Fourth, rotate all related credentials — not just the one that leaked. Fifth, log the incident and write a postmortem. Sixth, notify any affected services.

Code review is your last line of defence before code ships. When you review a pull request, you’re checking that there are no secrets or hardcoded paths, that user input is validated, that output is properly escaped to prevent cross-site scripting, that database queries use parameterized statements, that authentication and authorization checks are in place, and that error messages don’t accidentally expose sensitive information.

And if a security issue is detected, follow seven steps: isolate the affected service or roll back the deployment, assess the scope and impact, notify the admin and relevant team leads, remediate and deploy a patch, verify the fix is working, document everything in a postmortem, and if user data was affected, communicate that to the right people.

Security isn’t a one-time setup — it’s an ongoing practice. Keep your credentials rotated, your reviews thorough, and your incident response sharp.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Vs Code Github Integration

Welcome to the NZRT Wiki Podcast. Today we’re looking at VS Code and GitHub Integration.

If you work at NZRT as a developer, VS Code is your home base. And when you pair it with GitHub, you get a setup that handles everything from writing code to reviewing pull requests to spinning up full cloud environments. Let’s walk through how it all fits together.

First, the key concepts. VS Code has a built-in Source Control panel. Think of it as a visual git client sitting right inside your editor. It shows you what files have changed, lets you compare versions side by side, and gives you a full commit history. Alongside that, you authenticate with your GitHub account directly inside VS Code, so all your repository access flows through securely without juggling tokens manually.

A handful of extensions make this really powerful. The GitHub Pull Requests and Issues extension lets you review, comment on, and approve pull requests without ever leaving your editor. GitHub Copilot gives you AI-powered code suggestions as you type, though that one requires a subscription. GitLens supercharges your git history view, showing you who changed what and when, right inline in your code. Then there are practical ones like Markdown All in One for writing notes and docs with live preview, PHP Intelephense and the PHP Extension Pack for server-side work, and the Remote SSH extension, which we’ll come back to in a moment.

To install these, you run a command in your terminal starting with the word “code” followed by “install-extension” and the extension identifier. You do that once for each extension. The wiki shows eight of them lined up in sequence.

Now let’s talk about the day-to-day workflow when you’re working on a feature. You start by cloning a repository. In VS Code, you press Control, Shift, and P to open the command palette, search for Git Clone, and paste in the repository URL. Once it’s open, you create a feature branch from the integrated terminal. As you make changes, the modified files are highlighted automatically in the file explorer. When you’re ready to commit, you open the Source Control panel, click the plus icon next to each file to stage it, type your commit message, and press Control and Enter. Then you click Publish Branch to push it up to GitHub. Back in the command palette, you search for GitHub: Create Pull Request, pick your base branch, add a title and description, and you’re done.

Reviewing pull requests is just as smooth. You open the command palette, search for the GitHub PR option to fetch a pull request, find the one you want by title or number, and it opens in diff view right inside the editor. You can click any line to leave a comment, start a thread, request changes, or approve. Everything you’d normally do on the GitHub website, you’re doing without leaving VS Code.

If you want a full cloud-based development environment, GitHub Codespaces is worth knowing about. You go to the repository on github.com, click the Code dropdown, and choose to create a codespace on the main branch. VS Code opens connected to a cloud machine that already has PHP, Composer, git, npm, and everything else ready to go.

For NZRT’s Dolibarr custom repository, there’s a configuration file in the devcontainer folder that tells GitHub exactly what environment to set up. It specifies a PHP 8.1 base image, adds Docker and Node version 18 as features, forwards ports for the web server and database so they’re accessible from your browser, runs Composer install and npm install automatically once the environment is created, and pre-installs the Pull Requests, PHP Intelephense, and GitLens extensions. You don’t configure any of that by hand. It just happens when the Codespace starts.

The last piece is SSH Remote development, which lets you connect VS Code directly to your local Laragon dev environment over your network. Your SSH settings point to the machine’s local IP address, specify the username, port 22, and the path to your SSH key file. Then in the command palette, you search for Remote-SSH: Connect to Host, select your Laragon Dev entry, and VS Code connects. From that point on, you’re editing files on the remote machine with the full IDE experience. Syntax highlighting, autocomplete, debugging, all of it works exactly as if the files were sitting on your own drive.

That covers the full picture: local development, cloud Codespaces, remote SSH connections, pull request reviews inside the editor, and the extension stack that ties it all together. Whether you’re committing a quick fix or spinning up an entire cloud environment, VS Code and GitHub have you covered at every step.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Project Boards

Welcome to the NZRT Wiki Podcast. Today we’re looking at 📊 Project Boards.

If you’ve ever wondered how NZRT keeps track of all the moving parts in a software release — from idea through to deployment — this is the episode for you. GitHub Projects are the tool we use, and they let you organise issues and pull requests into a visual workflow that the whole team can see and act on.

Let’s start with the two main ways you can look at a project board. The first is the Table View, which works a lot like a spreadsheet. You can see all your items in rows, with custom columns for things like who it’s assigned to, what the status is, and how high the priority is. The second is the Board View, which is a Kanban-style layout — columns running left to right, with cards you can drag between them. The standard columns you’ll see are Backlog, In Progress, In Review, and Done.

One of the most powerful things about GitHub Projects is automation. You don’t have to manually move things around all the time. The board can be set up so that new issues automatically land in the Backlog the moment they’re created. When a pull request is raised, it jumps straight to the Deploy column. When a PR gets merged, it moves itself to Done — and if there’s a linked issue, that gets automatically closed too. A lot of admin just takes care of itself.

You can also filter the board to show only what’s relevant to you — by status, by assignee, by label, or by priority. And if you need to update a bunch of items at once, bulk actions let you select multiple cards and change priority, add a label, or reassign them all in one go.

Let’s look at a real NZRT example. We have a board called the Dolibarr Custom Release Board, set up for version two point one. It has six columns. Backlog, for things not yet started — like a feature request for product export. Design, for anything in design review — for example, mockups for a comparison widget. Development, for work currently in progress, like actually building that comparison feature. Testing, where items are going through QA validation on staging. Deploy, for things ready to release but waiting on a second approval before merging to main. And finally Done, for everything already shipped — like version two point zero, which is already in production.

The board also uses custom fields to add more detail to each card. There’s a Priority field with High, Medium, or Low options. There’s an Effort field using story points — one, two, three, five, or eight points. There’s a Release field to tag which version something belongs to. And there’s an Owner field to assign work to specific team members.

Now let’s talk about sprint planning. Say you’re planning the sprint for a particular week. You go through your backlog and look at what’s available. You might have four issues to consider: one for advanced filtering at five points and high priority, one for improving mobile responsiveness at three points and medium priority, one for API rate limiting at eight points and high priority, and one for documentation updates at three points and low priority. Your sprint capacity for the week is thirteen points. So you’d pick the filtering issue at five, mobile responsiveness at three, and documentation at three — eleven points total — keeping two points in reserve for bugs or unexpected interruptions.

When you’re working day to day, you can filter the board to show only your assigned items. Instead of seeing everything, you’d see just your slice: maybe one item in Design, two in Development, one in Testing, and a collapsed list of whatever you’ve finished that sprint. It keeps your view clean and focused.

Bulk actions make light work of repetitive updates too. Say you’ve selected two items — a bug fix and a mobile responsiveness task. You can set both to High priority, add an urgent label, and assign them to a team member, all in one step rather than editing each card individually.

So to pull it all together: project boards give you and your team a shared, real-time picture of where work stands. Automation reduces the manual overhead, custom fields add the context you need, and filtering keeps your view focused on what matters to you right now. Whether you’re planning a sprint or tracking a release, this is how NZRT keeps things moving forward.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

WordPress Github Integration

Welcome to the NZRT Wiki Podcast. Today we’re looking at WordPress GitHub Integration.

So let’s start with the big picture. When it comes to the NZRT setup, WordPress and GitHub work together through a combination of webhooks, REST APIs, and GitHub Actions. The key thing to understand is that there are two separate sources of truth here. Code lives in GitHub, and content lives in the WordPress database. Those two responsibilities never cross over, and keeping that distinction clear makes the whole system much easier to reason about.

When you push code, it flows from GitHub through a GitHub Actions pipeline and lands on the WordPress server via SSH. If product data changes in WordPress, a webhook can fire and sync that change over to Dolibarr through its API. Theme files, plugin code, and configuration are all version controlled in git. And you’ve got two environments to work with: the develop branch deploys to staging, and the main branch, via a release tag, deploys to production.

Now let’s talk about how the code itself is organised in the repository. Picture a root folder called dolibarr-custom. Inside that you’ve got a wp-content folder, which contains a plugins folder and a themes folder. Under plugins, there’s a plugin called wp-sync-core, and inside that you’ll find a src folder with three sub-folders for Admin, Frontend, and API logic. Alongside src there are folders for templates, and assets which holds CSS and JavaScript. The plugin’s main entry file sits at the root of that plugin folder, along with a composer.json for PHP dependencies. Back in wp-content, the themes folder holds the nzrt-theme, which contains template parts, assets, a functions file, and a stylesheet. At the very root of the repository you’ll also find the main WordPress config file, an environment variables file, a Docker Compose file for local development, and a readme.

Let’s walk through the product sync flow, because this is where a lot of the integration magic happens. When you edit a product in the WordPress admin, WordPress fires a REST API hook. The wp-sync-core plugin picks up that event and prepares a request for Dolibarr. That request packages up the product name, SKU, price, category, images, and any relevant metadata. It then sends a POST request to the Dolibarr products endpoint to either create or update the record. Once Dolibarr responds, WordPress stores the Dolibarr product ID and a timestamp in its own post metadata, so you always know when a product was last synced and what its Dolibarr identifier is. Finally, the event gets written to an audit trail for traceability.

The PHP code that handles this lives in a class called DolibarrSync inside the API folder of the plugin. It reads the Dolibarr API URL and your API key from the environment, then defines a method that accepts a WordPress product ID. It fetches the product details, builds a payload with the label, price, tax rate, and status, then sends that payload to Dolibarr using WordPress’s built-in HTTP helper. If the request fails, the error gets logged. If it succeeds, the returned Dolibarr ID gets saved back into WordPress meta. Clean, self-contained, and auditable.

Now for the deployment pipeline. The GitHub Actions workflow triggers whenever you push to either the develop or main branch. It starts by checking out the code on a fresh Ubuntu runner, then sets up PHP version eight point one. Next it installs Composer dependencies without the dev packages, then runs a PHP lint check across every PHP file in wp-content to catch any syntax errors before anything hits a server. The deploy step then reads your deploy key from GitHub secrets, writes it to a temporary SSH key file, locks down its permissions, adds the target host to the known hosts file, and finally SSH’s in to run a git pull on the server. The target host is determined automatically: main branch points to production, any other branch points to staging.

For local development, you’re using a Docker Compose setup with two services. One runs the latest WordPress image connected to a MySQL database, maps port eighty through to your host, and mounts your repository folder directly into the web root so changes are instant. The other service runs MySQL eight, creates the dolibarr-custom database on startup, and exposes port three three zero six for direct database access.

That’s the full picture: code in GitHub, content in WordPress, syncing to Dolibarr via the plugin, deployed automatically through Actions, and reproducible locally with Docker.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.