mirror of
				https://github.com/softprops/action-gh-release.git
				synced 2025-11-03 21:29:24 +00:00 
			
		
		
		
	node_modules
This commit is contained in:
		
							
								
								
									
										128
									
								
								node_modules/@octokit/plugin-throttling/lib/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								node_modules/@octokit/plugin-throttling/lib/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
module.exports = throttlingPlugin
 | 
			
		||||
 | 
			
		||||
const BottleneckLight = require('bottleneck/light')
 | 
			
		||||
const wrapRequest = require('./wrap-request')
 | 
			
		||||
const triggersNotificationPaths = require('./triggers-notification-paths')
 | 
			
		||||
const routeMatcher = require('./route-matcher')(triggersNotificationPaths)
 | 
			
		||||
 | 
			
		||||
// Workaround to allow tests to directly access the triggersNotification function.
 | 
			
		||||
const triggersNotification = throttlingPlugin.triggersNotification =
 | 
			
		||||
  routeMatcher.test.bind(routeMatcher)
 | 
			
		||||
 | 
			
		||||
const groups = {}
 | 
			
		||||
 | 
			
		||||
const createGroups = function (Bottleneck, common) {
 | 
			
		||||
  groups.global = new Bottleneck.Group({
 | 
			
		||||
    id: 'octokit-global',
 | 
			
		||||
    maxConcurrent: 10,
 | 
			
		||||
    ...common
 | 
			
		||||
  })
 | 
			
		||||
  groups.search = new Bottleneck.Group({
 | 
			
		||||
    id: 'octokit-search',
 | 
			
		||||
    maxConcurrent: 1,
 | 
			
		||||
    minTime: 2000,
 | 
			
		||||
    ...common
 | 
			
		||||
  })
 | 
			
		||||
  groups.write = new Bottleneck.Group({
 | 
			
		||||
    id: 'octokit-write',
 | 
			
		||||
    maxConcurrent: 1,
 | 
			
		||||
    minTime: 1000,
 | 
			
		||||
    ...common
 | 
			
		||||
  })
 | 
			
		||||
  groups.notifications = new Bottleneck.Group({
 | 
			
		||||
    id: 'octokit-notifications',
 | 
			
		||||
    maxConcurrent: 1,
 | 
			
		||||
    minTime: 3000,
 | 
			
		||||
    ...common
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function throttlingPlugin (octokit, octokitOptions = {}) {
 | 
			
		||||
  const {
 | 
			
		||||
    enabled = true,
 | 
			
		||||
    Bottleneck = BottleneckLight,
 | 
			
		||||
    id = 'no-id',
 | 
			
		||||
    timeout = 1000 * 60 * 2, // Redis TTL: 2 minutes
 | 
			
		||||
    connection
 | 
			
		||||
  } = octokitOptions.throttle || {}
 | 
			
		||||
  if (!enabled) {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  const common = { connection, timeout }
 | 
			
		||||
 | 
			
		||||
  if (groups.global == null) {
 | 
			
		||||
    createGroups(Bottleneck, common)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const state = Object.assign({
 | 
			
		||||
    clustering: connection != null,
 | 
			
		||||
    triggersNotification,
 | 
			
		||||
    minimumAbuseRetryAfter: 5,
 | 
			
		||||
    retryAfterBaseValue: 1000,
 | 
			
		||||
    retryLimiter: new Bottleneck(),
 | 
			
		||||
    id,
 | 
			
		||||
    ...groups
 | 
			
		||||
  }, octokitOptions.throttle)
 | 
			
		||||
 | 
			
		||||
  if (typeof state.onAbuseLimit !== 'function' || typeof state.onRateLimit !== 'function') {
 | 
			
		||||
    throw new Error(`octokit/plugin-throttling error:
 | 
			
		||||
        You must pass the onAbuseLimit and onRateLimit error handlers.
 | 
			
		||||
        See https://github.com/octokit/rest.js#throttling
 | 
			
		||||
 | 
			
		||||
        const octokit = new Octokit({
 | 
			
		||||
          throttle: {
 | 
			
		||||
            onAbuseLimit: (error, options) => {/* ... */},
 | 
			
		||||
            onRateLimit: (error, options) => {/* ... */}
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
    `)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const events = {}
 | 
			
		||||
  const emitter = new Bottleneck.Events(events)
 | 
			
		||||
  events.on('abuse-limit', state.onAbuseLimit)
 | 
			
		||||
  events.on('rate-limit', state.onRateLimit)
 | 
			
		||||
  events.on('error', e => console.warn('Error in throttling-plugin limit handler', e))
 | 
			
		||||
 | 
			
		||||
  state.retryLimiter.on('failed', async function (error, info) {
 | 
			
		||||
    const options = info.args[info.args.length - 1]
 | 
			
		||||
    const isGraphQL = options.url.startsWith('/graphql')
 | 
			
		||||
 | 
			
		||||
    if (!(isGraphQL || error.status === 403)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const retryCount = ~~options.request.retryCount
 | 
			
		||||
    options.request.retryCount = retryCount
 | 
			
		||||
 | 
			
		||||
    const { wantRetry, retryAfter } = await (async function () {
 | 
			
		||||
      if (/\babuse\b/i.test(error.message)) {
 | 
			
		||||
        // The user has hit the abuse rate limit. (REST only)
 | 
			
		||||
        // https://developer.github.com/v3/#abuse-rate-limits
 | 
			
		||||
 | 
			
		||||
        // The Retry-After header can sometimes be blank when hitting an abuse limit,
 | 
			
		||||
        // but is always present after 2-3s, so make sure to set `retryAfter` to at least 5s by default.
 | 
			
		||||
        const retryAfter = Math.max(~~error.headers['retry-after'], state.minimumAbuseRetryAfter)
 | 
			
		||||
        const wantRetry = await emitter.trigger('abuse-limit', retryAfter, options)
 | 
			
		||||
        return { wantRetry, retryAfter }
 | 
			
		||||
      }
 | 
			
		||||
      if (error.headers != null && error.headers['x-ratelimit-remaining'] === '0') {
 | 
			
		||||
        // The user has used all their allowed calls for the current time period (REST and GraphQL)
 | 
			
		||||
        // https://developer.github.com/v3/#rate-limiting
 | 
			
		||||
 | 
			
		||||
        const rateLimitReset = new Date(~~error.headers['x-ratelimit-reset'] * 1000).getTime()
 | 
			
		||||
        const retryAfter = Math.max(Math.ceil((rateLimitReset - Date.now()) / 1000), 0)
 | 
			
		||||
        const wantRetry = await emitter.trigger('rate-limit', retryAfter, options)
 | 
			
		||||
        return { wantRetry, retryAfter }
 | 
			
		||||
      }
 | 
			
		||||
      return {}
 | 
			
		||||
    })()
 | 
			
		||||
 | 
			
		||||
    if (wantRetry) {
 | 
			
		||||
      options.request.retryCount++
 | 
			
		||||
      return retryAfter * state.retryAfterBaseValue
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  octokit.hook.wrap('request', wrapRequest.bind(null, state))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								node_modules/@octokit/plugin-throttling/lib/route-matcher.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								node_modules/@octokit/plugin-throttling/lib/route-matcher.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
module.exports = routeMatcher
 | 
			
		||||
 | 
			
		||||
function routeMatcher (paths) {
 | 
			
		||||
  // EXAMPLE. For the following paths:
 | 
			
		||||
  /* [
 | 
			
		||||
      "/orgs/:org/invitations",
 | 
			
		||||
      "/repos/:owner/:repo/collaborators/:username"
 | 
			
		||||
  ] */
 | 
			
		||||
 | 
			
		||||
  const regexes = paths.map(p =>
 | 
			
		||||
    p.split('/')
 | 
			
		||||
      .map(c => c.startsWith(':') ? '(?:.+?)' : c)
 | 
			
		||||
      .join('/')
 | 
			
		||||
  )
 | 
			
		||||
  // 'regexes' would contain:
 | 
			
		||||
  /* [
 | 
			
		||||
      '/orgs/(?:.+?)/invitations',
 | 
			
		||||
      '/repos/(?:.+?)/(?:.+?)/collaborators/(?:.+?)'
 | 
			
		||||
  ] */
 | 
			
		||||
 | 
			
		||||
  const regex = `^(?:${regexes.map(r => `(?:${r})`).join('|')})[^/]*$`
 | 
			
		||||
  // 'regex' would contain:
 | 
			
		||||
  /*
 | 
			
		||||
    ^(?:(?:\/orgs\/(?:.+?)\/invitations)|(?:\/repos\/(?:.+?)\/(?:.+?)\/collaborators\/(?:.+?)))[^\/]*$
 | 
			
		||||
 | 
			
		||||
    It may look scary, but paste it into https://www.debuggex.com/
 | 
			
		||||
    and it will make a lot more sense!
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  return new RegExp(regex, 'i')
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								node_modules/@octokit/plugin-throttling/lib/triggers-notification-paths.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								node_modules/@octokit/plugin-throttling/lib/triggers-notification-paths.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
[
 | 
			
		||||
  "/orgs/:org/invitations",
 | 
			
		||||
  "/repos/:owner/:repo/collaborators/:username",
 | 
			
		||||
  "/repos/:owner/:repo/commits/:sha/comments",
 | 
			
		||||
  "/repos/:owner/:repo/issues",
 | 
			
		||||
  "/repos/:owner/:repo/issues/:issue_number/comments",
 | 
			
		||||
  "/repos/:owner/:repo/pulls",
 | 
			
		||||
  "/repos/:owner/:repo/pulls/:pull_number/comments",
 | 
			
		||||
  "/repos/:owner/:repo/pulls/:pull_number/merge",
 | 
			
		||||
  "/repos/:owner/:repo/pulls/:pull_number/requested_reviewers",
 | 
			
		||||
  "/repos/:owner/:repo/pulls/:pull_number/reviews",
 | 
			
		||||
  "/repos/:owner/:repo/releases",
 | 
			
		||||
  "/teams/:team_id/discussions",
 | 
			
		||||
  "/teams/:team_id/discussions/:discussion_number/comments"
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										49
									
								
								node_modules/@octokit/plugin-throttling/lib/wrap-request.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								node_modules/@octokit/plugin-throttling/lib/wrap-request.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
module.exports = wrapRequest
 | 
			
		||||
 | 
			
		||||
const noop = () => Promise.resolve()
 | 
			
		||||
 | 
			
		||||
function wrapRequest (state, request, options) {
 | 
			
		||||
  return state.retryLimiter.schedule(doRequest, state, request, options)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function doRequest (state, request, options) {
 | 
			
		||||
  const isWrite = options.method !== 'GET' && options.method !== 'HEAD'
 | 
			
		||||
  const isSearch = options.method === 'GET' && options.url.startsWith('/search/')
 | 
			
		||||
  const isGraphQL = options.url.startsWith('/graphql')
 | 
			
		||||
 | 
			
		||||
  const retryCount = ~~options.request.retryCount
 | 
			
		||||
  const jobOptions = retryCount > 0 ? { priority: 0, weight: 0 } : {}
 | 
			
		||||
  if (state.clustering) {
 | 
			
		||||
    // Remove a job from Redis if it has not completed or failed within 60s
 | 
			
		||||
    // Examples: Node process terminated, client disconnected, etc.
 | 
			
		||||
    jobOptions.expiration = 1000 * 60
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Guarantee at least 1000ms between writes
 | 
			
		||||
  // GraphQL can also trigger writes
 | 
			
		||||
  if (isWrite || isGraphQL) {
 | 
			
		||||
    await state.write.key(state.id).schedule(jobOptions, noop)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Guarantee at least 3000ms between requests that trigger notifications
 | 
			
		||||
  if (isWrite && state.triggersNotification(options.url)) {
 | 
			
		||||
    await state.notifications.key(state.id).schedule(jobOptions, noop)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Guarantee at least 2000ms between search requests
 | 
			
		||||
  if (isSearch) {
 | 
			
		||||
    await state.search.key(state.id).schedule(jobOptions, noop)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const req = state.global.key(state.id).schedule(jobOptions, request, options)
 | 
			
		||||
  if (isGraphQL) {
 | 
			
		||||
    const res = await req
 | 
			
		||||
    if (res.data.errors != null && res.data.errors.some((err) => err.type === 'RATE_LIMITED')) {
 | 
			
		||||
      const err = new Error('GraphQL Rate Limit Exceeded')
 | 
			
		||||
      err.headers = res.headers
 | 
			
		||||
      err.data = res.data
 | 
			
		||||
      throw err
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return req
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user