
- Build index.html at deploy time - Update corresponding documentation references - Since index.html is untracked, git add needs -f - Clarify gh-pages generated commit message - Improve Makefile dependencies related to website generation As discussed in #936, tracking the index.html causes makes PRs longer / noisier and causes extra merge conflicts. More importantly, it causes contributors to inadvertently edit the wrong file, which causes extra work (#949) or contributions to be lost (#898). Since there's no need for index.html in development (everything uses try.html) a logical solution is to generate and commit the index.html at deploy time. Recording compiled or generated files in a deploy commit is a reasonable practice for git-based deploys (Heroku, gh-pages, and others). The old version of this was slightly "unsafe" for my taste, in that it depended on the local copy of gh-pages (if it existed) and master. The new version just replaces gh-pages with master + the new commit. Closes #936. Fixes #954 (the PR).
12 KiB
Tutorial on how to add a badge for a service
This tutorial should help you add a service to shields.io in form of a badge. You will need to learn to use JavaScript, git and Github. Please improve the tutorial while you read it.
(1) Reading
You should read the following:
You can read
- previous successful pull-requests to see how other people implemented their badges. Usally they start with "add".
- later pull-requests tagged with
new-badge
. - implementations and their commits in the the server.js file.
- merged pull-requests.
(2) Setup
I suppose you have git installed. If you do not, install it and learn about the Github workflow.
- Fork this repository.
- Clone the fork
git clone git@github.com:YOURGITHUBUSERNAME/shields.git
cd shields
- Install npm and other required packages (Ubuntu 16.10)
sudo apt-get install npm nodejs-legacy curl imagemagick
- Install all packages
npm install
- Setup
make setup
- Run the server
node server.js 8080
- Visit the website to check the badges get loaded slowly:
http://[::1]:8080/try.html
(3) Open an Issue
Before you want to implement your service, you may want to open an issue and describe what you have in mind:
- What is the badge for?
- Which API do you want to use?
You may additionally proceed to say what you want to work on. This information allows other humans to help and build on your work.
(4) Implementing
If there is already a related badge, you may want to place your code next to it.
Here you can see code for a badge at route for /test/<first>/<second><ending>
.
Lines with // (1)
and alike are commented below.
// Test integration.
camp.route(/^\/test\/([^\/]+)\/([^\/]+)\.(svg|png|gif|jpg|json)$/, // (1)
cache(function(data, match, sendBadge, request) {
var first = match[1]; // (2)
var second = match[2]; // (2)
var format = match[3]; // (2)
var badgeData = getBadgeData('X' + first + 'X', data); // (3)
badgeData.text[1] = second; // (4)
badgeData.colorscheme = 'blue'; // (4)
badgeData.colorB = '#008bb8'; // (4)
sendBadge(format, badgeData); // (5)
}));
Description of the code:
- This is the route specified as regular expression.
- These lines parse the route given in (1).
- This requests a default configuration for the badge.
- These lines customize the design of the badge. Possible attributes are specified.
- This line sends the response back to the browser.
To try out this custom badge do the following:
- Copy and paste these lines into server.js. I did this at about line 5000.
- Quit the running server with
Control+C
. - Start the server again.
node server.js 8080
- Visit the badge at http://[::1]:8080/test/subject/STATUS.svg.
It should look like this:
(4.1) Querying an API
Make sure, you can get the data somehow, best as JSON. There might be an API for your service delivering the data.
The test badge above is quite simple and static. You can change the behavior by asking your API. There are various examples on how to answer with a customized badge:
This example is the for the Docker Hub automated integration. (Source)
// Docker Hub automated integration. // (1)
camp.route(/^\/docker\/automated\/([^\/]+)\/([^\/]+)\.(svg|png|gif|jpg|json)$/, // (2)
cache(function(data, match, sendBadge, request) { // (2)
var user = match[1]; // eg, jrottenberg // (3)
var repo = match[2]; // eg, ffmpeg // (3)
var format = match[3]; // (3)
if (user === '_') { // (4)
user = 'library'; // (4)
} // (4)
var path = user + '/' + repo; // (4)
var url = 'https://registry.hub.docker.com/v2/repositories/' + path; // (4)
var badgeData = getBadgeData('docker build', data); // (5)
request(url, function(err, res, buffer) { // (6)
if (err != null) { // (7)
badgeData.text[1] = 'inaccessible'; // (7)
sendBadge(format, badgeData); // (7)
return; // (7)
}
try {
var data = JSON.parse(buffer); // (8)
var is_automated = data.is_automated; // (8)
if (is_automated) {
badgeData.text[1] = 'automated'; // (9)
badgeData.colorscheme = 'blue'; // (9)
} else {
badgeData.text[1] = 'manual'; // (9)
badgeData.colorscheme = 'yellow'; // (9)
}
badgeData.colorB = '#008bb8'; // (9)
sendBadge(format, badgeData); // (9)
} catch(e) { // (10)
badgeData.text[1] = 'invalid'; // (10)
sendBadge(format, badgeData); // (10)
}
});
}));
The source code is annotated with // (1)
and alike on the right side.
The following numbering explains what happens in the corresponding lines.
- All badges are preceded by a comment. This allows other developers to find the badge regardless of implementation. Usally, badges with an similar topic have their implementation close to each other's.
- The regular expression matches the path behind the host name in the URL, e.g.
img.shields.io
.
Example: https://img.shields.io/docker/automated/jrottenberg/ffmpeg.svg/^\/docker\/automated\/([^\/]+)\/([^\/]+)\.(svg|png|gif|jpg|json)$/ \.(svg|png|gif|jpg|json) The supported endings e.g. ".svg" ([^\/]+)\/([^\/]+) The name of the repository e.g. "jrottenberg/ffmpeg" \/docker\/automated\/ "/docker/automated/" is the start of the url. "/" must be escaped to "\/".
All parts are enclosed by brackets()
are passed though to the function as the parametermatch
. - The parts of the match are named.
- Based on the input parameters, we construct our query to the API.
Here,
"_"
is a special case. Theurl
is created to query the API. - Create the basic badge to use. You can read about the different formats available. It contains the format for all responses, regarless of the API's response.
- We request the
url
and pass a call back function to the request. The function is called once the data is retrieved from the API. - We want to always see a badge regardless the input.
In some cases the API may return an error e.g. if the query was invalid.
The error is handled and a badge with the the status "inaccessible" is returned.
- The data returned by the API as JSON is parsed.
- Based on the result, the text and the color of the badge are altered.
- In case of an error, an "invalid" badge is constructed.
The pattern described can be found in may other badges. When you look at the server.js, you find many other badges. Some of them may query the same API. Those can be of additional help when implementing your badge.
(4.2) Querying an API with Authentication
TODO
This has something to do with private/secret.json.
- Credentials should be stored there.
- You do not need to create this file, the server works without.
- Somewhere the format (JSON? Keys?) should be documented.
- How to get the keys?
(4.3) Add Badges to Front Page
Once you are done implementing your badge, you can add it to the collection on shields.io.
First, we make it visible on http://[::1]:8080/try.html. Edit try.html in the right section (Build, Downloads, ...) and add your badge:
<tr><th data-keywords='test badge keywords for google'>Test Badge from the tutorial</th>
<td><img src='/test/subject/STATUS.svg' alt=''/></td>
<td><code>https://img.shields.io/test/subject/STATUS.svg</code></td>
</tr>
Save, restart and you can see it locally.
(5) Create a Pull Request
You have implemented changes in server.js
, try.html
and index.html
.
These changes shall go live on shields.io.
To do that, create a pull-request.
By doing this, your changes are made public to the shields team.
You can respond to their questions and the badge may soon be merged.
Further Reading
These files can also be of help for creating your own badge.