Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MicroBadger] Add MicroBadger #1340

Merged
merged 2 commits into from
Dec 7, 2017
Merged

Conversation

goozler
Copy link
Contributor

@goozler goozler commented Dec 6, 2017

Added support for MicroBadger image size and layers with ability to choose a tag (#944)

image

@goozler
Copy link
Contributor Author

goozler commented Dec 6, 2017

I've seen the pull request with CircleCI and there "flaky tests" are mentioned. To be honest, locally my new tests fail sometimes due to to a long response from the MicroBadger API (more than 2 seconds).

I don't know what the best solution in that case. I can stub every request but I saw in other PRs that you ask to add a few "live" tests, so, I need your suggestion here.

@paulmelnikow paulmelnikow added the service-badge Accepted and actionable changes, features, and bugs label Dec 6, 2017
@paulmelnikow
Copy link
Member

Hi, thanks for this!

I've seen the pull request with CircleCI and there "flaky tests" are mentioned.

I should clarify that. We want tests that hit the real services. They're unreliable by necessity. I should think of a value-neutral way to say "unreliable." 😜 There's a long discussion of the test strategy in #927.

To be honest, locally my new tests fail sometimes due to to a long response from the MicroBadger API (more than 2 seconds).

Since readme images are served through GitHub's proxy (camo) which has its own timeout, they may be unreliable there too.

We will increase the test timeout, so tests that occasionally take longer than 2s do not cause failures. This is waiting on a release of IcedFrisby which includes IcedFrisby/IcedFrisby#71 which I should wrap up!

@goozler
Copy link
Contributor Author

goozler commented Dec 6, 2017

Ok, that makes sense! So, let me know if you need something more from my side to merge it. Feel free to make notes about the code.

@paulmelnikow
Copy link
Member

Would anyone care to review this? @PyvesB @platan @chris48s

@PyvesB
Copy link
Member

PyvesB commented Dec 6, 2017

@paulmelnikow : sure, I'll take care of it later in the evening. 😉

Copy link
Member

@chris48s chris48s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for working on this. I've left some comments for things you could improve but its shaping up nicely :) Some of my comments may benefit from clarification from another reviewer.

.get('/image-size/_/httpd/alpine.json')
.expectJSONTypes(Joi.object().keys({
name: 'image size',
value: Joi.string().regex(/^[0-9]+[kMGTPEZY]B$/)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the convention for this project is that when writing a service test for a badge that uses metric(), the test should make a call that should generate a non-zero value and check the result with a regex that ensures the badge value is non-zero: /^[1-9][0-9]*[kMGTPEZY]?$/. See https://github.com/badges/shields/blob/master/service-tests/helpers/validators.js#L38-L43

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have isFileSize, though probably it should be modified to reject 0 as well!

server.js Outdated
var image;

if (tag) {
if (!parsedData['Versions']) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this project have a convention for dot-notation vs square-bracket on object properties, or we not care?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we waiting for the answer of another maintainer but personally, I use square-bracket only when the key has an uppercase first letter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For historical reasons server.js has really lax rules, and we're about to rewrite the services which will slowly empty it out. Elsewhere our code uses dots on any possible key (c.f. eslint-config-standard).

server.js Outdated
user = 'library';
}
var path = user + '/' + repo;
var url = 'https://api.microbadger.com/v1/images/' + path;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know a lot of the code in server.js uses var, but when adding new code maybe it would be better to make use of let and const where possible. For example url, repo, format etc here are declared and never re-assigned so could be declared with const. Similarly, i, j, versionJson, tagJson further down are unnecessarily defined with function scope and could be block-scoped by declaring them with let.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I'll change it. Totally makes sense. I just see that the most part uses var and the linter doesn't complain, so, I tried to be like majority :)

server.js Outdated
return;
}

if (type == 'image-size') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we compare using === here

server.js Outdated
if (type == 'image-size') {
var size = metric(image['DownloadSize']) + "B";
badgeData.text[1] = size;
} else if (type == 'layers') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and here

} else {
image = parsedData;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a chunk of logic in the middle here which parses the api response to find the latest tag. Could this be extracted to a helper?

To follow convention, you would create /lib/microbadger-helpers.js and move this bit of logic to a function getLatestTag() or getLatestVersionTag() or something. That would reduce the amount of branching/logic in this function making it easier to read and by factoring it out it would be easier to test. You could add few unit tests for it in /lib/microbadger-spec.js.

If you have a look through /lib there are some examples following this pattern that you can crib from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll take a look! Thank you for the tip. I've just seen several other services with similar complexity code but I would like to break off that code too.

@chris48s
Copy link
Member

chris48s commented Dec 6, 2017

oh, also could you rename the pull request so it is prefixed with [MicroBadger] before pushing additional commits to your branch please. That will allow the CI build to identify that it should run the tests in service-tests/microbadger.js when it runs the build. Cheers

@PyvesB
Copy link
Member

PyvesB commented Dec 6, 2017

@chris48s did you not see my comment above? I had literally almost finished my review and, as one would expect, I had picked up mostly similar comments to yours (see below for some extra points). While consecutive reviews may be valuable, there is no point in several people reviewing the exact same code at the exact same time and stepping on each other's toes. I guess I have wasted my time and can discard most of my work.

@chris48s
Copy link
Member

chris48s commented Dec 6, 2017

@PyvesB - oh no! Sorry. We must have been looking at it at the same time. Really sorry we've duplicated effort here. I'll make sure I communicate more clearly in future to avoid this :(

t.create('layers without a specified tag')
.get('/layers/_/hello-world.json')
.expectJSONTypes(Joi.object().keys({ name: 'layers',
value: Joi.number().integer()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably make this slightly more restrictive by using Joi.number().integer().positive(). Also, I believe the formatting is not entirely consistent with your other tests.

server.js Outdated
}

if (type == 'image-size') {
var size = metric(image['DownloadSize']) + "B";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use our prettyBytes helper function here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I like it

server.js Outdated
if (user === '_') {
user = 'library';
}
var path = user + '/' + repo;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be a good candidate for using template strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, why not

Copy link
Member

@paulmelnikow paulmelnikow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you @platan @chris48s for your reviews!

previewUri: '/microbadger/image-size/_/httpd.svg',
keywords: [
'docker',
'microbadger'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'microbadger' is not needed since it is in the title. Seems there are some others that should be cleaned up as well. I'd love to set up Danger to catch things like this!

},
{
title: 'MicroBadger Layers',
previewUri: '/microbadger/layers/_/httpd.svg',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does layers support tag as well? Perhaps it would be worth including a fourth example.

@goozler goozler changed the title Add MicroBadger [MicroBadger] Add MicroBadger Dec 6, 2017
@goozler
Copy link
Contributor Author

goozler commented Dec 6, 2017

Thank everyone for the review. I tried to fix all of your notes except extracting the parsing logic into a helper. I'll make an effort to do it tomorrow

@paulmelnikow
Copy link
Member

You can get CircleCI running again by merging master into this branch.

@goozler
Copy link
Contributor Author

goozler commented Dec 7, 2017

@paulmelnikow I've updated the pull request with adding a helper. I didn't add a test for it because the helper is tested already by the general tests and to be honest I'm too lazy to add something more to test the same thing. I would have liked to add it if had thought about it at the beginning of the development because it could be useful in that case.

}
}
}
return result;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm understanding correctly, this would be equivalent:

return data.Versions.find(v => v.Tags.some(t => t.tag === tag))

Since you only call it once, you could move that code to the handler and eliminate the helper.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you got it correctly. Thanks for the refs though!

@goozler
Copy link
Contributor Author

goozler commented Dec 7, 2017

@paulmelnikow I removed the helper a changed conditions a little

@paulmelnikow paulmelnikow merged commit b1ca639 into badges:master Dec 7, 2017
@paulmelnikow
Copy link
Member

Thanks for your work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
service-badge Accepted and actionable changes, features, and bugs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants