Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/hugo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ jobs:
test -f _vendor/modules.txt

- name: Build
run: ./scripts/hugo.sh --minify --buildFuture
run: ./scripts/hugo.sh --minify --buildFuture --cleanDestinationDir

- name: Test Internal Link Checker
run: python3 -m unittest discover -s scripts -p 'test_*.py'

- name: Check Rendered Internal Links
run: python3 scripts/check_internal_links.py public --base-url https://cloudartisan.com/

- name: Copy CNAME file
run: |
Expand Down
33 changes: 8 additions & 25 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,21 @@ jobs:
- name: Test Build (Development)
run: |
echo "Testing development build..."
./scripts/hugo.sh --buildDrafts --buildFuture
./scripts/hugo.sh --buildDrafts --buildFuture --destination "${RUNNER_TEMP}/hugo-development"
echo "✅ Development build successful"

- name: Test Build (Production)
run: |
echo "Testing production build..."
./scripts/hugo.sh --minify --buildFuture
./scripts/hugo.sh --minify --buildFuture --cleanDestinationDir
echo "✅ Production build successful"

- name: Test Internal Link Checker
run: python3 -m unittest discover -s scripts -p 'test_*.py'

- name: Check Rendered Internal Links
run: python3 scripts/check_internal_links.py public --base-url https://cloudartisan.com/

- name: Check Build Output
run: |
echo "Analysing build output..."
Expand Down Expand Up @@ -144,29 +150,6 @@ jobs:

echo "✅ All markdown files have valid front matter"

- name: Check for Broken Internal Links
run: |
echo "Checking for potential broken internal links..."

# Look for common broken link patterns
if grep -r "](http://localhost" content/; then
echo "❌ Found localhost links in content"
exit 1
fi

# Check for missing project references
if grep -r "](/projects/" content/; then
echo "Found internal project links, checking they exist..."
for link in $(grep -ro "](/projects/[^)]*)" content/ | sed 's/.*](/projects//;s/[)].*//' | sort -u); do
if [ ! -d "content/projects$link" ] && [ ! -f "content/projects$link.md" ] && [ ! -f "content/projects$link/index.md" ]; then
echo "❌ Broken internal link: /projects$link"
exit 1
fi
done
fi

echo "✅ No obvious broken internal links found"

validate-images:
runs-on: ubuntu-latest
steps:
Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,43 @@ The theme is vendored under `_vendor/`, so day-to-day builds do not need Go or a
./scripts/hugo.sh --minify --buildFuture
```

## Internal Links and Legacy URLs

After a clean production build, run the offline link check:

```sh
./scripts/hugo.sh --minify --buildFuture --cleanDestinationDir
python3 -m unittest discover -s scripts -p 'test_*.py'
python3 scripts/check_internal_links.py public --base-url https://cloudartisan.com/
```

PR validation runs these checks against production output, so draft pages or stale
development files cannot hide missing destinations. The checker covers same-site
HTML links, canonical and redirect targets, images, scripts, stylesheets, `srcset`
and sitemap URLs, including HTTP/www variants and relative links. It reports the
rendered file, line and missing target, and fails on localhost links or an empty
build. It does not fetch external sites or validate fragments, CSS URLs or URLs
constructed by JavaScript. Use Hugo `relref` for article links so renamed or
missing source pages also fail the Hugo build.

Keep aliases for moved articles in their YAML front matter. GitHub Pages serves
static files and does not expose arbitrary HTTP 301/308 path rules through this
repository. Hugo aliases generate immediate (zero-second) meta-refresh redirects
with a canonical destination, which [Google treats as permanent redirects for
indexing](https://developers.google.com/search/docs/crawling-indexing/301-redirects).
They still return HTTP 200, rather than 301. The legacy `/feed/` path has a static
redirect to `/feed.xml`; link directly to `/feed.xml` for RSS clients.

Search Console has no old-to-new path correction operation: its [Change of
Address tool](https://support.google.com/webmasters/answer/9370220?hl=en) does not
apply to moves within a site. After these changes are merged and deployed,
verify the live redirects and current destinations, then optionally [request
indexing](https://developers.google.com/search/docs/crawling-indexing/ask-google-to-recrawl)
for the destination articles and validate the 404 fix in Search Console. A request
encourages a recrawl; it does not force a canonical URL or guarantee rankings.
Keep legacy redirects long-term, and keep only current canonical URLs in the
sitemap. Do not use removals to correct moved URLs.

## Updating Theme Dependencies

Normal builds do not require Go. You only need Go when you want to refresh vendored Hugo modules, for example when updating Congo.
Expand Down
2 changes: 2 additions & 0 deletions content/posts/2010-08-09-google-app-engine-gotcha-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ draft: false
slug: google-app-engine-gotcha-2
tags: ["google app engine", "paas", "python"]
description: Inflexible outbound timeouts are a pain in the...
aliases:
- /2010/08/google-app-engine-gotcha-2/
---

For _Google App Engine: Gotcha #2_ I choose the default 5 second timeout on `urlfetch`. This function is part of the Google App Engine's API and applies to both Python and Java.
Expand Down
4 changes: 3 additions & 1 deletion content/posts/2010-08-29-google-app-engine-gotcha-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ draft: false
slug: google-app-engine-gotcha-3
tags: ["gae", "google app engine", "google apps", "gotcha", "paas", "sdc", "urlfetch"]
description: Do I really need to whitelist every Google IP address ever?!
aliases:
- /2010/08/google-app-engine-gotcha-3/
---

## What's the problem?
Expand All @@ -17,7 +19,7 @@ It makes sense, when you think about it. Google App Engine is ([apparently](http

Unfortunately, some APIs (eg, eNom) still require users to register their source IP so that it can be whitelisted. If you can't register an IP you can't use their API.

Google are really not making it easy to integrate Google App Engine with external (slow/legacy) APIs. Refer to [Google App Engine: Gotcha #2](http://www.cloudartisan.com/2010/08/google-app-engine-gotcha-2/) for another issue with `urlfetch` and consuming external APIs...
Google are really not making it easy to integrate Google App Engine with external (slow/legacy) APIs. Refer to [Google App Engine: Gotcha #2]({{< relref "2010-08-09-google-app-engine-gotcha-2.md" >}}) for another issue with `urlfetch` and consuming external APIs...

## How did I test this?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ tags: ["google app engine", "paas", "python"]
description: Looks like I might need to migrate from Google App Engine to Django...
---

I've been nose-deep migrating a project from Google App Engine to Django.  See [Google App Engine Gotcha #2](http://www.cloudartisan.com/2010/08/google-app-engine-gotcha-2/) and [Google App Engine Gotcha #3](http://www.cloudartisan.com/2010/08/google-app-engine-gotcha-3/) for the reasons.  I'm keeping notes on the experience, in case any other poor suckers out there have to migrate from the cosy, loving embrace of a PaaS to the cold, hard trenches of a self-managed server.
I've been nose-deep migrating a project from Google App Engine to Django.  See [Google App Engine Gotcha #2]({{< relref "2010-08-09-google-app-engine-gotcha-2.md" >}}) and [Google App Engine Gotcha #3]({{< relref "2010-08-29-google-app-engine-gotcha-3.md" >}}) for the reasons.  I'm keeping notes on the experience, in case any other poor suckers out there have to migrate from the cosy, loving embrace of a PaaS to the cold, hard trenches of a self-managed server.

Stay tuned...
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ draft: false
slug: install-cherokee-testing-on-debian-lenny
tags: ["debian", "general", "lenny", "system administration"]
description: How to install Cherokee (testing) on Debian Lenny...
aliases:
- /2010/10/install-cherokee-testing-on-debian-lenny/
---

Add the following to `/etc/sources`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tags: ["general", "google app engine", "paas", "python", "software development"]
description: Yup, I'm migrating from Google App Engine to Django. In this post I go over some of the key differences and considerations...
---

Unfortunately, I had to migrate one of my projects from Google App Engine to Django on a self-managed server. I didn't want to do this. See [Google App Engine Gotcha #2](http://www.cloudartisan.com/2010/08/google-app-engine-gotcha-2/) and [Google App Engine Gotcha #3](http://www.cloudartisan.com/2010/08/google-app-engine-gotcha-3/) for the main reasons. Those headaches became bad enough that I had to bite the bullet and migrate out of Google App Engine.
Unfortunately, I had to migrate one of my projects from Google App Engine to Django on a self-managed server. I didn't want to do this. See [Google App Engine Gotcha #2]({{< relref "2010-08-09-google-app-engine-gotcha-2.md" >}}) and [Google App Engine Gotcha #3]({{< relref "2010-08-29-google-app-engine-gotcha-3.md" >}}) for the main reasons. Those headaches became bad enough that I had to bite the bullet and migrate out of Google App Engine.

_It's not for the faint-hearted..._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ draft: false
slug: google-app-engine-sdk-broken-on-ubuntu-maverick-10-10
tags: ["google app engine", "paas", "python"]
description: The Google App Engine SDK is broken on Ubuntu 10.10, but it's easy enough to fix...
aliases:
- /2010/10/google-app-engine-sdk-broken-on-ubuntu-maverick-10-10/
---

The Google App Engine SDK is broken on Ubuntu 10.10, but it's easy enough to fix...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ draft: false
slug: adding-the-cherokee-web-server-ppa-to-ubuntu
tags: ["general", "system administration", "ubuntu"]
description: Follow the commands in this post to add the Cherokee Web Server PPA to Ubuntu 9.10 or higher...
aliases:
- /2010/11/adding-the-cherokee-web-server-ppa-to-ubuntu/
---

The following commands will add the Cherokee Web Server PPA to Ubuntu (version 9.10 and higher). The first command adds the extremely handy `add-apt-repository` program to your system. The second adds the Cherokee Personal Package Archive.
Expand All @@ -27,4 +29,4 @@ If you don't already have Cherokee installed and you want to install it I find t
```


That's it. If you want more simple posts on building lean servers, cloud computing, software development and more, [subscribe to my RSS feed](http://www.cloudartisan.com/feed) and/or [follow me on Twitter](https://twitter.com/davidltaylor). Cheers!
That's it. If you want more simple posts on building lean servers, cloud computing, software development and more, [subscribe to my RSS feed](/feed.xml) and/or [follow me on Twitter](https://twitter.com/davidltaylor). Cheers!
6 changes: 3 additions & 3 deletions content/posts/2010-11-25-using-ispconfig-with-cherokee.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ There are some very good instructions for installing ISPConfig on various distri

Also, I've previously written about installing Cherokee on Ubuntu and Debian Lenny (using the testing repository):

* [Adding the Cherokee Web Server PPA to Ubuntu](http://www.cloudartisan.com/2010/11/adding-the-cherokee-web-server-ppa-to-ubuntu/)
* [Install Cherokee (testing) on Debian Lenny](http://www.cloudartisan.com/2010/10/install-cherokee-testing-on-debian-lenny/)
* [Adding the Cherokee Web Server PPA to Ubuntu]({{< relref "2010-11-20-adding-the-cherokee-web-server-ppa-to-ubuntu.md" >}})
* [Install Cherokee (testing) on Debian Lenny]({{< relref "2010-10-02-install-cherokee-testing-on-debian-lenny.md" >}})

Once you're past that, you need to get them both to work together.

Expand Down Expand Up @@ -104,6 +104,6 @@ Try loading the site again. As long as the usual culprits are OK (eg, DNS) ISPCo

_Caveat: these permissions might pose a problem for future upgrades to ISPConfig. Also, it's the easy way out... I became bored and gave up before figuring out exactly what was experiencing permissions problems. If you know, let me know, I'll update the post._

You should [subscribe to my feed](http://www.cloudartisan.com/feed/) and [follow me on twitter](https://twitter.com/davidltaylor).
You should [subscribe to my feed](/feed.xml) and [follow me on twitter](https://twitter.com/davidltaylor).

Cheers!
2 changes: 2 additions & 0 deletions content/posts/2010-11-28-using-php-apc-with-cherokee.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ date: 2010-11-28
draft: false
slug: using-php-apc-with-cherokee
tags: ["cherokee", "general", "php-apc", "system administration", "ubuntu"]
aliases:
- /2010/11/using-php-apc-with-cherokee/
---

If you're using Cherokee as your web server, you're probably already interested in squeezing every drop of performance out of your server. If you're hosting PHP sites with Cherokee, using APC (Alternative PHP Cache) could enable you to squeeze out even more drops.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tags: ["cherokee", "general", "php-apc", "system administration", "ubuntu"]
description: "A short guide on performance tuning PHP APC with the Cherokee web server"
---

Since writing [Using PHP APC with Cherokee](http://www.cloudartisan.com/2010/11/using-php-apc-with-cherokee/) I noticed that my cache hits were dropping and my cache misses were growing. This is my first attempt at tweaking the configuration of `php-apc` to try to eke out more performance.
Since writing [Using PHP APC with Cherokee]({{< relref "2010-11-28-using-php-apc-with-cherokee.md" >}}) I noticed that my cache hits were dropping and my cache misses were growing. This is my first attempt at tweaking the configuration of `php-apc` to try to eke out more performance.

I enabled my `apc.php` page (check the previous article), checked the statistics, and saw that the `Cache full count` was growing. My cache had filled several times.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: My first Djangy project (initial testing)
date: 2010-12-02
draft: false
slug: my-first-djangy-project-initial-testing
aliases:
- /2010/12/my-first-djangy-project-initial-testing/
---

My first Djangy project will be an application called `rightscalefeed`. It will pull down a user's RightScale event feed. Ideally, I'd like to transform the feed into a WebSocket, suitable for continuous updates, perhaps for display in a data centre or network operations centre.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ draft: false
slug: my-first-djangy-project-local-testing
---

In my [previous post](http://www.cloudartisan.com/2010/12/my-first-djangy-project-initial-testing/) I knocked out some simple code and pushed it straight to Djangy. I didn't even test it locally first (_gosh shock horror aghast_)! Well, that must end... now.
In my [previous post]({{< relref "2010-12-02-my-first-djangy-project-initial-testing.md" >}}) I knocked out some simple code and pushed it straight to Djangy. I didn't even test it locally first (_gosh shock horror aghast_)! Well, that must end... now.

A Djangy project is, in it's heart of hearts, a Django project that you've shoved out your door into the big bad world. And the great thing about Django projects... you can run them locally for testing.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,5 +295,5 @@ There's definitely a learning curve to using these tools effectively. You need t

If you're already using Claude Code, Codex doesn't necessarily offer a compelling reason to switch. In my case, it was worth adding to my toolkit, as I already have an OpenAI account I'm paying for and so it was no great hurdle to set it up and add it to my development workflow.

Keep an eye out for my next post in this series, where I'll dive into [more advanced tips and tricks](/posts/2025-04-19-openai-codex-tips-tricks/) for getting the most out of Codex CLI.
Keep an eye out for my next post in this series, where I'll dive into [more advanced tips and tricks]({{< relref "2025-04-21-openai-codex-tips-tricks.md" >}}) for getting the most out of Codex CLI.

2 changes: 2 additions & 0 deletions content/posts/2025-04-21-openai-codex-tips-tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ author: "david-taylor"
tags: ["OpenAI", "Codex", "CLI", "AI", "Development Tools", "Tips"]
categories: ["Tutorials"]
series: ["OpenAI Codex Tips & Tricks"]
aliases:
- /posts/2025-04-19-openai-codex-tips-tricks/
---

After [getting started with OpenAI Codex CLI](/posts/2025-04-18-getting-started-with-openai-codex-cli/), I've discovered some handy tips to make working with it a bit easier.
Expand Down
Loading
Loading