whoami
Lucas Jenß
cat /etc/motd
The Coding Journal ツ — Notes taken on an epic coding journey. Technical solutions, debugging notes, and practical guides from the trenches of software development.
ls -la ~/languages/
- drwxr-xr-x
- ▶ PHP
- ▶ Ruby
- ▶ Scala
- ▶ C#
- ▶ JavaScript
- ▶ Objective-C
- ▶ Shell Scripting
ls -la ~/toolchain/
- drwxr-xr-x
- ▶ Typo3
- ▶ Akka
- ▶ Capistrano
- ▶ Git
- ▶ MAMP
- ▶ Adobe Illustrator
- ▶ NSTrackingArea (Cocoa)
uname -a
- drwxr-xr-x
- ▶ Mac OS X
- ▶ Unix
Automating Ruby formatting with RuboCop in CI
Automating Ruby code formatting with RuboCop in a CI pipeline gives every contributor the same rules, even when editors and operating systems differ. RuboCop checks layout, style, and many common code smells; the pipeline makes those results visible before changes are merged. That consistency reduces formatting-only reviews and prevents small style differences from accumulating across a long-lived codebase.
Automation should still leave room for judgement. The pipeline can identify deterministic offences, publish precise feedback, and protect shared branches, while people decide whether an unusual exception is justified. The result is less review noise and an auditable history of the formatting decisions made with each change.
Why formatting checks belong in continuous integration
Without an automated gate, whitespace and naming debates drift into pull requests, and merge conflicts become harder to resolve as the codebase grows. RuboCop provides a repeatable baseline, but the baseline matters only if every environment uses the same configuration and dependency versions. A style rule that exists on one laptop is not a team-wide safeguard.
Continuous integration is useful because it runs against a clean checkout rather than an already modified working tree. It can inspect every proposed change, fail the build when an offence appears, and leave a durable record for reviewers. A local pre-commit hook remains useful for quick feedback, but it should complement the pipeline rather than replace it.
The same validation-first mindset appears in validating IP addresses in PHP: automated checks should report a concrete, reproducible problem rather than ask reviewers to guess what happened. Applied to Ruby, that means stable commands, pinned tools, and output that points directly to the file and rule that needs attention.
Defining a reliable project configuration
Start with the project’s dependency files, not a global gem installation. Add rubocop and any specialist plugins, such as rubocop-rspec or rubocop-performance, to the Gemfile, then commit Gemfile.lock. A checked-in .rubocop.yml should set the target Ruby version, inherit plugin defaults with inherit_gem, and make new cops visible through a deliberate NewCops policy.
Older applications often need a staged cleanup. Generate a .rubocop_todo.yml baseline, review every excluded offence, and track that file with the code instead of ignoring the warning. Keep exclusions narrow, especially for generated or vendored code; blanket exclusions can hide defects that RuboCop would otherwise catch in maintained files.
Defaults are a starting point, not a substitute for project judgement. Before overriding a cop, check its behaviour on representative code and record why the exception is needed. An independent view of Ruby tooling can help frame that decision; Mike Patt’s Ruby perspective is a useful reference point when comparing established conventions with your own.
Running RuboCop in a GitHub Actions workflow
A GitHub Actions workflow is a practical place to enforce the rules. The job should check out the repository, set up the Ruby version used by the project, and install dependencies from the lockfile. The ruby/setup-ruby action supports Bundler caching, while permissions should be limited to what the check actually needs.
Run bundle exec rubocop --parallel --format simple on pull requests, and repeat it for pushes to the protected main branch. The command inherits the locked gem versions, and any offence produces a non-zero exit status that fails the job. A separate annotation format can place the same offence details directly beside pull request changes.
Use the pull-request event to cover proposed work and the branch push to catch changes that arrived by another route. Keep the workflow readable: install dependencies, run RuboCop, and upload any saved report or log. For a gem supporting several Ruby versions, a small matrix can test those runtimes, but the formatting configuration should remain identical.
Turning violations into useful pull request feedback
Useful feedback identifies the file, line, cop name, and suggested correction. RuboCop’s GitHub formatter can turn results into annotations on the diff, while the job log remains the fallback for details. This matters when a pull request contains many files: reviewers can focus on behaviour instead of hunting through a wall of console output.
Developers can apply safe corrections locally with bundle exec rubocop -a. The broader -A mode includes corrections classified as unsafe, so its diff deserves careful review. The CI job should normally report rather than silently rewrite a branch: automatic commits can race with new pushes, obscure authorship, and are risky on pull requests from forks.
Save a structured report when the repository is large enough to need trend tracking, and retain it as a build artifact for the chosen period. Compare offence counts and job duration across changes, not just the final green or red state. A rising baseline can reveal that a dependency upgrade enabled new cops or that a subsystem is drifting.
Fitting the pipeline into Australian team routines
Australian teams may prefer Australian English in project documentation, including words such as “organisation” and “behaviour”. That preference belongs in the team’s written conventions; it should not trigger broad renames of public Ruby methods, gem options, or database fields after release. RuboCop governs code shape, while spelling policy is best handled separately and deliberately.
Schedules also cross several clocks. Sydney and Melbourne observe daylight saving, Brisbane uses a fixed offset, and Perth is two hours behind Brisbane. For example, a 09:00 Sydney review during daylight saving occurs at 22:00 UTC on the previous day. Set release windows and notification expectations explicitly so a Sydney approval does not arrive after a Perth developer has left work.
The local technology market includes cloud teams serving Australian banks, retailers, and government clients. Production workloads may run in AWS’s Sydney region, ap-southeast-2, or Melbourne, ap-southeast-4, and pipeline artefacts should follow the organisation’s data-residency policy. Ruby Australia meetups in cities such as Sydney and Melbourne also provide a local channel for discussing tooling standards across client projects.
Safeguards for a sustainable quality gate
A sustainable gate must distinguish new work from historical debt. Keep the baseline small and dated, avoid changing the target Ruby version or cop set in the same pull request as unrelated business logic, and explain configuration changes separately. In a monorepo, split checks by component if one full scan has become too slow for routine feedback.
Measure the job before optimising it. Bundler’s dependency cache and RuboCop’s parallel mode usually provide the largest gains, while generated artefacts and vendor trees should be excluded through explicit paths. Security-sensitive teams may also pin third-party actions to commit hashes, a common expectation when audit evidence is required for Australian financial or public-sector contracts.
- Pin RuboCop and every plugin in
Gemfile.lock, and review release notes before upgrading either. - Keep one canonical configuration, with a written reason and removal condition for each exception.
- Run the full check on pull requests until the baseline is clean, then avoid changed-file blind spots.
- Use read-only permissions for untrusted fork pull requests and isolate any trusted auto-fix job.
- Track job duration and offence counts so a noisy or slowing gate receives attention before it is ignored.
Make the quality gate part of every change
Begin with a small pilot rather than switching every repository at once. Add the locked dependencies and configuration, run the same command locally that CI will run, then open a draft pull request to inspect the annotations. Once the output is understood and the baseline is agreed, make the check required for the protected branch and document how exceptions are approved.
Add the workflow to one repository today, verify it on a small pull request, and use the result to agree on the team’s shared Ruby conventions. Make the first protected pull request the concrete next action.
cat ~/interests.json
| Key | Value |
|---|---|
| editor | Terminal-first workflow |
| os | Mac OS X / Unix |
| vcs | Git, distributed version control |
| deploy | Capistrano, cron automation |
| graphics | SVG, Adobe Illustrator troubleshooting |
| networking | IP validation, SSH, VPN |
git log --oneline --reverse
Solving SVG import issues in Adobe Illustrator CS6 and CC
When importing an SVG into Illustrator, the operation fails with an unknown error [CANT]. A workaround for this Adobe-side bug.
Solving NDK build issues on OS X
Troubleshooting native development kit compilation problems on Mac OS X.
Programmatically adding PHP generated TypoScript to the backend configuration
Integrating dynamically generated TypoScript into Typo3 backend setups using PHP.
ArgumentError: Could not parse PKey: no start line
Debugging an SSH key parsing error encountered during deployment.
Validating IP-Addresses in PHP
Using PHP filter functions with flags like FILTER_FLAG_IPV4 and FILTER_FLAG_IPV6, and understanding how filter_var handles reserved IP addresses.
Cocoa: Using NSTrackingArea
A short tutorial on using Cocoa's NSTrackingArea to capture mouseEntered and mouseExited events.
cat ~/contact.txt