Blog
-
The Myth of the Virtuous Driver
October 29, 2021
This is a riff of The Myth of the Virtuous Cyclist a puff editorial piece that seems to think one rule breaking cyclist is proof we need to cancel biking and continue allowing drivers the deference as the sole users of our roads.
This Wednesday, at about 8pm, in the middle of Beacon St, I saw an SUV run a red turning left across traffic during the walk cycle. As the pedestrian walk light came on, he cut across the opposite traffic lane, across two cross walks to get to a parking lot entrance. There he parked presumably as a delivery driver who couldn’t wait 60 seconds for a light cycle. I couldn’t imagine why he thought it was okay or what was in his mind, but he seemed unconcerned about the risk he posed to others or that he might be reprimanded.
Everyone who walks or bikes around in Cambridge knows that flagrant “anything goes” behavior is the normal it has spread among delivery drivers, tractor trailers, work trucks, commuters, Uber drivers and the like.
This outbreak of norm-breaking by drivers may in part be due to advances in cellphone technology that make driving distracted easier and more enjoyable. It may in part be that continued lax enforcement in driving laws and infrastructure that has long stimulated a desire to push boundaries with wide open lanes to gun it. It may also be generational, a badge of boomer entitlement identity.
The norm-breaking driver is not alone. A belief that “anything goes” for an extra 10 seconds saved is widespread throughout society, and driving is all about that 10 seconds. Witness the City’s Bicycle Safety Ordinance amendment passed by the City Council in 2020. This remarkable piece of legislation was enacted via Zoom with little discussion by a public who were preoccupied with the pandemic as well as myriad disruptions to normal life and lulled by the proposal’s benign and highly misleading title.
The law in fact contains a detailed menu and timeline of mandates for the city to build separated bicycle lanes on less than 5% (?) of our of public ways. It briefly references the goal of bicycle safety but none of the other recognized means of improving safety, such as enforcement of traffic regulations, driver re-education or signs. It simply asserts that an elaborate and inflexible plan is necessary to reduce systemic risks to cyclists and makes no provision for evaluation of impacts, or reconsideration as progress is made, circumstances change or new information comes to light. Further, it explicitly privileges needs and lives of local residents over single occupancy car commuters on the public ways.
In approving this law, councillors showed that they are willing to choose people over cars, protecting lives and livelihoods, to “build the future you want,” the mantra of optimism, that developers are comfortable with a policy that may force settled residents to continue living there normal lives as on average non-drivers. Running reds, distracted driving, honking horns, dangerous passes this is the norm of drivers in Cambridge, I believe we need to break these habits that drivers insist on. It is surprising and encouraging that our local government leaders, our representatives, recognize we cannot just keep prioritizing cars in our spaces.
We need to support city councillors who are willing to reconsider the timeline and details of the 2020 ordinance speeding it up and expanding it’s scope. They cannot do this without upsetting the minority of entitled residents in our midst, drivers. We build these safe bike networks to remove and reduce the dangers for all citizens, giving walkers and bikers increased space to co-exist without fighting over the scraps left after feeding the space guzzling automobile.
-
Elixir Gitlab CI Example
March 10, 2021
Inspired by @akoutmos’s tweet on Elixir test coverage ExUnit Test Coverage Tweet, I wanted to show off how you can integrate this into Gitlab CI for tracking test coverage in Gitlab.
At Skylla we have been using Gitlab for source control and CI for a while a now. I have enjoyed using Gitlab and it works well for us. Gitlab CI has a ton of different options and ways to use it so I wanted to showcase an Elixir app pipeline.
This example will walk through setting up CI tests, test coverage tracking, linting, and publishing an Elixir release.
Setup
For this I set up a new mix project with
mix new example_gitlab_ci_ex
and set up a Gitlab repository at agundy/example_gitlab_ci_ex..gitlab-ci.yml
Gitlab CI reads a file in the root directory and can include templates or other files in subdirectories. For now everything well be in one file and we’ll set up which stages our CI pipeline will have and a reusable Elixir helper for different CI jobs.
--- stages: - test - publish .elixir: &elixir image: elixir:1.11 before_script: - mix local.hex --force - mix local.rebar --force - mix deps.get --only $MIX_ENV
Linting
Elixir has some nice built in code quality tools. I set up this repo to be strict, rejecting code that if is not formated or there are any compilation warnings.
lint:elixir: extends: .elixir stage: test variables: MIX_ENV: test script: - mix compile --warnings-as-errors --force - mix format --check-formatted
If you want to be less strict you could remove some of the checks or add
allow_failure: true
to the block. Allow failure tells Gitlab CI to run the job but don’t error if the check fails, just show a warning.Tests and Coverage
CI with tests does not provide much value so let’s add a test stage. Here’s a basic Elixir test stage that will run tests in the repo, reusing that same
.elixir
job partial.test:elixir: extends: .elixir stage: test variables: MIX_ENV: test script: - mix test
Test coverage is a whole other blog post, I do not believe in 100% code test coverage or hard requirements but use it as a lossy signal of repository health. I treat it the same way I do a step counter, good for viewing overall trends but a poor snapshot judging a specific day/merge request. Updating our script
mix test
tomix test --cover
gets us a nice little report for viewing in the CI output.Once we have coverage in CI what else can we do? Gitlab has two features we can integrate with to get even more information into our merge requests and project analytics, coverage percentage information and parsed test failure feedback.
Coverage
In the projects CI/CD configuration under “General pipeline settings” is a “Test coverage parsing” field and the Regex we want to add there is:
\d+.\d+\%\s+\|\s+Total
.Reports
Gitlab supports
junit.xml
reports which are a standard for test reports. Elixir does not export these by default but we can install a package that helps us and configure it in two steps.- In
mix.exs
add{:junit_formatter, "~> 3.1", only: [:test]}
in thedeps
section. - In
test/test_helpers.exs
addExUnit.configure(formatters: [JUnitFormatter])
to the top.
With this setup jobs will show how many tests and an include timing as well as test failures in the UI. Here is a merge request with report summaries visible: Gitlab Merge request and the pipeline test summary.
Summary
Our final test CI job will look like this:
test:elixir: extends: .elixir stage: test variables: MIX_ENV: test script: - mix test --cover artifacts: paths: - _build/test/lib/example_gitlab_ci_ex/test-junit-report.xml reports: junit: _build/test/lib/example_gitlab_ci_ex/test-junit-report.xml
Publishing
Elixir has a few different deployment options depending on how and where you are using the code. At Skylla we use releases and so I’ll show that off here, I’m sure there are other ways to do this but one way to deploy is to set up a release, publish it to an artifact and then download it and unpack on whichever server we are running our app on.
Configure the app to compile and then compress the project in the
mix.exs
.releases: [ example_gitlab_ci_ex: [ steps: [:assemble, :tar], applications: [runtime_tools: :permanent], include_executables_for: [:unix] ] ]
Once it’s packing up a tar we can run
mix release
and have a tar under the_build/ENV
folder. For CI purposes I added a little script to move it up to the root level and we store it in Gitlab artifacts.publish:elixir: stage: publish extends: - .elixir variables: MIX_ENV: prod ARCH: amd64 script: - mix release --overwrite - ARTIFACT_NAME="$(find . -name "example_gitlab_ci_ex-*.tar.gz" -exec basename {} .tar.gz \;)" - mv _build/prod/${ARTIFACT_NAME}.tar.gz ${ARTIFACT_NAME}-${ARCH}.tar.gz artifacts: name: "example_gitlab_ci_ex-${CI_COMMIT_REF_SLUG:-CI_COMMIT_SHA}-${ARCH}.tar.gz" paths: - example_gitlab_ci_ex-*.tar.gz rules: - if: $CI_COMMIT_TAG - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
Results
With this setup we now have an Elixir application that integrates with Gitlab running tests, linting, and publishing a release artifact that is downloadable from any server or device we want. Left as an exercise to the reader is getting the artifact downloaded but you can leverage Gitlab API’s with curl.
You can explore all the code and the integrations over in Gitlab at agundy/example_gitlab_ci_ex.
Some related things we’ve tackled you may find interesting enough to pester me to blog about include bundling static site docs into an Phoenix release and cross compiling Elixir for ARM in Gitlab CI.
- In
-
reMarkable 2 Tablet Review
November 24, 2020
Belated initial impressions on the reMarkable 2 tablet.
The hardware feels premium with a nice with a metal border, one part that really caught my eye is the asymetry of the bezel when comparing the top versus the bottom of the display. Between the premium materials and the large screen the device is heavy to hold one handed for long times.
The pencil feels good in the hand and the writing is 99% of the time fast and responsive. I say 98% because occasionally I’ve caught the UI spending a split second catching up to the writing, but this has been rare for me this far.
Planned Use Cases
I plan on using the device for:
- Writing and sketching out thoughts and ideas.
- Reading PDF’s
- Reading books as EPUB
Writing
Writing on the tablet is smooth and easy. My handwriting is roughly the same as it is on actually notebook paper unlike when I try to write with the Apple Pencil on my normal iPad.
One part of the writing experience I need to figure out still is how to handle a notebook explosion. I have created a bunch of notebooks but probably should go back down to only a few. I am unsure yet of what referencing old pages and notes will be like with the electronic setup.
Reading PDF’s
Reading PDF’s is pretty smooth, it can handle larger books and can use hyperlinks in the table of contents. There are options for configuring cropping for the view, setting landscape or portrait mode and a preview list that can be flipped through. This device has the perfect size eInk display for reading PDF’s with minimal cropping or fuss.
Obviously if you read a lot of PDF’s where color is important you will not be seeing the colors though it tries to render shades of gray.
Reading Books
EPUB support on the reMarkable needs work. I am a fan of small font for fitting a lot on a screen but the minimum font size is too large. Some EPUB’s did not load correctly and could not be read.
When changing a font or font size with EPUB book it appears to kick off a re-render of the book which can take a while to complete.
Missing Features
A relatively new and small company releasing only their second product means that it’s not all there. I’ve never used the reMarkable 1 but here are my takes on the hardware and software for the second generation device.
Selective Sync
For privacy purposes I would love to have notebooks that were guaranteed to stay on device. The software currently allows working fully offline or fully online. Fully offline means no sending notes, no handwriting to text conversion or syncing to phone.
reMarkable does not advertise information about full end to end encryption or other privacy protecting measures. Though their privacy policy does a decent job of encouraging me that the data is not being sold or used for other purposes.
Read Later Support
I have been using Pocket for years and have the apps and a huge backlog to work through. I would love to be able to read Pocket on the tablet. I have the Kobo Aura one that integrates with Pocket for reading articles on the run and love it. Instead of integrating with an existing read it later application reMarkable has made their own read it later integration that is Chrome only and because of this I have not been able to try it yet.
Better Syncing Support
reMarkable has applications for syncing in Windows and Mac OS that I have not been able to use because I only have Linux computers, so this is only a review of the experience on Linux.
Plugging in the tablet to a computers USB port does not expose a USB system with drag and drop file support in your file browser. Instead to sync to and from the tablet on Linux a toggle in the settings on the tablet advertises enabling a web server and lists and IP address that you can type into your web browser to access the tablet files and drag uploads. This interface is really rudimentary and can only handle simple upload and download tasks.
Take Aways
I am enjoying the reMarkable 2 so far it’s great hardware and I love the form factor and functionality for reading and writing. The software is promising but needs a lot of work.
-
Affirming Black Lives Matter
July 14, 2020
I am affirming that black lives matter.
Does that upset you?
Why?
It should not.
If I say your life matters does that mean your life is the only one that matters? Of course not. But right now, in American, we need to pronounce that Black Lives Matter and take a serious hard look at our systems and ensure we are making them equitable in their distribution of freedom and justice.
I encourage you to make contributions in your community to help shape a diverse and equitable future.
Since I work in technology and live in Boston, I wanted to call out two local programs: Both of these projects help support and empower Black and Latinx to break and flourish in the tech industry.
Hack.Diversity
Hack.Diversity is a high energy, positive group that I volunteered with once at BookBub. Read how you can support them here: Act in Solidarity with Hack.Diversity.
Resilient Coders
Resilient Coders is a boot camp to train people of color for careers as software engineers. I have committed to a monthly monetary donation for them and encourage you to do the same. Donate
If you have the authority and the openings both of these organizations are looking for placements for their engineers! Hire diverse tech talent, we need it.
-
Gitlab Status Bar
March 20, 2020
Augmenting my workflow and home with unobstrusive intelligent devices has long been interesting to me. My apartment is decidedly not smart but this has been a project I was thinking about for a while. I programmed a Blinkstick Strip as a display bar visualizing the status of continuous integration builds for Gitlab.
Status bar is reminiscient of the Canary monitoring project I began back in college for a class project. Originally inspired by The Mailbox Lights the idea is to translate events into a light pattern. An intriguing way to show the gestalt of a complex system.
I have a few more ideas on helpful tasks to visualize and I want spend a little more time honing the project in the future. Introduce some personal and private ambient intelligence into my workflow.
Here is another photo of the bar showcasing the running pipeline visible in browser and on the bar.
Right now the project is only a couple hours into development and not complicated but you can still check out the code I wrote on Gitlab here. Anything you think would be interesting to visualize this way?
-
Ubuntu 18.04 Thinkpad P1 Gen 2 Setup
December 16, 2019
Skylla recently set up Ubuntu 18.04 on the new Thinkpad P1 Gen 2 and had some issues with no WiFi drivers after install. Looking for a fix I found this Stack Overflow answer which pointed to the wireless driver issues. They suggested upgrading to Ubuntu 19.04 but this is not an option for work, we need the Long Term Support version.
Instead to get this working on Ubuntu 18.04 you can install a newer kernel with:
sudo apt install linux-generic-hwe-18.04-edge
After this installs reboot and WiFi should be up!