{"action":"created","comment":{"url":"https://api.github.com/repos/npm/newww/pulls/comments/27906722","id":27906722,"diff_hunk":"@@ -508,7 +508,7 @@ describe(\"package access\", function(){\n       };\n \n       before(function(done) {\n-        process.env.FEATURE_ACCESS = 'true';\n+        process.env.FEATURE_ACCESS_PAGE = 'true';\n         server.inject(options, function(response) {\n           resp = response;\n           context = resp.request.response.source.context;","path":"test/handlers/access.js","position":112,"original_position":112,"commit_id":"9ca3b8ab56e4b0079ea30acdbe5072fce6720d73","original_commit_id":"9ca3b8ab56e4b0079ea30acdbe5072fce6720d73","user":{"login":"rockbot","id":954269,"avatar_url":"https://avatars.githubusercontent.com/u/954269?v=3","gravatar_id":"","url":"https://api.github.com/users/rockbot","html_url":"https://github.com/rockbot","followers_url":"https://api.github.com/users/rockbot/followers","following_url":"https://api.github.com/users/rockbot/following{/other_user}","gists_url":"https://api.github.com/users/rockbot/gists{/gist_id}","starred_url":"https://api.github.com/users/rockbot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rockbot/subscriptions","organizations_url":"https://api.github.com/users/rockbot/orgs","repos_url":"https://api.github.com/users/rockbot/repos","events_url":"https://api.github.com/users/rockbot/events{/privacy}","received_events_url":"https://api.github.com/users/rockbot/received_events","type":"User","site_admin":false},"body":"do you want to `delete process.env.FEATURE_ACCESS_PAGE` in an after block somewhere?","created_at":"2015-04-07T18:33:50Z","updated_at":"2015-04-07T18:33:50Z","html_url":"https://github.com/npm/newww/pull/806#discussion_r27906722","pull_request_url":"https://api.github.com/repos/npm/newww/pulls/806","_links":{"self":{"href":"https://api.github.com/repos/npm/newww/pulls/comments/27906722"},"html":{"href":"https://github.com/npm/newww/pull/806#discussion_r27906722"},"pull_request":{"href":"https://api.github.com/repos/npm/newww/pulls/806"}}},"pull_request":{"url":"https://api.github.com/repos/npm/newww/pulls/806","id":32557145,"html_url":"https://github.com/npm/newww/pull/806","diff_url":"https://github.com/npm/newww/pull/806.diff","patch_url":"https://github.com/npm/newww/pull/806.patch","issue_url":"https://api.github.com/repos/npm/newww/issues/806","number":806,"state":"open","locked":false,"title":"feature flags","user":{"login":"zeke","id":2289,"avatar_url":"https://avatars.githubusercontent.com/u/2289?v=3","gravatar_id":"","url":"https://api.github.com/users/zeke","html_url":"https://github.com/zeke","followers_url":"https://api.github.com/users/zeke/followers","following_url":"https://api.github.com/users/zeke/following{/other_user}","gists_url":"https://api.github.com/users/zeke/gists{/gist_id}","starred_url":"https://api.github.com/users/zeke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zeke/subscriptions","organizations_url":"https://api.github.com/users/zeke/orgs","repos_url":"https://api.github.com/users/zeke/repos","events_url":"https://api.github.com/users/zeke/events{/privacy}","received_events_url":"https://api.github.com/users/zeke/received_events","type":"User","site_admin":false},"body":"This PR allows feature flags to be configured entirely through environment variables, and sets up some groups in code: `npm-humans` and `friends` for starters. Some examples:\r\n\r\n- Disable for everyone: `process.env.FEATURE_FOO=false`\r\n- Enable for everyone: `process.env.FEATURE_FOO=true`\r\n- Enable for bob only: `process.env.FEATURE_FOO=bob`\r\n- Enable for bob and everyone at npm: `process.env.FEATURE_FOO=bob,group:npm-humans`\r\n- Enable for bob, everyone at npm, and some friends: `process.env.FEATURE_FOO=bob,group:npm-humans,group:friends`\r\n\r\n## Usage\r\n\r\nIn any request handler:\r\n\r\n```js\r\nif (request.features.foo) {\r\n  console.log(\"foo stuff here\")\r\n}\r\n```\r\n\r\nIn a template:\r\n\r\n```hbs\r\n{{#if features.foo}}\r\n  <blink>welcome to foo country</blink>\r\n{{/if}\r\n```\r\n\r\n## How it works\r\n\r\nThere's a hapi `onPreHandler` method that iterates over all the environment variables and checks whether to enable them for the current request. Given the following environment variables:\r\n\r\n```\r\nprocess.env.FEATURE_STEALTH = 'false'\r\nprocess.env.FEATURE_ALPHA = 'group:npm-humans'\r\nprocess.env.FEATURE_BETA = 'group:npm-humans,group:friends,bob'\r\nprocess.env.FEATURE_COMMON = 'true'\r\n```\r\n\r\nand an incoming request from a logged-in npm employee, the `request.features` object looks like this:\r\n\r\n```js\r\n{\r\n  stealth: false,\r\n  alpha: true,\r\n  beta: true,\r\n  common: true\r\n}\r\n```\r\n\r\n## Requirements\r\n\r\n- env vars should always be uppercase and start with  `FEATURE_`\r\n- all properties on the generated `features` object are booleans, and their key is the lowercased name of the env var, minus the `FEATURE_` prefix\r\n- whitelisted users are delimited by commas. Space after the comma is optional\r\n- to whitelist a whole group, use the `group:` prefix: `group:npm-humans`. Current extant groups are `npm-humans` and `friends`. This can be customized in `../lib/feature-flags`.\r\n\r\n## Tests\r\n\r\n```\r\nfeature flags\r\n  enabled\r\n    ✔ 1) returns true if variable is 'true' (4 ms)\r\n    ✔ 2) returns true if variable is 'TRUE' (1 ms)\r\n    ✔ 3) allows lowercase values (1 ms)\r\n    ✔ 4) allows feature name to include `feature_` prefix (0 ms)\r\n  disabled\r\n    ✔ 5) returns false if variable does not exist (0 ms)\r\n    ✔ 6) returns false if variable is an empty string (0 ms)\r\n    ✔ 7) returns false if variable is 'false' (0 ms)\r\n    ✔ 8) returns false if variable is 'FALSE' (0 ms)\r\n  whitelisted users\r\n    ✔ 9) returns true for whitelisted users (1 ms)\r\n    ✔ 10) returns false for users not in whitelist (0 ms)\r\n    ✔ 11) returns false for anonymous users (0 ms)\r\n    ✔ 12) returns false if request object is absent (0 ms)\r\n  whitelisted groups\r\n    ✔ 13) returns true for npm humans (0 ms)\r\n    ✔ 14) returns true for friends (0 ms)\r\n    ✔ 15) returns true for one-off users (1 ms)\r\n    ✔ 16) returns false for users not in whitelist (1 ms)\r\n    ✔ 17) returns false if request object is absent (0 ms)\r\n\r\nbonbon\r\n  feature flags\r\n    ✔ 24) gives anonymous users access to common features (16 ms)\r\n    ✔ 25) gives people in the friends group access to beta and common features (19 ms)\r\n    ✔ 26) gives one-off listed friends access to beta and common features (11 ms)\r\n    ✔ 27) gives npm employees access to alpha, beta, and common features (18 ms)\r\n```","created_at":"2015-04-02T22:38:33Z","updated_at":"2015-04-07T18:33:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2254841f03c303c866959e30b6b0e30508e88c56","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/npm/newww/pulls/806/commits","review_comments_url":"https://api.github.com/repos/npm/newww/pulls/806/comments","review_comment_url":"https://api.github.com/repos/npm/newww/pulls/comments{/number}","comments_url":"https://api.github.com/repos/npm/newww/issues/806/comments","statuses_url":"https://api.github.com/repos/npm/newww/statuses/9ca3b8ab56e4b0079ea30acdbe5072fce6720d73","head":{"label":"npm:granular-feature-flags","ref":"granular-feature-flags","sha":"9ca3b8ab56e4b0079ea30acdbe5072fce6720d73","user":{"login":"npm","id":6078720,"avatar_url":"https://avatars.githubusercontent.com/u/6078720?v=3","gravatar_id":"","url":"https://api.github.com/users/npm","html_url":"https://github.com/npm","followers_url":"https://api.github.com/users/npm/followers","following_url":"https://api.github.com/users/npm/following{/other_user}","gists_url":"https://api.github.com/users/npm/gists{/gist_id}","starred_url":"https://api.github.com/users/npm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/npm/subscriptions","organizations_url":"https://api.github.com/users/npm/orgs","repos_url":"https://api.github.com/users/npm/repos","events_url":"https://api.github.com/users/npm/events{/privacy}","received_events_url":"https://api.github.com/users/npm/received_events","type":"Organization","site_admin":false},"repo":{"id":19872239,"name":"newww","full_name":"npm/newww","owner":{"login":"npm","id":6078720,"avatar_url":"https://avatars.githubusercontent.com/u/6078720?v=3","gravatar_id":"","url":"https://api.github.com/users/npm","html_url":"https://github.com/npm","followers_url":"https://api.github.com/users/npm/followers","following_url":"https://api.github.com/users/npm/following{/other_user}","gists_url":"https://api.github.com/users/npm/gists{/gist_id}","starred_url":"https://api.github.com/users/npm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/npm/subscriptions","organizations_url":"https://api.github.com/users/npm/orgs","repos_url":"https://api.github.com/users/npm/repos","events_url":"https://api.github.com/users/npm/events{/privacy}","received_events_url":"https://api.github.com/users/npm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/npm/newww","description":"The npm website","fork":false,"url":"https://api.github.com/repos/npm/newww","forks_url":"https://api.github.com/repos/npm/newww/forks","keys_url":"https://api.github.com/repos/npm/newww/keys{/key_id}","collaborators_url":"https://api.github.com/repos/npm/newww/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/npm/newww/teams","hooks_url":"https://api.github.com/repos/npm/newww/hooks","issue_events_url":"https://api.github.com/repos/npm/newww/issues/events{/number}","events_url":"https://api.github.com/repos/npm/newww/events","assignees_url":"https://api.github.com/repos/npm/newww/assignees{/user}","branches_url":"https://api.github.com/repos/npm/newww/branches{/branch}","tags_url":"https://api.github.com/repos/npm/newww/tags","blobs_url":"https://api.github.com/repos/npm/newww/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/npm/newww/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/npm/newww/git/refs{/sha}","trees_url":"https://api.github.com/repos/npm/newww/git/trees{/sha}","statuses_url":"https://api.github.com/repos/npm/newww/statuses/{sha}","languages_url":"https://api.github.com/repos/npm/newww/languages","stargazers_url":"https://api.github.com/repos/npm/newww/stargazers","contributors_url":"https://api.github.com/repos/npm/newww/contributors","subscribers_url":"https://api.github.com/repos/npm/newww/subscribers","subscription_url":"https://api.github.com/repos/npm/newww/subscription","commits_url":"https://api.github.com/repos/npm/newww/commits{/sha}","git_commits_url":"https://api.github.com/repos/npm/newww/git/commits{/sha}","comments_url":"https://api.github.com/repos/npm/newww/comments{/number}","issue_comment_url":"https://api.github.com/repos/npm/newww/issues/comments{/number}","contents_url":"https://api.github.com/repos/npm/newww/contents/{+path}","compare_url":"https://api.github.com/repos/npm/newww/compare/{base}...{head}","merges_url":"https://api.github.com/repos/npm/newww/merges","archive_url":"https://api.github.com/repos/npm/newww/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/npm/newww/downloads","issues_url":"https://api.github.com/repos/npm/newww/issues{/number}","pulls_url":"https://api.github.com/repos/npm/newww/pulls{/number}","milestones_url":"https://api.github.com/repos/npm/newww/milestones{/number}","notifications_url":"https://api.github.com/repos/npm/newww/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/npm/newww/labels{/name}","releases_url":"https://api.github.com/repos/npm/newww/releases{/id}","created_at":"2014-05-16T22:12:47Z","updated_at":"2015-04-06T19:56:16Z","pushed_at":"2015-04-07T04:05:19Z","git_url":"git://github.com/npm/newww.git","ssh_url":"git@github.com:npm/newww.git","clone_url":"https://github.com/npm/newww.git","svn_url":"https://github.com/npm/newww","homepage":"http://npmjs.com","size":13890,"stargazers_count":282,"watchers_count":282,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":87,"mirror_url":null,"open_issues_count":126,"forks":87,"open_issues":126,"watchers":282,"default_branch":"master"}},"base":{"label":"npm:r2","ref":"r2","sha":"efb6d1ff66650b0fe8239f2853640d8207d60322","user":{"login":"npm","id":6078720,"avatar_url":"https://avatars.githubusercontent.com/u/6078720?v=3","gravatar_id":"","url":"https://api.github.com/users/npm","html_url":"https://github.com/npm","followers_url":"https://api.github.com/users/npm/followers","following_url":"https://api.github.com/users/npm/following{/other_user}","gists_url":"https://api.github.com/users/npm/gists{/gist_id}","starred_url":"https://api.github.com/users/npm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/npm/subscriptions","organizations_url":"https://api.github.com/users/npm/orgs","repos_url":"https://api.github.com/users/npm/repos","events_url":"https://api.github.com/users/npm/events{/privacy}","received_events_url":"https://api.github.com/users/npm/received_events","type":"Organization","site_admin":false},"repo":{"id":19872239,"name":"newww","full_name":"npm/newww","owner":{"login":"npm","id":6078720,"avatar_url":"https://avatars.githubusercontent.com/u/6078720?v=3","gravatar_id":"","url":"https://api.github.com/users/npm","html_url":"https://github.com/npm","followers_url":"https://api.github.com/users/npm/followers","following_url":"https://api.github.com/users/npm/following{/other_user}","gists_url":"https://api.github.com/users/npm/gists{/gist_id}","starred_url":"https://api.github.com/users/npm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/npm/subscriptions","organizations_url":"https://api.github.com/users/npm/orgs","repos_url":"https://api.github.com/users/npm/repos","events_url":"https://api.github.com/users/npm/events{/privacy}","received_events_url":"https://api.github.com/users/npm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/npm/newww","description":"The npm website","fork":false,"url":"https://api.github.com/repos/npm/newww","forks_url":"https://api.github.com/repos/npm/newww/forks","keys_url":"https://api.github.com/repos/npm/newww/keys{/key_id}","collaborators_url":"https://api.github.com/repos/npm/newww/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/npm/newww/teams","hooks_url":"https://api.github.com/repos/npm/newww/hooks","issue_events_url":"https://api.github.com/repos/npm/newww/issues/events{/number}","events_url":"https://api.github.com/repos/npm/newww/events","assignees_url":"https://api.github.com/repos/npm/newww/assignees{/user}","branches_url":"https://api.github.com/repos/npm/newww/branches{/branch}","tags_url":"https://api.github.com/repos/npm/newww/tags","blobs_url":"https://api.github.com/repos/npm/newww/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/npm/newww/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/npm/newww/git/refs{/sha}","trees_url":"https://api.github.com/repos/npm/newww/git/trees{/sha}","statuses_url":"https://api.github.com/repos/npm/newww/statuses/{sha}","languages_url":"https://api.github.com/repos/npm/newww/languages","stargazers_url":"https://api.github.com/repos/npm/newww/stargazers","contributors_url":"https://api.github.com/repos/npm/newww/contributors","subscribers_url":"https://api.github.com/repos/npm/newww/subscribers","subscription_url":"https://api.github.com/repos/npm/newww/subscription","commits_url":"https://api.github.com/repos/npm/newww/commits{/sha}","git_commits_url":"https://api.github.com/repos/npm/newww/git/commits{/sha}","comments_url":"https://api.github.com/repos/npm/newww/comments{/number}","issue_comment_url":"https://api.github.com/repos/npm/newww/issues/comments{/number}","contents_url":"https://api.github.com/repos/npm/newww/contents/{+path}","compare_url":"https://api.github.com/repos/npm/newww/compare/{base}...{head}","merges_url":"https://api.github.com/repos/npm/newww/merges","archive_url":"https://api.github.com/repos/npm/newww/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/npm/newww/downloads","issues_url":"https://api.github.com/repos/npm/newww/issues{/number}","pulls_url":"https://api.github.com/repos/npm/newww/pulls{/number}","milestones_url":"https://api.github.com/repos/npm/newww/milestones{/number}","notifications_url":"https://api.github.com/repos/npm/newww/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/npm/newww/labels{/name}","releases_url":"https://api.github.com/repos/npm/newww/releases{/id}","created_at":"2014-05-16T22:12:47Z","updated_at":"2015-04-06T19:56:16Z","pushed_at":"2015-04-07T04:05:19Z","git_url":"git://github.com/npm/newww.git","ssh_url":"git@github.com:npm/newww.git","clone_url":"https://github.com/npm/newww.git","svn_url":"https://github.com/npm/newww","homepage":"http://npmjs.com","size":13890,"stargazers_count":282,"watchers_count":282,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":87,"mirror_url":null,"open_issues_count":126,"forks":87,"open_issues":126,"watchers":282,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/npm/newww/pulls/806"},"html":{"href":"https://github.com/npm/newww/pull/806"},"issue":{"href":"https://api.github.com/repos/npm/newww/issues/806"},"comments":{"href":"https://api.github.com/repos/npm/newww/issues/806/comments"},"review_comments":{"href":"https://api.github.com/repos/npm/newww/pulls/806/comments"},"review_comment":{"href":"https://api.github.com/repos/npm/newww/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/npm/newww/pulls/806/commits"},"statuses":{"href":"https://api.github.com/repos/npm/newww/statuses/9ca3b8ab56e4b0079ea30acdbe5072fce6720d73"}}}}