Skip to content

Commit ecf41ce

Browse files
authored
Blog: "Add Badge" (#46)
* wip * chore: start new blog * feat: progress on add-badge blog * feat: progress on add-badge blog * chore: remove forced width to not distort image * chore: reword * chore: reword
1 parent 731a247 commit ecf41ce

File tree

7 files changed

+103
-0
lines changed

7 files changed

+103
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
slug: 2024/introducing-add-badge
3+
title: Introducing Add Badge - an overlay badge plugin.
4+
authors: [connort, erikp]
5+
tags: [nodejs, wasm, imagick, badge, badging, fastlane]
6+
---
7+
8+
import ImageRow from '@site/src/components/ImageRow';
9+
10+
As our application pipeline elevated into ephemeral GitHub Action containers the Fastlane plugin codenamed "[badge](https://github.com/HazAT/badge)" we used was showing some age. It depended on a few native dependencies and took a bit of time to install on our runners. We saw this chance to leverage some exciting new technology and produce an alternative.
11+
12+
{/* truncate */}
13+
14+
For context badging is the art of adding little ribbons around your application icon to more easily denote different builds (Beta/Alpha) during development. Thus, in late 2015 when [Fastlane](https://fastlane.tools/) was exploding in popularity to automate application builds - we found success using the badge plugin.
15+
16+
import oldBadge1 from './old-badge.png';
17+
import oldBadge2 from './old-badge-2.png';
18+
19+
<ImageRow
20+
images={[
21+
{src: oldBadge1, alt: 'Old Badge #1'},
22+
{src: oldBadge2, alt: 'Old Badge #2'}
23+
]}
24+
/>
25+
26+
It was great for almost an entire decade, but like some software it showed some sign of decay. We noticed that as our build machines evolved packages like Librsvg and ImageMagick had compatibility issues. We got to work envisioning a new plugin to badge our applications.
27+
28+
We knew the power behind ImageMagick, and we wanted to stick with it, but we wanted to leverage the tool without the effort of installing binaries onto runners. Thankfully WASM (WebAssembly) had matured as a solution for this. We found an open source library called [magick-wasm](https://github.com/dlemstra/magick-wasm). It offered an elegant API to work with ImageMagick leveraging a WASM implementation for the ImageMagick binary itself.
29+
30+
:::tip
31+
WebAssembly (WASM) is a binary code format that serves as a portable compilation target for programs, enabling high-performance applications to run on web browsers at near-native speed.
32+
:::
33+
34+
This meant we could write code familiar to us in Node.js while using the power of WASM in one common codebase.
35+
36+
```ts
37+
import { readFileSync } from 'node:fs';
38+
import { initializeImageMagick, Magick } from '@imagemagick/magick-wasm';
39+
40+
const wasmBytes = readFileSync(
41+
require.resolve('@imagemagick/magick-wasm/magick.wasm'),
42+
);
43+
initializeImageMagick(wasmBytes).then(() => {
44+
console.log(Magick.imageMagickVersion);
45+
});
46+
```
47+
48+
With a few short lines of code we were moving and a library was being born. We wanted to keep the behavior we were used to which allowed us to bulk edit images and modify them in place. Our use-case would be a build pipeline changing a variety of Android and iOS images to badge the Beta builds. The features our plugin offered expanded towards:
49+
50+
* Changing the font size, color and font itself.
51+
* Controlling the background color or shadow color.
52+
* Controlling the position and gravity of the badge.
53+
* Supporting a dry run mode
54+
55+
With a few pull requests ([#69](https://github.com/dlemstra/magick-wasm/pull/69) and [#70](https://github.com/dlemstra/magick-wasm/pull/70)) upstream to the magick-wasm library and a bit of development we had a good proof of concept.
56+
57+
import newBadge1 from './new-badge-1.png';
58+
import newBadge2 from './new-badge-2.png';
59+
60+
<ImageRow
61+
images={[
62+
{src: newBadge1, alt: 'New Badge #1'},
63+
{src: newBadge2, alt: 'New Badge #2'}
64+
]}
65+
/>
66+
67+
We could handle circles or squares as the logic checks the insets and width to place the ribbon correctly. We test drove a few of our client applications to confirm their specific logos worked and once we worked out a few edge cases we were happy with it.
68+
69+
Thus, [add-badge](https://github.com/sourcetoad/add-badge) was born. An open source package intended for build pipelines to badge applications.
70+
71+
* [Icon Samples](https://github.com/sourcetoad/add-badge/blob/master/SAMPLES.md)
72+
* [GitHub Repo](https://github.com/sourcetoad/add-badge)
73+
* [npmjs](https://www.npmjs.com/package/@sourcetoad/add-badge)
10.7 KB
Loading
16.8 KB
Loading
15.1 KB
Loading
20.6 KB
Loading

blog/authors.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ justinw:
99
title: CTO
1010
url: https://github.com/jweberst
1111
image_url: https://github.com/jweberst.png
12+
13+
erikp:
14+
name: Erik Perri
15+
title: Senior Software Engineer II
16+
url: https://github.com/erik-perri
17+
image_url: https://github.com/erik-perri.png

src/components/ImageRow.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
3+
interface ImageProps {
4+
src: string;
5+
alt?: string;
6+
}
7+
8+
interface ImageRowProps {
9+
images: ImageProps[];
10+
}
11+
12+
export default function ImageRow({ images }: ImageRowProps) {
13+
return (
14+
<div style={{ display: 'flex', justifyContent: 'space-evenly', marginBottom: '1rem' }}>
15+
{images.map((image) => (
16+
<img
17+
key={image.src}
18+
src={image.src}
19+
alt={image.alt || ''}
20+
/>
21+
))}
22+
</div>
23+
);
24+
}

0 commit comments

Comments
 (0)