[deploy] Decouple GitHub authentication from fetching GitHub issues (#7660)
* Improve error handling * Add tests for Github::Client * Add GithubIssue validation * Refactor GithubIssue and fix bug with pull requests * Improve tests * Fix PR API URL generation * Improve logic and get rid of the issue fragment * Fix disappeared avatar * Improve rendering * Activate client side caching using Redis * Remove unnecessary file * Add RemoveGithubIssues data update script * Fix comma * Forgot to disable the approvals verify text * Apply PR feedback
This commit is contained in:
parent
f75bcf8673
commit
ae8a58fec2
22 changed files with 1177 additions and 357 deletions
4
Envfile
4
Envfile
|
|
@ -48,8 +48,8 @@ variable :FORCE_SSL_IN_RAILS, :String, default: "not applicable in dev"
|
|||
|
||||
# Github for github related access
|
||||
# (https://developer.github.com/v3/guides/basics-of-authentication/)
|
||||
variable :GITHUB_KEY, :String, default: "Optional"
|
||||
variable :GITHUB_SECRET, :String, default: "Optional"
|
||||
variable :GITHUB_KEY, :String, default: ""
|
||||
variable :GITHUB_SECRET, :String, default: ""
|
||||
|
||||
# Twitter for normal twitter access
|
||||
# (https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens)
|
||||
|
|
|
|||
1
Gemfile
1
Gemfile
|
|
@ -38,6 +38,7 @@ gem "elasticsearch", "~> 7.6" # Powers DEVs core search functionality
|
|||
gem "email_validator", "~> 2.0" # Email validator for Rails and ActiveModel
|
||||
gem "emoji_regex", "~> 3.0" # A pair of Ruby regular expressions for matching Unicode Emoji symbols
|
||||
gem "envied", "~> 0.9" # Ensure presence and type of your app's ENV-variables
|
||||
gem "faraday-http-cache", "~> 2.2" # Middleware to handle HTTP caching
|
||||
gem "fast_jsonapi", "~> 1.5" # Serializer for Ruby objects
|
||||
gem "fastly", "~> 2.5" # Client library for the Fastly acceleration system
|
||||
gem "feedjira", "~> 3.1" # A feed fetching and parsing library
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ GEM
|
|||
i18n (>= 1.6, < 2)
|
||||
faraday (1.0.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-http-cache (2.2.0)
|
||||
faraday (>= 0.8)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fast_jsonapi (1.5)
|
||||
|
|
@ -880,6 +882,7 @@ DEPENDENCIES
|
|||
exifr (>= 1.3.6)
|
||||
factory_bot_rails (~> 5.2)
|
||||
faker (~> 2.11)
|
||||
faraday-http-cache (~> 2.2)
|
||||
fast_jsonapi (~> 1.5)
|
||||
fastly (~> 2.5)
|
||||
feedjira (~> 3.1)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@import 'variables';
|
||||
|
||||
.ltag_github-liquid-tag {
|
||||
margin: 1.1em auto 1.3em;
|
||||
max-width: 580px;
|
||||
|
|
@ -95,19 +96,19 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
img.github-liquid-tag-img {
|
||||
.github-liquid-tag-img {
|
||||
min-height: inherit;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 3px;
|
||||
float: none;
|
||||
padding: 10px 0 10px 12px;
|
||||
padding: 10px 12px 10px 0px;
|
||||
margin: inherit;
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
float: left;
|
||||
padding: 0;
|
||||
margin-left: -75px;
|
||||
margin-left: -9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
# GithubTag generates the following api links
|
||||
# GithubTag generates the following API links:
|
||||
# getting an issue
|
||||
# https://api.github.com/repos/facebook/react/issues/9218
|
||||
# getting comments of an issue
|
||||
# https://api.github.com/repos/facebook/react/issues/9218/comments
|
||||
# getting exat comment of an issue
|
||||
# getting a pull request
|
||||
# https://api.github.com/repos/facebook/react/pulls/14105
|
||||
# getting a comment belonging to an issue
|
||||
# https://api.github.com/repos/facebook/react/issues/comments/287635042
|
||||
class GithubTag
|
||||
class GithubIssueTag
|
||||
PARTIAL = "liquids/github_issue".freeze
|
||||
API_BASE_ENDPOINT = "https://api.github.com/repos/".freeze
|
||||
|
||||
def initialize(link)
|
||||
@orig_link = link
|
||||
@link = parse_link(link)
|
||||
@content = GithubIssue.find_or_fetch(@link)
|
||||
@content_json = @content.issue_serialized
|
||||
@is_issue = @content_json[:title].present?
|
||||
@created_at = @content_json[:created_at]
|
||||
@body = @content.processed_html.html_safe
|
||||
end
|
||||
|
||||
|
|
@ -21,20 +24,24 @@ class GithubTag
|
|||
ActionController::Base.new.render_to_string(
|
||||
partial: PARTIAL,
|
||||
locals: {
|
||||
title: @content_json[:title],
|
||||
issue_number: @content_json[:number],
|
||||
user_html_url: @content_json[:user][:html_url],
|
||||
body: @body,
|
||||
created_at: @created_at.rfc3339,
|
||||
date: @created_at.utc.strftime("%b %d, %Y"),
|
||||
html_url: @content_json[:html_url],
|
||||
issue_number: issue_number,
|
||||
tagline: tagline,
|
||||
title: title,
|
||||
user_avatar_url: @content_json[:user][:avatar_url],
|
||||
username: @content_json[:user][:login],
|
||||
date_link: @content_json[:html_url],
|
||||
date: Time.zone.parse(@content_json[:created_at].to_s).utc.strftime("%b %d, %Y"),
|
||||
body: @body
|
||||
user_html_url: @content_json[:user][:html_url],
|
||||
username: @content_json[:user][:login]
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :content_json
|
||||
|
||||
def parse_link(link)
|
||||
link = ActionController::Base.helpers.strip_tags(link)
|
||||
link_no_space = link.delete(" ")
|
||||
|
|
@ -46,9 +53,29 @@ class GithubTag
|
|||
end
|
||||
|
||||
def generate_api_link(input)
|
||||
input = input.gsub(/\?.*/, "")
|
||||
input = input.gsub(/\d{1,}#issuecomment-/, "comments/") if input.include?("#issuecomment-")
|
||||
"https://api.github.com/repos/#{input.gsub(/.*github\.com\//, '')}"
|
||||
uri = URI.parse(input).normalize
|
||||
uri.host = nil if uri.host == "github.com"
|
||||
|
||||
# public PRs URLs are "/pull/{id}" but the API requires "/pulls/{id}"
|
||||
uri.path = uri.path.gsub(%r{/pull/}, "/pulls/")
|
||||
|
||||
# public comments URLs are "/issues/{id}#issuecomment-{comment_id}"
|
||||
# or "/pull/{id}#issuecomment-{comment_id}"
|
||||
# but the API requires "/issues/comments/{comment_id}"
|
||||
if uri.fragment&.start_with?("issuecomment-")
|
||||
uri.path = uri.path.gsub(%r{(issues|pulls)/\d+}, "issues/comments/")
|
||||
comment_id = uri.fragment.split("-").last
|
||||
uri.merge!(comment_id)
|
||||
end
|
||||
|
||||
# fragments and query params are not needed in the API call
|
||||
uri.fragment = nil
|
||||
uri.query = nil
|
||||
|
||||
# remove leading forward slash in the path
|
||||
path = uri.path.sub(%r{\A/}, "")
|
||||
|
||||
URI.parse(API_BASE_ENDPOINT).merge(path).to_s
|
||||
end
|
||||
|
||||
def finalize_html(input)
|
||||
|
|
@ -68,7 +95,19 @@ class GithubTag
|
|||
end
|
||||
|
||||
def raise_error
|
||||
raise StandardError, "Invalid Github issue link"
|
||||
raise StandardError, "Invalid GitHub issue, pull request or comment link"
|
||||
end
|
||||
|
||||
def title
|
||||
content_json[:title] || "Comment for"
|
||||
end
|
||||
|
||||
def issue_number
|
||||
@issue_number ||= content_json[:number] || content_json[:issue_url].split("/").last
|
||||
end
|
||||
|
||||
def tagline
|
||||
@is_issue ? "posted on" : "commented on"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,65 +1,78 @@
|
|||
# NOTE: we are using `GithubIssue` to store issues, pull requests and comments
|
||||
class GithubIssue < ApplicationRecord
|
||||
CATEGORIES = %w[issue issue_comment].freeze
|
||||
API_URL_REGEXP = %r{\Ahttps://api.github.com/repos/.*\z}.freeze
|
||||
PATH_COMMENT_REGEXP = %r{/issues/comments/}.freeze
|
||||
PATH_ISSUE_REGEXP = %r{/issues/}.freeze
|
||||
PATH_PULL_REQUEST_REGEXP = %r{/pulls/}.freeze
|
||||
PATH_REPO_REGEXP = %r{.*github.com/repos/}.freeze
|
||||
|
||||
serialize :issue_serialized, Hash
|
||||
validates :category, inclusion: { in: %w[issue issue_comment] }
|
||||
|
||||
def self.find_or_fetch(url)
|
||||
find_by(url: url) || fetch(url)
|
||||
end
|
||||
validates :category, inclusion: { in: CATEGORIES }
|
||||
validates :url, presence: true, length: { maximum: 400 }, format: API_URL_REGEXP
|
||||
|
||||
def self.fetch(url)
|
||||
try_to_get_issue(url)
|
||||
rescue StandardError => e
|
||||
raise StandardError, "A GitHub issue 404'ed and could not be found!" if e.message.include?("404 - Not Found")
|
||||
|
||||
raise StandardError, e.message
|
||||
end
|
||||
|
||||
def self.try_to_get_issue(url)
|
||||
client = Octokit::Client.new(access_token: random_token)
|
||||
issue = GithubIssue.new(url: url)
|
||||
if /\/issues\/comments/.match?(url)
|
||||
repo, issue_id = url.gsub(/.*github\.com\/repos\//, "").split("/issues/comments/")
|
||||
issue.issue_serialized = client.issue_comment(repo, issue_id).to_hash
|
||||
issue.category = "issue_comment"
|
||||
else
|
||||
repo, issue_id = url.gsub(/.*github\.com\/repos\//, "").split(issue_or_pull(url))
|
||||
issue.issue_serialized = get_issue_serialized(client, repo, issue_id)
|
||||
issue.category = "issue"
|
||||
class << self
|
||||
def find_or_fetch(url)
|
||||
find_by(url: url) || fetch(url)
|
||||
end
|
||||
issue.processed_html = get_html(client, issue)
|
||||
issue.save!
|
||||
issue
|
||||
end
|
||||
|
||||
def self.get_html(client, issue)
|
||||
client.markdown(issue.issue_serialized[:body])
|
||||
end
|
||||
private
|
||||
|
||||
def self.get_issue_serialized(client, repo, issue_id)
|
||||
client.issue(repo, issue_id).to_hash
|
||||
end
|
||||
|
||||
def self.random_token
|
||||
if Rails.env.test?
|
||||
"ddsddsdsdssdsds"
|
||||
else
|
||||
random_identity.token
|
||||
def fetch(url)
|
||||
retrieve_and_save_issue(url)
|
||||
rescue Github::Errors::NotFound => e
|
||||
raise e, error_message(url)
|
||||
end
|
||||
end
|
||||
|
||||
def self.random_identity
|
||||
if Rails.env.production?
|
||||
Identity.where(provider: "github").last(250).sample
|
||||
else
|
||||
Identity.where(provider: "github").last
|
||||
def retrieve_and_save_issue(url)
|
||||
issue = new(url: url)
|
||||
|
||||
if PATH_COMMENT_REGEXP.match?(url)
|
||||
repo, issue_id = comment_repo_and_issue_id(url)
|
||||
issue.issue_serialized = Github::Client.issue_comment(repo, issue_id).to_h
|
||||
issue.category = "issue_comment"
|
||||
else
|
||||
repo, issue_id = issue_or_pull_repo_and_issue_id(url)
|
||||
issue.issue_serialized = Github::Client.issue(repo, issue_id).to_h
|
||||
issue.category = "issue"
|
||||
end
|
||||
|
||||
# despite the counter intuitive name `.markdown` returns HTML rendered
|
||||
# from the original markdown
|
||||
issue.processed_html = Github::Client.markdown(issue.issue_serialized[:body])
|
||||
|
||||
issue.save!
|
||||
|
||||
issue
|
||||
end
|
||||
end
|
||||
|
||||
def self.issue_or_pull(url)
|
||||
if !url.include?("pull")
|
||||
"/issues/"
|
||||
else
|
||||
"/pull/"
|
||||
def clean_url(url)
|
||||
url.gsub(PATH_REPO_REGEXP, "")
|
||||
end
|
||||
|
||||
def comment_repo_and_issue_id(url)
|
||||
clean_url(url).split(PATH_COMMENT_REGEXP)
|
||||
end
|
||||
|
||||
def issue_or_pull_repo_and_issue_id(url)
|
||||
splitter = if PATH_PULL_REQUEST_REGEXP.match?(url)
|
||||
PATH_PULL_REQUEST_REGEXP
|
||||
else
|
||||
PATH_ISSUE_REGEXP
|
||||
end
|
||||
|
||||
clean_url(url).split(splitter)
|
||||
end
|
||||
|
||||
def error_message(url)
|
||||
if PATH_COMMENT_REGEXP.match?(url)
|
||||
_, issue_id = comment_repo_and_issue_id(url)
|
||||
"Issue comment #{issue_id} not found"
|
||||
else
|
||||
_, issue_id = issue_or_pull_repo_and_issue_id(url)
|
||||
"Issue #{issue_id} not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
103
app/services/github/client.rb
Normal file
103
app/services/github/client.rb
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
module Github
|
||||
# Github client (uses ocktokit.rb as a backend)
|
||||
class Client
|
||||
class << self
|
||||
# adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
|
||||
def method_missing(method, *args, &block)
|
||||
return super unless target.respond_to?(method, false)
|
||||
|
||||
# define for re-use
|
||||
self.class.define_method(method) do |*new_args, &new_block|
|
||||
request do
|
||||
target.public_send(method, *new_args, &new_block)
|
||||
end
|
||||
end
|
||||
|
||||
# call the original method, this will only be called the first time
|
||||
# as in subsequent calls, the newly defined method will prevail
|
||||
request do
|
||||
target.public_send(method, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
# adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
|
||||
def respond_to_missing?(method, _include_all = false)
|
||||
target.respond_to?(method, false) || super
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request
|
||||
Honeycomb.add_field("app.name", "github.client")
|
||||
yield
|
||||
rescue Octokit::Error => e
|
||||
record_error(e)
|
||||
handle_error(e)
|
||||
end
|
||||
|
||||
def record_error(exception)
|
||||
class_name = exception.class.name.demodulize
|
||||
|
||||
Honeycomb.add_field("github.result", "error")
|
||||
Honeycomb.add_field("github.error", class_name)
|
||||
DatadogStatsClient.increment(
|
||||
"github.errors",
|
||||
tags: ["error:#{class_name}", "message:#{exception.message}"],
|
||||
)
|
||||
end
|
||||
|
||||
def handle_error(exception)
|
||||
class_name = exception.class.name.demodulize
|
||||
|
||||
# raise specific error if known, generic one if unknown
|
||||
error_class = "::Github::Errors::#{class_name}".safe_constantize
|
||||
raise error_class, exception.message if error_class
|
||||
|
||||
error_class = if exception.class < Octokit::ClientError
|
||||
Github::Errors::ClientError
|
||||
elsif exception.class < Octokit::ServerError
|
||||
Github::Errors::ServerError
|
||||
else
|
||||
Github::Errors::Error
|
||||
end
|
||||
|
||||
raise error_class, exception.message
|
||||
end
|
||||
|
||||
def target
|
||||
@target ||= Octokit::Client.new(
|
||||
client_id: ApplicationConfig["GITHUB_KEY"],
|
||||
client_secret: ApplicationConfig["GITHUB_SECRET"],
|
||||
user_agent: "#{Octokit::Default::USER_AGENT} (#{URL.url})",
|
||||
middleware: faraday_middleware_stack,
|
||||
connection_options: connection_options,
|
||||
)
|
||||
end
|
||||
|
||||
def faraday_middleware_stack
|
||||
# Extending the default functionality
|
||||
# see <https://github.com/octokit/octokit.rb#advanced-usage>,
|
||||
# <https://github.com/octokit/octokit.rb#caching>
|
||||
# and <https://github.com/octokit/octokit.rb/blob/master/lib/octokit/default.rb>
|
||||
Faraday::RackBuilder.new do |builder|
|
||||
builder.use Faraday::HttpCache, store: Rails.cache, serializer: Marshal, shared_cache: false
|
||||
builder.use Faraday::Request::Retry, exceptions: [Octokit::ServerError]
|
||||
builder.use Octokit::Middleware::FollowRedirects
|
||||
builder.use Octokit::Response::RaiseError
|
||||
builder.use Octokit::Response::FeedParser
|
||||
|
||||
builder.adapter :patron
|
||||
end
|
||||
end
|
||||
|
||||
def connection_options
|
||||
Octokit.connection_options.merge(
|
||||
request: {
|
||||
open_timeout: 5,
|
||||
timeout: 5
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
15
app/services/github/errors.rb
Normal file
15
app/services/github/errors.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
module Github
|
||||
module Errors
|
||||
class Error < StandardError
|
||||
end
|
||||
|
||||
class ClientError < Error
|
||||
end
|
||||
|
||||
class ServerError < Error
|
||||
end
|
||||
|
||||
class NotFound < ClientError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="ltag_github-liquid-tag">
|
||||
<h1>
|
||||
<a href="<%= date_link %>">
|
||||
<a href="<%= html_url %>">
|
||||
<img class="github-logo" alt="GitHub logo" src="<%= ActionController::Base.helpers.asset_path('github-logo.svg') %>">
|
||||
<span class="issue-title">
|
||||
<%= title %>
|
||||
|
|
@ -18,12 +18,12 @@
|
|||
<div class="timeline-comment-header-text">
|
||||
<strong>
|
||||
<a href="<%= user_html_url %>"><%= username %></a>
|
||||
</strong> commented on <a href="<%= date_link %>"><%= date %></a><span class="timestamp"></span>
|
||||
</strong> <%= tagline %> <a href="<%= html_url %>"><time datetime="<%= created_at %>"><%= date %></time></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ltag-github-body">
|
||||
<%= body %>
|
||||
</div>
|
||||
<div class="gh-btn-container"><a class="gh-btn" href="<%= date_link %>">View on GitHub</a></div>
|
||||
<div class="gh-btn-container"><a class="gh-btn" href="<%= html_url %>">View on GitHub</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
module DataUpdateScripts
|
||||
class RemoveGithubIssues
|
||||
def run
|
||||
GithubIssue.in_batches.delete_all
|
||||
end
|
||||
end
|
||||
end
|
||||
5
spec/factories/github_issues.rb
Normal file
5
spec/factories/github_issues.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
FactoryBot.define do
|
||||
factory :github_issue do
|
||||
category { "issue" }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,40 +1,80 @@
|
|||
require "rails_helper"
|
||||
|
||||
vcr_option = {
|
||||
cassette_name: "github_api",
|
||||
allow_playback_repeats: "true"
|
||||
}
|
||||
|
||||
RSpec.describe GithubTag::GithubIssueTag, type: :liquid_tag, vcr: vcr_option do
|
||||
RSpec.describe GithubTag::GithubIssueTag, type: :liquid_tag, vcr: true do
|
||||
describe "#id" do
|
||||
let(:github_link) { "https://github.com/facebook/react/issues/9218" }
|
||||
let(:url_issue) { "https://github.com/thepracticaldev/dev.to/issues/7434" }
|
||||
let(:url_issue_fragment) { "https://github.com/thepracticaldev/dev.to/issues/7434#issue-604653303" }
|
||||
let(:url_pull_request) { "https://github.com/thepracticaldev/dev.to/pull/7653" }
|
||||
let(:url_pull_request_issue_fragment) { "https://github.com/thepracticaldev/dev.to/pull/7653#issue-412271322" }
|
||||
let(:url_issue_comment) { "https://github.com/thepracticaldev/dev.to/issues/7434#issuecomment-621043602" }
|
||||
let(:url_pull_request_comment) { "https://github.com/thepracticaldev/dev.to/pull/7653#issuecomment-622572436" }
|
||||
let(:url_not_found) { "https://github.com/thepracticaldev/dev.to/issues/0" }
|
||||
|
||||
setup { Liquid::Template.register_tag("github", GithubTag) }
|
||||
|
||||
def generate_github_issue(link)
|
||||
Liquid::Template.parse("{% github #{link} %}")
|
||||
def generate_tag(url)
|
||||
Liquid::Template.register_tag("github", GithubTag)
|
||||
Liquid::Template.parse("{% github #{url} %}")
|
||||
end
|
||||
|
||||
it "rejects github link without domain" do
|
||||
it "rejects GitHub URL without domain" do
|
||||
expect do
|
||||
generate_github_issue("/react/issues/9193")
|
||||
generate_tag("/react/issues/9193")
|
||||
end.to raise_error(StandardError)
|
||||
end
|
||||
|
||||
it "rejects invalid github issue link" do
|
||||
it "rejects invalid GitHub issue URL" do
|
||||
expect do
|
||||
generate_github_issue("https://github.com/issues/9193")
|
||||
generate_tag("https://github.com/issues/9193")
|
||||
end.to raise_error(StandardError)
|
||||
end
|
||||
|
||||
xit "renders properly" do
|
||||
output = generate_github_issue(github_link).render
|
||||
# NB: this approvals test is a little harder to update
|
||||
# because a legitimate github access token is required for octokit
|
||||
# which is then captured via vcr.
|
||||
# IF YOU DO PLAN TO UPDATE THIS: be sure to remove your access token
|
||||
# from the vcr cassette generated by this
|
||||
Approvals.verify(output, name: "github_liquid_tag_default", format: :html)
|
||||
it "rejects a non existing GitHub issue URL" do
|
||||
VCR.use_cassette("github_client_issue_not_found") do
|
||||
expect do
|
||||
generate_tag(url_not_found)
|
||||
end.to raise_error(StandardError)
|
||||
end
|
||||
end
|
||||
|
||||
it "renders an issue URL" do
|
||||
VCR.use_cassette("github_client_issue") do
|
||||
html = generate_tag(url_issue).render
|
||||
expect(html).to include("#7434")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders an issue URL with an issue fragment" do
|
||||
VCR.use_cassette("github_client_issue") do
|
||||
html = generate_tag(url_issue_fragment).render
|
||||
expect(html).to include("#7434")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders a pull request URL" do
|
||||
VCR.use_cassette("github_client_pull_request") do
|
||||
html = generate_tag(url_pull_request).render
|
||||
expect(html).to include("#7653")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders a pull request URL with an issue fragment" do
|
||||
VCR.use_cassette("github_client_pull_request") do
|
||||
html = generate_tag(url_pull_request_issue_fragment).render
|
||||
expect(html).to include("#7653")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders an issue comment" do
|
||||
VCR.use_cassette("github_client_comment") do
|
||||
html = generate_tag(url_issue_comment).render
|
||||
expect(html).to include("621043602")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders a PR comment" do
|
||||
VCR.use_cassette("github_client_pull_request_comment") do
|
||||
html = generate_tag(url_pull_request_comment).render
|
||||
expect(html).to include("622572436")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,20 +1,105 @@
|
|||
require "rails_helper"
|
||||
|
||||
vcr_option = {
|
||||
cassette_name: "github_issue_api",
|
||||
allow_playback_repeats: "true"
|
||||
}
|
||||
RSpec.describe GithubIssue, type: :model, vcr: true do
|
||||
let(:url_issue) { "https://api.github.com/repos/thepracticaldev/dev.to/issues/7434" }
|
||||
let(:url_pull_request) { "https://api.github.com/repos/thepracticaldev/dev.to/pulls/7653" }
|
||||
let(:url_comment) { "https://api.github.com/repos/thepracticaldev/dev.to/issues/comments/621043602" }
|
||||
let(:url_not_found) { "https://api.github.com/repos/thepracticaldev/dev.to/issues/0" }
|
||||
|
||||
RSpec.describe GithubIssue, type: :model, vcr: vcr_option do
|
||||
let(:link) { "https://api.github.com/repos/thepracticaldev/dev.to/issues/510#issue-354483683" }
|
||||
it { is_expected.to validate_length_of(:url).is_at_most(400) }
|
||||
it { is_expected.to validate_inclusion_of(:category).in_array(%w[issue issue_comment]) }
|
||||
it { is_expected.to validate_presence_of(:url) }
|
||||
|
||||
it "finds or fetches based on URL" do
|
||||
# NB: this approvals test is a little harder to update
|
||||
# because a legitimate github access token is required for octokit
|
||||
# which is then captured via vcr.
|
||||
# IF YOU DO PLAN TO UPDATE THIS: be sure to remove your access token
|
||||
# from the vcr cassette generated by this
|
||||
issue = described_class.find_or_fetch(link)
|
||||
Approvals.verify(issue.processed_html, name: "github_issue_test", format: :html)
|
||||
describe ".find_or_fetch" do
|
||||
context "when retrieving an issue", vcr: { cassette_name: "github_client_issue" } do
|
||||
it "saves a new issue" do
|
||||
expect do
|
||||
described_class.find_or_fetch(url_issue)
|
||||
end.to change(described_class, :count).by(1)
|
||||
end
|
||||
|
||||
it "retrieves an existing issue" do
|
||||
created_issue = described_class.find_or_fetch(url_issue)
|
||||
|
||||
expect do
|
||||
found_issue = described_class.find_or_fetch(url_issue)
|
||||
expect(found_issue.id).to eq(created_issue.id)
|
||||
end.not_to change(described_class, :count)
|
||||
end
|
||||
|
||||
it "saves the proper fields" do
|
||||
issue = described_class.find_or_fetch(url_issue)
|
||||
|
||||
expect(issue.url).to eq(url_issue)
|
||||
expect(issue.issue_serialized[:title]).to be_present
|
||||
expect(issue.category).to eq("issue")
|
||||
end
|
||||
end
|
||||
|
||||
context "when retrieving a pull request", vcr: { cassette_name: "github_client_pull_request" } do
|
||||
it "saves a new issue" do
|
||||
expect do
|
||||
described_class.find_or_fetch(url_pull_request)
|
||||
end.to change(described_class, :count).by(1)
|
||||
end
|
||||
|
||||
it "retrieves an existing issue" do
|
||||
created_issue = described_class.find_or_fetch(url_pull_request)
|
||||
|
||||
expect do
|
||||
found_issue = described_class.find_or_fetch(url_pull_request)
|
||||
expect(found_issue.id).to eq(created_issue.id)
|
||||
end.not_to change(described_class, :count)
|
||||
end
|
||||
|
||||
it "saves the proper fields" do
|
||||
issue = described_class.find_or_fetch(url_pull_request)
|
||||
|
||||
expect(issue.url).to eq(url_pull_request)
|
||||
expect(issue.issue_serialized[:title]).to be_present
|
||||
expect(issue.category).to eq("issue")
|
||||
end
|
||||
end
|
||||
|
||||
context "when retrieving a comment", vcr: { cassette_name: "github_client_comment" } do
|
||||
it "saves a new issue comment" do
|
||||
expect do
|
||||
described_class.find_or_fetch(url_comment)
|
||||
end.to change(described_class, :count).by(1)
|
||||
end
|
||||
|
||||
it "retrieves an existing issue comment" do
|
||||
created_issue = described_class.find_or_fetch(url_comment)
|
||||
|
||||
expect do
|
||||
found_issue = described_class.find_or_fetch(url_comment)
|
||||
expect(found_issue.id).to eq(created_issue.id)
|
||||
end.not_to change(described_class, :count)
|
||||
end
|
||||
|
||||
it "saves the proper fields" do
|
||||
issue = described_class.find_or_fetch(url_comment)
|
||||
|
||||
expect(issue.url).to eq(url_comment)
|
||||
expect(issue.issue_serialized[:title]).not_to be_present
|
||||
expect(issue.issue_serialized[:body]).to be_present
|
||||
expect(issue.category).to eq("issue_comment")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
xit "saves HTML in .processed_html" do
|
||||
VCR.use_cassette("github_client_issue") do
|
||||
issue = described_class.find_or_fetch(url_issue)
|
||||
Approvals.verify(issue.processed_html, name: "github_client_issue", format: :html)
|
||||
end
|
||||
end
|
||||
|
||||
it "raises Github::Errors::NotFound if the issue is not found" do
|
||||
VCR.use_cassette("github_client_issue_not_found") do
|
||||
expect do
|
||||
described_class.find_or_fetch(url_not_found)
|
||||
end.to raise_error(Github::Errors::NotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
22
spec/services/github/client_spec.rb
Normal file
22
spec/services/github/client_spec.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Github::Client, type: :service, vcr: true do
|
||||
let(:repo) { "thepracticaldev/dev.to" }
|
||||
|
||||
describe ".issue" do
|
||||
it "returns a an issue" do
|
||||
VCR.use_cassette("github_client_issue") do
|
||||
issue = described_class.issue(repo, 7434)
|
||||
expect(issue.title).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
it "raises NotFound if the issue does not exist" do
|
||||
VCR.use_cassette("github_client_issue_not_found") do
|
||||
expect do
|
||||
described_class.issue(repo, 0)
|
||||
end.to raise_error(Github::Errors::NotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body><p>@jessleenyc commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638">Tue Jul 31 2018</a></p>
|
||||
<h1>
|
||||
<a id="user-content-task-or-feature" class="anchor" href="#task-or-feature" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a><em>TASK or Feature</em>
|
||||
</h1>
|
||||
<h3>
|
||||
<a id="user-content-request-or-user-story" class="anchor" href="#request-or-user-story" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Request or User Story</h3>
|
||||
<p>Getting lots of crawlers clicking on the hidden link that's giving them 404 errors and jamming up honeybadger!</p>
|
||||
<h3>
|
||||
<a id="user-content-definition-of-done" class="anchor" href="#definition-of-done" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition of Done</h3>
|
||||
<h3>
|
||||
<a id="user-content-notes" class="anchor" href="#notes" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Notes</h3>
|
||||
<hr /><p>@arun1595 commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-409774531">Wed Aug 01 2018</a></p>
|
||||
<p>@jessleenyc I would like to tackle this issue. Can you guide me with what "moderate" links are?</p>
|
||||
<p>Thanks.</p>
|
||||
<hr /><p>@Zhao-Andy commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-416373282">Mon Aug 27 2018</a></p>
|
||||
<p>Hey @arun1595, we're going to move this to the public repo and continue the conversation there.</p></body>
|
||||
</html>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<div class="ltag_github-liquid-tag">
|
||||
<h1>
|
||||
<a href="https://github.com/facebook/react/issues/9218">
|
||||
<img class="github-logo" alt="GitHub logo" src="/assets/github-logo-6a5bca60a4ebf959a6df7f08217acd07ac2bc285164fae041eacb8a148b1bab9.svg" /><span class="issue-title">
|
||||
[Feature] granular forceUpdate
|
||||
</span>
|
||||
<span class="issue-number">#9218</span>
|
||||
</a>
|
||||
</h1>
|
||||
<div class="github-thread">
|
||||
<div class="timeline-comment-header">
|
||||
<a href="https://github.com/thysultan">
|
||||
<img class="github-liquid-tag-img" src="https://avatars2.githubusercontent.com/u/810601?v=4" alt="thysultan avatar" /></a>
|
||||
<span class="arrow-left-outer"></span>
|
||||
<span class="arrow-left-inner"></span>
|
||||
<div class="timeline-comment-header-text">
|
||||
<strong>
|
||||
<a href="https://github.com/thysultan">thysultan</a>
|
||||
</strong> commented on <a href="https://github.com/facebook/react/issues/9218">Mar 19, 2017</a><span class="timestamp"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ltag-github-body">
|
||||
<p>When <code>forceUpdate</code> is called on a long list at the very least the whole list must be traversed. For example with the following list <code>arr = [1, 2, 3, 4, 5, 6]</code> and if we where to push 7 <code>arr.push(7)</code> the reconciler will go through elements 1 - 6 and then add a 7 at the end of that list. The suggestion to add support for the following forceUpdate signature.</p>
|
||||
<div class="highlight highlight-source-js"><pre><span class="pl-en">forceUpdate</span>(a<span class="pl-k">:</span> {<span class="pl-k">function</span>|number}, b: number?)</pre></div>
|
||||
<p>Where when passed as an integer <code>a</code> is the start index and <code>b</code> the number of items to traverse similar to how <code>str.substr()</code> works.</p>
|
||||
<p>When the function encounters a number as the <code>a</code> argument it changes the start index of where to start when reconciling the components children and when the <code>b</code> argument is set it changes the end index of where to end the traversal of the components children. So with the above mentioned example if i wanted to optimize the reconciliation process for append updates i could do the following.</p>
|
||||
<div class="highlight highlight-source-js"><pre><span class="pl-c1">this</span>.<span class="pl-en">forceUpdate</span>(<span class="pl-smi">arr</span>.<span class="pl-c1">length</span>);</pre></div>
|
||||
<p>and to target an update in the middle of the list of up to 3 items.</p>
|
||||
<div class="highlight highlight-source-js"><pre><span class="pl-c1">this</span>.<span class="pl-en">forceUpdate</span>(<span class="pl-smi">arr</span>.<span class="pl-c1">length</span><span class="pl-k">/</span><span class="pl-c1">2</span>, <span class="pl-c1">3</span>);</pre></div>
|
||||
<p>This will allow for very precise O(1) updates when you know ahead of time how the data will change.</p>
|
||||
<p>Possible <code>setState</code> counter-part.</p>
|
||||
<div class="highlight highlight-source-js"><pre><span class="pl-en">setState</span>(a<span class="pl-k">:</span> {<span class="pl-k">function</span>|Object}, b: (<span class="pl-k">function</span>|number)?, c: {number})
|
||||
|
||||
<span class="pl-c"><span class="pl-c">//</span> usage</span>
|
||||
setState({arr<span class="pl-k">:</span> [<span class="pl-k">...</span>]}, <span class="pl-c1">this</span>.<span class="pl-smi">state</span>.<span class="pl-smi">arr</span>.<span class="pl-c1">length</span>);</pre></div>
|
||||
|
||||
</div>
|
||||
<div class="gh-btn-container"><a class="gh-btn" href="https://github.com/facebook/react/issues/9218">View on GitHub</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
143
spec/support/fixtures/vcr_cassettes/github_client_comment.yml
Normal file
143
spec/support/fixtures/vcr_cassettes/github_client_comment.yml
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/comments/621043602?per_page=100
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=b7791fdb-dcc2-4751-84d7-6d5b91d4c8d7,parent_id=f98dfdd2-ef73-44bd-a92c-3cc4ffd3f62c,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:45 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '1454'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4978'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
Cache-Control:
|
||||
- public, max-age=60, s-maxage=60
|
||||
Vary:
|
||||
- Accept
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
Etag:
|
||||
- '"1589430fd33ed6b00098c14727a2a9f6"'
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Github-Request-Id:
|
||||
- F3AC:786B:2668DF:351A29:5EAE0845
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{"url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/comments/621043602","html_url":"https://github.com/thepracticaldev/dev.to/issues/7434#issuecomment-621043602","issue_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7434","id":621043602,"node_id":"MDEyOklzc3VlQ29tbWVudDYyMTA0MzYwMg==","user":{"login":"catalinpit","id":25515812,"node_id":"MDQ6VXNlcjI1NTE1ODEy","avatar_url":"https://avatars3.githubusercontent.com/u/25515812?u=2c7e3d9e557cc819c3dd2069f5e4904d6a365ad1&v=4","gravatar_id":"","url":"https://api.github.com/users/catalinpit","html_url":"https://github.com/catalinpit","followers_url":"https://api.github.com/users/catalinpit/followers","following_url":"https://api.github.com/users/catalinpit/following{/other_user}","gists_url":"https://api.github.com/users/catalinpit/gists{/gist_id}","starred_url":"https://api.github.com/users/catalinpit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/catalinpit/subscriptions","organizations_url":"https://api.github.com/users/catalinpit/orgs","repos_url":"https://api.github.com/users/catalinpit/repos","events_url":"https://api.github.com/users/catalinpit/events{/privacy}","received_events_url":"https://api.github.com/users/catalinpit/received_events","type":"User","site_admin":false},"created_at":"2020-04-29T07:46:28Z","updated_at":"2020-04-29T07:46:28Z","author_association":"CONTRIBUTOR","body":"What
|
||||
do you think, @ludwiczakpawel?"}'
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:45 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.github.com/markdown
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"text":"What do you think, @ludwiczakpawel?"}'
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.raw
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=c3f4fcd3-12df-4e45-90ed-6eff8690d534,parent_id=7666e3c3-e7c8-4655-b4ab-b6f5f9622c88,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:46 GMT
|
||||
Content-Type:
|
||||
- text/html;charset=utf-8
|
||||
Content-Length:
|
||||
- '43'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4977'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
X-Commonmarker-Version:
|
||||
- 0.21.0
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
Vary:
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
X-Github-Request-Id:
|
||||
- F3AD:786C:193245:227CB0:5EAE0846
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: "<p>What do you think, @ludwiczakpawel?</p>\n"
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:46 GMT
|
||||
recorded_with: VCR 5.1.0
|
||||
182
spec/support/fixtures/vcr_cassettes/github_client_issue.yml
Normal file
182
spec/support/fixtures/vcr_cassettes/github_client_issue.yml
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/7434
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=4085b91d-4649-4fc3-bf1c-96c5a2bc8d57,parent_id=9367c158-33bc-4172-bbbe-b5ac5e8926de,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:39 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '3552'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4983'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
Cache-Control:
|
||||
- public, max-age=60, s-maxage=60
|
||||
Vary:
|
||||
- Accept
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
Etag:
|
||||
- '"54e1b0dd3fed55dc41e2d4affd48d3d7"'
|
||||
Last-Modified:
|
||||
- Sat, 02 May 2020 10:56:49 GMT
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Github-Request-Id:
|
||||
- F3A7:29D1:25238A:33C5C5:5EAE083E
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{"url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7434","repository_url":"https://api.github.com/repos/thepracticaldev/dev.to","labels_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7434/labels{/name}","comments_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7434/comments","events_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7434/events","html_url":"https://github.com/thepracticaldev/dev.to/issues/7434","id":604653303,"node_id":"MDU6SXNzdWU2MDQ2NTMzMDM=","number":7434,"title":"Profile
|
||||
page not displaying the name due to theming and custom colors","user":{"login":"catalinpit","id":25515812,"node_id":"MDQ6VXNlcjI1NTE1ODEy","avatar_url":"https://avatars0.githubusercontent.com/u/25515812?v=4","gravatar_id":"","url":"https://api.github.com/users/catalinpit","html_url":"https://github.com/catalinpit","followers_url":"https://api.github.com/users/catalinpit/followers","following_url":"https://api.github.com/users/catalinpit/following{/other_user}","gists_url":"https://api.github.com/users/catalinpit/gists{/gist_id}","starred_url":"https://api.github.com/users/catalinpit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/catalinpit/subscriptions","organizations_url":"https://api.github.com/users/catalinpit/orgs","repos_url":"https://api.github.com/users/catalinpit/repos","events_url":"https://api.github.com/users/catalinpit/events{/privacy}","received_events_url":"https://api.github.com/users/catalinpit/received_events","type":"User","site_admin":false},"labels":[{"id":1031106689,"node_id":"MDU6TGFiZWwxMDMxMTA2Njg5","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/accessibility","name":"accessibility","color":"c5aef2","default":false,"description":""},{"id":1290917705,"node_id":"MDU6TGFiZWwxMjkwOTE3NzA1","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/area:%20profile","name":"area:
|
||||
profile","color":"2a75b2","default":false,"description":"user''s profile"},{"id":1290878626,"node_id":"MDU6TGFiZWwxMjkwODc4NjI2","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/area:%20themes","name":"area:
|
||||
themes","color":"2a75b2","default":false,"description":"UX theming"},{"id":480869965,"node_id":"MDU6TGFiZWw0ODA4Njk5NjU=","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/type:%20bug","name":"type:
|
||||
bug","color":"C61C32","default":false,"description":"always open for contribution"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2020-04-22T10:43:38Z","updated_at":"2020-05-02T10:56:49Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"**Describe
|
||||
the bug**\r\n\r\nYou are allowed to change the colour for some of the information
|
||||
from your profile page. There are cases when the profile page doesn''t work
|
||||
properly when the colours are related.\r\n\r\nSee the pictures below or visit
|
||||
my profile [dev.to/catalinmpit](https://dev.to/catalinmpit).\r\n\r\n**To Reproduce**\r\n\r\n1.
|
||||
Go to [dev.to/catalinmpit](https://dev.to/catalinmpit)\r\n\r\n**Expected behavior**\r\n\r\nMy
|
||||
name and other information should be visible.\r\n\r\n**Screenshots**\r\n\r\n\r\n\r\n**Aditional
|
||||
information**\r\n\r\nPlayed around with the settings and I''ve done this:\r\n\r\n\r\n\r\n**Question**\r\n\r\nWhat
|
||||
do you recommend to fix the issue? If you have any recommendations, I''m happy
|
||||
to pick the issue.\r\n","closed_by":null}'
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:39 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.github.com/markdown
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"text":"**Describe the bug**\r\n\r\nYou are allowed to change the
|
||||
colour for some of the information from your profile page. There are cases
|
||||
when the profile page doesn''t work properly when the colours are related.\r\n\r\nSee
|
||||
the pictures below or visit my profile [dev.to/catalinmpit](https://dev.to/catalinmpit).\r\n\r\n**To
|
||||
Reproduce**\r\n\r\n1. Go to [dev.to/catalinmpit](https://dev.to/catalinmpit)\r\n\r\n**Expected
|
||||
behavior**\r\n\r\nMy name and other information should be visible.\r\n\r\n**Screenshots**\r\n\r\n\r\n\r\n**Aditional
|
||||
information**\r\n\r\nPlayed around with the settings and I''ve done this:\r\n\r\n\r\n\r\n**Question**\r\n\r\nWhat
|
||||
do you recommend to fix the issue? If you have any recommendations, I''m happy
|
||||
to pick the issue.\r\n"}'
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.raw
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=63ab979a-3896-4e70-b54d-bf2bf6d375b8,parent_id=b0559d07-130e-4438-ae4a-4852728336a1,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:40 GMT
|
||||
Content-Type:
|
||||
- text/html;charset=utf-8
|
||||
Content-Length:
|
||||
- '1759'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4982'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
X-Commonmarker-Version:
|
||||
- 0.21.0
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
Vary:
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
X-Github-Request-Id:
|
||||
- F3A8:29D1:2523AC:33C5F9:5EAE0840
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |
|
||||
<p><strong>Describe the bug</strong></p>
|
||||
<p>You are allowed to change the colour for some of the information from your profile page. There are cases when the profile page doesn't work properly when the colours are related.</p>
|
||||
<p>See the pictures below or visit my profile <a href="https://dev.to/catalinmpit" rel="nofollow">dev.to/catalinmpit</a>.</p>
|
||||
<p><strong>To Reproduce</strong></p>
|
||||
<ol>
|
||||
<li>Go to <a href="https://dev.to/catalinmpit" rel="nofollow">dev.to/catalinmpit</a>
|
||||
</li>
|
||||
</ol>
|
||||
<p><strong>Expected behavior</strong></p>
|
||||
<p>My name and other information should be visible.</p>
|
||||
<p><strong>Screenshots</strong></p>
|
||||
<p><a href="https://camo.githubusercontent.com/92af1284df38dd307a8b30ccafbea9f832a82d61/68747470733a2f2f692e696d6775722e636f6d2f414a794d3774482e706e67" target="_blank" rel="nofollow"><img src="https://camo.githubusercontent.com/92af1284df38dd307a8b30ccafbea9f832a82d61/68747470733a2f2f692e696d6775722e636f6d2f414a794d3774482e706e67" alt="broken-profile-page" data-canonical-src="https://i.imgur.com/AJyM7tH.png" style="max-width:100%;"></a></p>
|
||||
<p><strong>Aditional information</strong></p>
|
||||
<p>Played around with the settings and I've done this:</p>
|
||||
<p><a href="https://camo.githubusercontent.com/b2d23465b39fd003c0121c1b87177673d4d96336/68747470733a2f2f692e696d6775722e636f6d2f444c69505846542e706e67" target="_blank" rel="nofollow"><img src="https://camo.githubusercontent.com/b2d23465b39fd003c0121c1b87177673d4d96336/68747470733a2f2f692e696d6775722e636f6d2f444c69505846542e706e67" alt="profile-page-ok" data-canonical-src="https://i.imgur.com/DLiPXFT.png" style="max-width:100%;"></a></p>
|
||||
<p><strong>Question</strong></p>
|
||||
<p>What do you recommend to fix the issue? If you have any recommendations, I'm happy to pick the issue.</p>
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:40 GMT
|
||||
recorded_with: VCR 5.1.0
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/0
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=7b55123d-9904-435d-b5d3-7db505fe3bce,parent_id=73128408-7991-4aac-8a85-f6569b0e9d3b,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 404
|
||||
message: Not Found
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:41 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '104'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 404 Not Found
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4981'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
Vary:
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
X-Github-Request-Id:
|
||||
- F3A9:29D1:2523C7:33C61F:5EAE0841
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{"message":"Not Found","documentation_url":"https://developer.github.com/v3/issues/#get-a-single-issue"}'
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:41 GMT
|
||||
recorded_with: VCR 5.1.0
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/7653
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=3f8011ec-0d23-49d3-9d19-3acdb553274a,parent_id=e31110e6-dc1e-4884-b01b-ee15846d4236,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:43 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '4233'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4980'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465849'
|
||||
Cache-Control:
|
||||
- public, max-age=60, s-maxage=60
|
||||
Vary:
|
||||
- Accept
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
Etag:
|
||||
- '"0494d7edd146d9a6161dabf46f66cf6e"'
|
||||
Last-Modified:
|
||||
- Fri, 01 May 2020 21:47:35 GMT
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Github-Request-Id:
|
||||
- F3AA:4B32:24AC63:32E837:5EAE0842
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{"url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7653","repository_url":"https://api.github.com/repos/thepracticaldev/dev.to","labels_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7653/labels{/name}","comments_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7653/comments","events_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/7653/events","html_url":"https://github.com/thepracticaldev/dev.to/pull/7653","id":610931120,"node_id":"MDExOlB1bGxSZXF1ZXN0NDEyMjcxMzIy","number":7653,"title":"Log
|
||||
RateLimit hits to Datadog for Better Reporting","user":{"login":"mstruve","id":1813380,"node_id":"MDQ6VXNlcjE4MTMzODA=","avatar_url":"https://avatars3.githubusercontent.com/u/1813380?v=4","gravatar_id":"","url":"https://api.github.com/users/mstruve","html_url":"https://github.com/mstruve","followers_url":"https://api.github.com/users/mstruve/followers","following_url":"https://api.github.com/users/mstruve/following{/other_user}","gists_url":"https://api.github.com/users/mstruve/gists{/gist_id}","starred_url":"https://api.github.com/users/mstruve/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mstruve/subscriptions","organizations_url":"https://api.github.com/users/mstruve/orgs","repos_url":"https://api.github.com/users/mstruve/repos","events_url":"https://api.github.com/users/mstruve/events{/privacy}","received_events_url":"https://api.github.com/users/mstruve/received_events","type":"User","site_admin":false},"labels":[{"id":1123882148,"node_id":"MDU6TGFiZWwxMTIzODgyMTQ4","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/PR:%20merged","name":"PR:
|
||||
merged","color":"786DBE","default":false,"description":"bot applied label
|
||||
for PR''s that are merged"}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2020-05-01T19:40:23Z","updated_at":"2020-05-01T21:47:35Z","closed_at":"2020-05-01T21:47:32Z","author_association":"COLLABORATOR","pull_request":{"url":"https://api.github.com/repos/thepracticaldev/dev.to/pulls/7653","html_url":"https://github.com/thepracticaldev/dev.to/pull/7653","diff_url":"https://github.com/thepracticaldev/dev.to/pull/7653.diff","patch_url":"https://github.com/thepracticaldev/dev.to/pull/7653.patch"},"body":"\r\n##
|
||||
What type of PR is this? (check all applicable)\r\n- [x] Feature\r\n- [x]
|
||||
Optimization\r\n\r\n## Description\r\nRather than sending (almost) every single
|
||||
rate limit hit to Slack, lets send a metric to Datadog that we can track and
|
||||
alert on. The goal here is to send this data to Datadog. Once the data is
|
||||
there @michael-tharrington can then decide what thresholds he wants to set
|
||||
for what actions to determine when he gets alerted. Datadog then will be responsible
|
||||
for sending that information to Slack rather than our app. \r\n\r\nThis will
|
||||
allow us to set thresholds and alert only when users are excessively hitting
|
||||
rate limits rather than every single time which sometimes is not concerning
|
||||
if they only hit it once, like a pentester trying to see if a rate limiter
|
||||
exists. \r\n\r\n## Related Tickets & Documents\r\nhttps://github.com/thepracticaldev/dev.to/projects/9#card-37397577\r\n\r\n##
|
||||
Added tests?\r\n- [x] yes\r\n\r\n\r\n","closed_by":{"login":"mstruve","id":1813380,"node_id":"MDQ6VXNlcjE4MTMzODA=","avatar_url":"https://avatars3.githubusercontent.com/u/1813380?v=4","gravatar_id":"","url":"https://api.github.com/users/mstruve","html_url":"https://github.com/mstruve","followers_url":"https://api.github.com/users/mstruve/followers","following_url":"https://api.github.com/users/mstruve/following{/other_user}","gists_url":"https://api.github.com/users/mstruve/gists{/gist_id}","starred_url":"https://api.github.com/users/mstruve/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mstruve/subscriptions","organizations_url":"https://api.github.com/users/mstruve/orgs","repos_url":"https://api.github.com/users/mstruve/repos","events_url":"https://api.github.com/users/mstruve/events{/privacy}","received_events_url":"https://api.github.com/users/mstruve/received_events","type":"User","site_admin":false}}'
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:43 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.github.com/markdown
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"text":"\r\n## What type of PR is this? (check all applicable)\r\n-
|
||||
[x] Feature\r\n- [x] Optimization\r\n\r\n## Description\r\nRather than sending
|
||||
(almost) every single rate limit hit to Slack, lets send a metric to Datadog
|
||||
that we can track and alert on. The goal here is to send this data to Datadog.
|
||||
Once the data is there @michael-tharrington can then decide what thresholds
|
||||
he wants to set for what actions to determine when he gets alerted. Datadog
|
||||
then will be responsible for sending that information to Slack rather than
|
||||
our app. \r\n\r\nThis will allow us to set thresholds and alert only when
|
||||
users are excessively hitting rate limits rather than every single time which
|
||||
sometimes is not concerning if they only hit it once, like a pentester trying
|
||||
to see if a rate limiter exists. \r\n\r\n## Related Tickets & Documents\r\nhttps://github.com/thepracticaldev/dev.to/projects/9#card-37397577\r\n\r\n##
|
||||
Added tests?\r\n- [x] yes\r\n\r\n\r\n"}'
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.raw
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=40a6d376-ddbd-4054-8f13-16983a5f5d45,parent_id=8229768b-93f5-4952-8408-fec5650f68a9,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Sat, 02 May 2020 23:54:44 GMT
|
||||
Content-Type:
|
||||
- text/html;charset=utf-8
|
||||
Content-Length:
|
||||
- '2331'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4979'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588465848'
|
||||
X-Commonmarker-Version:
|
||||
- 0.21.0
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
Vary:
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
X-Github-Request-Id:
|
||||
- F3AB:29D2:192531:22748D:5EAE0843
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |
|
||||
<h2>
|
||||
<a id="user-content-what-type-of-pr-is-this-check-all-applicable" class="anchor" href="#what-type-of-pr-is-this-check-all-applicable" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>What type of PR is this? (check all applicable)</h2>
|
||||
<ul>
|
||||
<li>[x] Feature</li>
|
||||
<li>[x] Optimization</li>
|
||||
</ul>
|
||||
<h2>
|
||||
<a id="user-content-description" class="anchor" href="#description" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Description</h2>
|
||||
<p>Rather than sending (almost) every single rate limit hit to Slack, lets send a metric to Datadog that we can track and alert on. The goal here is to send this data to Datadog. Once the data is there @michael-tharrington can then decide what thresholds he wants to set for what actions to determine when he gets alerted. Datadog then will be responsible for sending that information to Slack rather than our app.</p>
|
||||
<p>This will allow us to set thresholds and alert only when users are excessively hitting rate limits rather than every single time which sometimes is not concerning if they only hit it once, like a pentester trying to see if a rate limiter exists.</p>
|
||||
<h2>
|
||||
<a id="user-content-related-tickets--documents" class="anchor" href="#related-tickets--documents" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Related Tickets & Documents</h2>
|
||||
<p><a href="https://github.com/thepracticaldev/dev.to/projects/9#card-37397577">https://github.com/thepracticaldev/dev.to/projects/9#card-37397577</a></p>
|
||||
<h2>
|
||||
<a id="user-content-added-tests" class="anchor" href="#added-tests" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Added tests?</h2>
|
||||
<ul>
|
||||
<li>[x] yes</li>
|
||||
</ul>
|
||||
<p><a href="https://camo.githubusercontent.com/3972d99d348007c519ae82451b8c52332933b5f4/68747470733a2f2f6d65646961312e67697068792e636f6d2f6d656469612f6c325957734f796d48445246597179414d2f67697068792e676966" target="_blank" rel="nofollow"><img src="https://camo.githubusercontent.com/3972d99d348007c519ae82451b8c52332933b5f4/68747470733a2f2f6d65646961312e67697068792e636f6d2f6d656469612f6c325957734f796d48445246597179414d2f67697068792e676966" alt="alt_text" data-canonical-src="https://media1.giphy.com/media/l2YWsOymHDRFYqyAM/giphy.gif" style="max-width:100%;"></a></p>
|
||||
http_version: null
|
||||
recorded_at: Sat, 02 May 2020 23:54:44 GMT
|
||||
recorded_with: VCR 5.1.0
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/comments/622572436?per_page=100
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=2130d678-d18a-4c28-a9d9-148409ed2ce1,parent_id=11aec9b3-1ad8-4021-9807-eb96f9426d36,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Mon, 04 May 2020 09:31:20 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '1663'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4999'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588588280'
|
||||
Cache-Control:
|
||||
- public, max-age=60, s-maxage=60
|
||||
Vary:
|
||||
- Accept
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
Etag:
|
||||
- '"006cef151248d15abe7e14ac18b6c5df"'
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Github-Request-Id:
|
||||
- F1B8:29D1:5382F7:738F6E:5EAFE0E7
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: !binary |-
|
||||
eyJ1cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zL3RoZXByYWN0aWNhbGRldi9kZXYudG8vaXNzdWVzL2NvbW1lbnRzLzYyMjU3MjQzNiIsImh0bWxfdXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL3RoZXByYWN0aWNhbGRldi9kZXYudG8vcHVsbC83NjUzI2lzc3VlY29tbWVudC02MjI1NzI0MzYiLCJpc3N1ZV91cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zL3RoZXByYWN0aWNhbGRldi9kZXYudG8vaXNzdWVzLzc2NTMiLCJpZCI6NjIyNTcyNDM2LCJub2RlX2lkIjoiTURFeU9rbHpjM1ZsUTI5dGJXVnVkRFl5TWpVM01qUXpOZz09IiwidXNlciI6eyJsb2dpbiI6Im1pY2hhZWwtdGhhcnJpbmd0b24iLCJpZCI6MTYwMDcwNzUsIm5vZGVfaWQiOiJNRFE2VlhObGNqRTJNREEzTURjMSIsImF2YXRhcl91cmwiOiJodHRwczovL2F2YXRhcnMyLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzE2MDA3MDc1P3U9ZTVmNDUwNjhhYTYyNDM2NThlYjVkMWQ1MmRiYzhlZWZjOWZlOWE1YiZ2PTQiLCJncmF2YXRhcl9pZCI6IiIsInVybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvbWljaGFlbC10aGFycmluZ3RvbiIsImh0bWxfdXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL21pY2hhZWwtdGhhcnJpbmd0b24iLCJmb2xsb3dlcnNfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9taWNoYWVsLXRoYXJyaW5ndG9uL2ZvbGxvd2VycyIsImZvbGxvd2luZ191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL21pY2hhZWwtdGhhcnJpbmd0b24vZm9sbG93aW5ney9vdGhlcl91c2VyfSIsImdpc3RzX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvbWljaGFlbC10aGFycmluZ3Rvbi9naXN0c3svZ2lzdF9pZH0iLCJzdGFycmVkX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvbWljaGFlbC10aGFycmluZ3Rvbi9zdGFycmVkey9vd25lcn17L3JlcG99Iiwic3Vic2NyaXB0aW9uc191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL21pY2hhZWwtdGhhcnJpbmd0b24vc3Vic2NyaXB0aW9ucyIsIm9yZ2FuaXphdGlvbnNfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9taWNoYWVsLXRoYXJyaW5ndG9uL29yZ3MiLCJyZXBvc191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL21pY2hhZWwtdGhhcnJpbmd0b24vcmVwb3MiLCJldmVudHNfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9taWNoYWVsLXRoYXJyaW5ndG9uL2V2ZW50c3svcHJpdmFjeX0iLCJyZWNlaXZlZF9ldmVudHNfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9taWNoYWVsLXRoYXJyaW5ndG9uL3JlY2VpdmVkX2V2ZW50cyIsInR5cGUiOiJVc2VyIiwic2l0ZV9hZG1pbiI6ZmFsc2V9LCJjcmVhdGVkX2F0IjoiMjAyMC0wNS0wMVQyMToxODoxMFoiLCJ1cGRhdGVkX2F0IjoiMjAyMC0wNS0wMVQyMToxODoxMFoiLCJhdXRob3JfYXNzb2NpYXRpb24iOiJDT05UUklCVVRPUiIsImJvZHkiOiJTbyBleGNpdGVkIGZvciB0aGlzISBJJ20gZ29pbmcgdG8gbWFrZSBzdXJlIHdlIHRhbGsgYWJvdXQgdGhpcyBpbiBvdXIgbmV4dCBzdXBwb3J0IG1lZXRpbmcuIEkgdGhpbmsgdGhpcyBpcyBhIHN1cGVyIPCfhpIgdGhpbmcgdG8gbW9uaXRvci4ifQ==
|
||||
http_version: null
|
||||
recorded_at: Mon, 04 May 2020 09:31:20 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.github.com/markdown
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: "{\"text\":\"So excited for this! I'm going to make sure we talk about
|
||||
this in our next support meeting. I think this is a super \U0001F192 thing
|
||||
to monitor.\"}"
|
||||
headers:
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.18.0 (http://localhost:3000)
|
||||
Accept:
|
||||
- application/vnd.github.raw
|
||||
Content-Type:
|
||||
- application/json
|
||||
X-Honeycomb-Trace:
|
||||
- 1;dataset=,trace_id=a4437cb5-738c-4169-894b-ee27dd425fc1,parent_id=1d39a812-0a36-4737-85bc-8efe8039dbda,context=e30=
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Mon, 04 May 2020 09:31:21 GMT
|
||||
Content-Type:
|
||||
- text/html;charset=utf-8
|
||||
Content-Length:
|
||||
- '278'
|
||||
Server:
|
||||
- GitHub.com
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4998'
|
||||
X-Ratelimit-Reset:
|
||||
- '1588588280'
|
||||
X-Commonmarker-Version:
|
||||
- 0.21.0
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval,
|
||||
X-GitHub-Media-Type, Deprecation, Sunset
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
Vary:
|
||||
- Accept-Encoding, Accept, X-Requested-With
|
||||
X-Github-Request-Id:
|
||||
- F1B9:786A:DA23C:12F2DF:5EAFE0E8
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: !binary |-
|
||||
PHA+U28gZXhjaXRlZCBmb3IgdGhpcyEgSSdtIGdvaW5nIHRvIG1ha2Ugc3VyZSB3ZSB0YWxrIGFib3V0IHRoaXMgaW4gb3VyIG5leHQgc3VwcG9ydCBtZWV0aW5nLiBJIHRoaW5rIHRoaXMgaXMgYSBzdXBlciA8Zy1lbW9qaSBjbGFzcz0iZy1lbW9qaSIgYWxpYXM9ImNvb2wiIGZhbGxiYWNrLXNyYz0iaHR0cHM6Ly9naXRodWIuZ2l0aHViYXNzZXRzLmNvbS9pbWFnZXMvaWNvbnMvZW1vamkvdW5pY29kZS8xZjE5Mi5wbmciPvCfhpI8L2ctZW1vamk+IHRoaW5nIHRvIG1vbml0b3IuPC9wPgo=
|
||||
http_version: null
|
||||
recorded_at: Mon, 04 May 2020 09:31:21 GMT
|
||||
recorded_with: VCR 5.1.0
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://api.github.com/repos/thepracticaldev/dev.to/issues/510
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
Accept:
|
||||
- application/vnd.github.v3+json
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.12.0
|
||||
Content-Type:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Server:
|
||||
- GitHub.com
|
||||
Date:
|
||||
- Tue, 25 Sep 2018 19:42:19 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4993'
|
||||
X-Ratelimit-Reset:
|
||||
- '1537907261'
|
||||
Cache-Control:
|
||||
- private, max-age=60, s-maxage=60
|
||||
Vary:
|
||||
- Accept, Authorization, Cookie, X-GitHub-OTP
|
||||
Etag:
|
||||
- W/"cf563de9cf5fd804d0232405d071b71a"
|
||||
Last-Modified:
|
||||
- Tue, 04 Sep 2018 21:09:29 GMT
|
||||
X-Oauth-Scopes:
|
||||
- public_repo, repo:status
|
||||
X-Accepted-Oauth-Scopes:
|
||||
- repo
|
||||
X-Github-Media-Type:
|
||||
- github.v3; format=json
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Runtime-Rack:
|
||||
- '0.072510'
|
||||
X-Github-Request-Id:
|
||||
- DEF9:675C:3CE1:80FA:5BAA8F9B
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{"url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/510","repository_url":"https://api.github.com/repos/thepracticaldev/dev.to","labels_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/510/labels{/name}","comments_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/510/comments","events_url":"https://api.github.com/repos/thepracticaldev/dev.to/issues/510/events","html_url":"https://github.com/thepracticaldev/dev.to/issues/510","id":354483683,"node_id":"MDU6SXNzdWUzNTQ0ODM2ODM=","number":510,"title":"Add
|
||||
to no follow to moderate links","user":{"login":"Zhao-Andy","id":17884966,"node_id":"MDQ6VXNlcjE3ODg0OTY2","avatar_url":"https://avatars0.githubusercontent.com/u/17884966?v=4","gravatar_id":"","url":"https://api.github.com/users/Zhao-Andy","html_url":"https://github.com/Zhao-Andy","followers_url":"https://api.github.com/users/Zhao-Andy/followers","following_url":"https://api.github.com/users/Zhao-Andy/following{/other_user}","gists_url":"https://api.github.com/users/Zhao-Andy/gists{/gist_id}","starred_url":"https://api.github.com/users/Zhao-Andy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Zhao-Andy/subscriptions","organizations_url":"https://api.github.com/users/Zhao-Andy/orgs","repos_url":"https://api.github.com/users/Zhao-Andy/repos","events_url":"https://api.github.com/users/Zhao-Andy/events{/privacy}","received_events_url":"https://api.github.com/users/Zhao-Andy/received_events","type":"User","site_admin":false},"labels":[{"id":1018588332,"node_id":"MDU6TGFiZWwxMDE4NTg4MzMy","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/approved","name":"approved","color":"A3FFBD","default":false},{"id":480869965,"node_id":"MDU6TGFiZWw0ODA4Njk5NjU=","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/bug","name":"bug","color":"ff050d","default":true},{"id":669356684,"node_id":"MDU6TGFiZWw2NjkzNTY2ODQ=","url":"https://api.github.com/repos/thepracticaldev/dev.to/labels/good%20first%20issue","name":"good
|
||||
first issue","color":"724ac9","default":true}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-08-27T21:23:19Z","updated_at":"2018-09-04T21:09:29Z","closed_at":"2018-09-04T21:09:29Z","author_association":"COLLABORATOR","body":"@jessleenyc
|
||||
commented on [Tue Jul 31 2018](https://github.com/thepracticaldev/dev.to_core/issues/638)\n\n#
|
||||
_TASK or Feature_\n### Request or User Story\nGetting lots of crawlers clicking
|
||||
on the hidden link that''s giving them 404 errors and jamming up honeybadger!\n###
|
||||
Definition of Done\n\n### Notes\n\n\n\n---\n\n@arun1595 commented on [Wed
|
||||
Aug 01 2018](https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-409774531)\n\n@jessleenyc
|
||||
I would like to tackle this issue. Can you guide me with what \"moderate\"
|
||||
links are?\r\n\r\nThanks.\n\n---\n\n@Zhao-Andy commented on [Mon Aug 27 2018](https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-416373282)\n\nHey
|
||||
@arun1595, we''re going to move this to the public repo and continue the conversation
|
||||
there.\n\n","closed_by":{"login":"benhalpern","id":3102842,"node_id":"MDQ6VXNlcjMxMDI4NDI=","avatar_url":"https://avatars0.githubusercontent.com/u/3102842?v=4","gravatar_id":"","url":"https://api.github.com/users/benhalpern","html_url":"https://github.com/benhalpern","followers_url":"https://api.github.com/users/benhalpern/followers","following_url":"https://api.github.com/users/benhalpern/following{/other_user}","gists_url":"https://api.github.com/users/benhalpern/gists{/gist_id}","starred_url":"https://api.github.com/users/benhalpern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/benhalpern/subscriptions","organizations_url":"https://api.github.com/users/benhalpern/orgs","repos_url":"https://api.github.com/users/benhalpern/repos","events_url":"https://api.github.com/users/benhalpern/events{/privacy}","received_events_url":"https://api.github.com/users/benhalpern/received_events","type":"User","site_admin":false}}'
|
||||
http_version:
|
||||
recorded_at: Tue, 25 Sep 2018 19:42:19 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.github.com/markdown
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"text":"@jessleenyc commented on [Tue Jul 31 2018](https://github.com/thepracticaldev/dev.to_core/issues/638)\n\n#
|
||||
_TASK or Feature_\n### Request or User Story\nGetting lots of crawlers clicking
|
||||
on the hidden link that''s giving them 404 errors and jamming up honeybadger!\n###
|
||||
Definition of Done\n\n### Notes\n\n\n\n---\n\n@arun1595 commented on [Wed
|
||||
Aug 01 2018](https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-409774531)\n\n@jessleenyc
|
||||
I would like to tackle this issue. Can you guide me with what \"moderate\"
|
||||
links are?\r\n\r\nThanks.\n\n---\n\n@Zhao-Andy commented on [Mon Aug 27 2018](https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-416373282)\n\nHey
|
||||
@arun1595, we''re going to move this to the public repo and continue the conversation
|
||||
there.\n\n"}'
|
||||
headers:
|
||||
Accept:
|
||||
- application/vnd.github.raw
|
||||
User-Agent:
|
||||
- Octokit Ruby Gem 4.12.0
|
||||
Content-Type:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Server:
|
||||
- GitHub.com
|
||||
Date:
|
||||
- Tue, 25 Sep 2018 19:42:19 GMT
|
||||
Content-Type:
|
||||
- text/html;charset=utf-8
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Status:
|
||||
- 200 OK
|
||||
X-Ratelimit-Limit:
|
||||
- '5000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '4992'
|
||||
X-Ratelimit-Reset:
|
||||
- '1537907261'
|
||||
X-Commonmarker-Version:
|
||||
- 0.17.11
|
||||
Access-Control-Expose-Headers:
|
||||
- ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining,
|
||||
X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
||||
Access-Control-Allow-Origin:
|
||||
- "*"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubdomains; preload
|
||||
X-Frame-Options:
|
||||
- deny
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Xss-Protection:
|
||||
- 1; mode=block
|
||||
Referrer-Policy:
|
||||
- origin-when-cross-origin, strict-origin-when-cross-origin
|
||||
Content-Security-Policy:
|
||||
- default-src 'none'
|
||||
X-Runtime-Rack:
|
||||
- '0.033681'
|
||||
X-Github-Request-Id:
|
||||
- DEFA:675C:3CF7:8124:5BAA8F9B
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |
|
||||
<p>@jessleenyc commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638">Tue Jul 31 2018</a></p>
|
||||
<h1>
|
||||
<a id="user-content-task-or-feature" class="anchor" href="#task-or-feature" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a><em>TASK or Feature</em>
|
||||
</h1>
|
||||
<h3>
|
||||
<a id="user-content-request-or-user-story" class="anchor" href="#request-or-user-story" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Request or User Story</h3>
|
||||
<p>Getting lots of crawlers clicking on the hidden link that's giving them 404 errors and jamming up honeybadger!</p>
|
||||
<h3>
|
||||
<a id="user-content-definition-of-done" class="anchor" href="#definition-of-done" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition of Done</h3>
|
||||
<h3>
|
||||
<a id="user-content-notes" class="anchor" href="#notes" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Notes</h3>
|
||||
<hr>
|
||||
<p>@arun1595 commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-409774531">Wed Aug 01 2018</a></p>
|
||||
<p>@jessleenyc I would like to tackle this issue. Can you guide me with what "moderate" links are?</p>
|
||||
<p>Thanks.</p>
|
||||
<hr>
|
||||
<p>@Zhao-Andy commented on <a href="https://github.com/thepracticaldev/dev.to_core/issues/638#issuecomment-416373282">Mon Aug 27 2018</a></p>
|
||||
<p>Hey @arun1595, we're going to move this to the public repo and continue the conversation there.</p>
|
||||
http_version:
|
||||
recorded_at: Tue, 25 Sep 2018 19:42:19 GMT
|
||||
recorded_with: VCR 4.0.0
|
||||
Loading…
Add table
Reference in a new issue