File Explorer

/var/lang/lib/node_modules/npm/lib/commands/trust

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

0 dirs
6 files
circleci.js5.7 KB · 180 lines
const Definition = require('@npmcli/config/lib/definitions/definition.js')const globalDefinitions = require('@npmcli/config/lib/definitions/definitions.js')const TrustCommand = require('../../trust-cmd.js') // UUID validation regexconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i class TrustCircleCI extends TrustCommand {  static description = 'Create a trusted relationship between a package and CircleCI'  static name = 'circleci'  static positionals = 1 // expects at most 1 positional (package name)  static providerName = 'CircleCI'  static providerEntity = 'CircleCI pipeline'   static usage = [    '[package] --org-id <uuid> --project-id <uuid> --pipeline-definition-id <uuid> --vcs-origin <origin> [--context-id <uuid>...] [-y|--yes]',  ]   static definitions = [    new Definition('org-id', {      default: null,      type: String,      required: true,      description: 'CircleCI organization UUID',    }),    new Definition('project-id', {      default: null,      type: String,      required: true,      description: 'CircleCI project UUID',    }),    new Definition('pipeline-definition-id', {      default: null,      type: String,      required: true,      description: 'CircleCI pipeline definition UUID',    }),    new Definition('vcs-origin', {      default: null,      type: String,      required: true,      description: "CircleCI repository origin in format 'provider/owner/repo'",    }),    new Definition('context-id', {      default: null,      type: [null, String, Array],      description: 'CircleCI context UUID to match',    }),    // globals are alphabetical    globalDefinitions['dry-run'],    globalDefinitions.json,    globalDefinitions.registry,    globalDefinitions.yes,  ]   validateUuid (value, fieldName) {    if (!UUID_REGEX.test(value)) {      throw new Error(`${fieldName} must be a valid UUID`)    }  }   validateVcsOrigin (value) {    // Expected format: provider/owner/repo (e.g., github.com/owner/repo, bitbucket.org/owner/repo)    if (value.includes('://')) {      throw new Error("vcs-origin must not include a scheme (e.g., use 'github.com/owner/repo' not 'https://github.com/owner/repo')")    }    const parts = value.split('/')    if (parts.length < 3) {      throw new Error("vcs-origin must be in format 'provider/owner/repo'")    }  }   // Generate a URL from vcs-origin (e.g., github.com/npm/repo -> https://github.com/npm/repo)  getVcsOriginUrl (vcsOrigin) {    if (!vcsOrigin) {      return null    }    // vcs-origin format: github.com/owner/repo or bitbucket.org/owner/repo    return `https://${vcsOrigin}`  }   static optionsToBody (options) {    const { orgId, projectId, pipelineDefinitionId, vcsOrigin, contextIds } = options    const trustConfig = {      type: 'circleci',      claims: {        'oidc.circleci.com/org-id': orgId,        'oidc.circleci.com/project-id': projectId,        'oidc.circleci.com/pipeline-definition-id': pipelineDefinitionId,        'oidc.circleci.com/vcs-origin': vcsOrigin,      },    }    if (contextIds && contextIds.length > 0) {      trustConfig.claims['oidc.circleci.com/context-ids'] = contextIds    }    return trustConfig  }   static bodyToOptions (body) {    return {      ...(body.id) && { id: body.id },      ...(body.type) && { type: body.type },      ...(body.claims?.['oidc.circleci.com/org-id']) && { orgId: body.claims['oidc.circleci.com/org-id'] },      ...(body.claims?.['oidc.circleci.com/project-id']) && { projectId: body.claims['oidc.circleci.com/project-id'] },      ...(body.claims?.['oidc.circleci.com/pipeline-definition-id']) && {        pipelineDefinitionId: body.claims['oidc.circleci.com/pipeline-definition-id'],      },      ...(body.claims?.['oidc.circleci.com/vcs-origin']) && { vcsOrigin: body.claims['oidc.circleci.com/vcs-origin'] },      ...(body.claims?.['oidc.circleci.com/context-ids']) && { contextIds: body.claims['oidc.circleci.com/context-ids'] },    }  }   // Override flagsToOptions since CircleCI doesn't use file/entity pattern  async flagsToOptions ({ positionalArgs, flags }) {    const content = await this.optionalPkgJson()    const pkgName = positionalArgs[0] || content.name     if (!pkgName) {      throw new Error('Package name must be specified either as an argument or in package.json file')    }     const orgId = flags['org-id']    const projectId = flags['project-id']    const pipelineDefinitionId = flags['pipeline-definition-id']    const vcsOrigin = flags['vcs-origin']    const contextIds = flags['context-id']     // Validate required flags    if (!orgId) {      throw new Error('org-id is required')    }    if (!projectId) {      throw new Error('project-id is required')    }    if (!pipelineDefinitionId) {      throw new Error('pipeline-definition-id is required')    }    if (!vcsOrigin) {      throw new Error('vcs-origin is required')    }     // Validate formats    this.validateUuid(orgId, 'org-id')    this.validateUuid(projectId, 'project-id')    this.validateUuid(pipelineDefinitionId, 'pipeline-definition-id')    this.validateVcsOrigin(vcsOrigin)    if (contextIds?.length > 0) {      for (const contextId of contextIds) {        this.validateUuid(contextId, 'context-id')      }    }     return {      values: {        package: pkgName,        orgId,        projectId,        pipelineDefinitionId,        vcsOrigin,        ...(contextIds?.length > 0 && { contextIds }),      },      fromPackageJson: {},      warnings: [],      urls: {        package: this.getFrontendUrl({ pkgName }),        vcsOrigin: this.getVcsOriginUrl(vcsOrigin),      },    }  }   async exec (positionalArgs, flags) {    await this.createConfigCommand({      positionalArgs,      flags,    })  }} module.exports = TrustCircleCI