Sintaxe de definição de grupos de pacotes e comportamento de correspondência - CodeArtifact

Sintaxe de definição de grupos de pacotes e comportamento de correspondência

Este tópico contém informações sobre como definir grupos de pacotes, comportamento de correspondência de padrões, força de associação de pacotes e hierarquia de grupos de pacotes.

Sintaxe de definição de grupos de pacotes e exemplos

A sintaxe padrão para definir grupos de pacotes segue de perto a formatação dos caminhos de pacotes. Um caminho de pacote é criado com base nos componentes de coordenadas de um pacote (formato, namespace e nome), adicionando uma barra no início e separando cada um dos componentes com uma barra. Por exemplo, o caminho do pacote npm chamado anycompany-ui-components no namespace space é /npm/space/anycompany-ui-components.

Um padrão de grupo de pacotes segue a mesma estrutura de um caminho de pacote, exceto que os componentes que não são especificados como parte da definição do grupo são omitidos e o padrão é finalizado com um sufixo. O sufixo incluído determina o comportamento correspondente do padrão, da seguinte forma:

  • Um sufixo $ corresponderá à coordenada completa do pacote.

  • Um sufixo ~ corresponderá a um prefixo.

  • Um sufixo * corresponderá a todos os valores do componente definido anteriormente.

Veja abaixo exemplos de padrões para cada uma das combinações permitidas:

  1. Todos os formatos de pacote: /*

  2. Formato de pacote específico: /npm/*

  3. Formato e prefixo do namespace do pacote: /maven/com.anycompany~

  4. Formato e namespace do pacote: /npm/space/*

  5. Formato, namespace e prefixo do nome do pacote: /npm/space/anycompany-ui~

  6. Formato, namespace e nome do pacote: /maven/org.apache.logging.log4j/log4j-core$

Conforme mostrado nos exemplos acima, o sufixo ~ é adicionado ao final de um namespace ou nome para representar uma correspondência de prefixo, e * é adicionado após uma barra quando usado para corresponder a todos os valores do próximo componente no caminho (todos os formatos, todos os namespaces ou todos os nomes).

Definição e normalização de grupos de pacotes

O CodeArtifact normaliza os nomes de pacotes NuGet, Python e Swift, e normaliza os namespaces dos pacotes Swift antes de armazená-los. O CodeArtifact usa esses nomes normalizados ao corresponder pacotes com definições de grupos de pacotes. Portanto, grupos de pacotes que contêm um namespace ou nome nesses formatos devem usar o namespace e o nome normalizados. Para obter mais informações sobre como os nomes e namespaces dos pacotes são normalizados, consulte a documentação de normalização de nomes do NuGet, Python e Swift.

Namespaces nas definições de grupos de pacotes

Para pacotes ou formatos de pacotes sem um namespace (Python e NuGet), os grupos de pacotes não devem conter um namespace. A definição do grupo de pacotes para esses grupos de pacotes contém uma seção de namespace em branco. Por exemplo, o caminho para o pacote Python chamado requests é /python//requests.

Para pacotes ou formatos de pacotes com um namespace (Maven, genérico e Swift), o namespace deverá ser incluído se o nome do pacote estiver incluído. Para o formato de pacote Swift, o namespace normalizado do pacote será usado. Para obter mais informações sobre como os namespaces de pacote Swift são normalizados, consulte Normalização do nome e do namespace do pacote Swift.

Hierarquia de grupos de pacotes e especificidade de padrões

Os pacotes que estão “em” ou “associados a” um grupo de pacotes são pacotes com um caminho de pacote que corresponde ao padrão do grupo, mas não corresponde ao padrão de um grupo mais específico. Por exemplo, dados os grupos de pacotes /npm/* e /npm/space/*, o caminho do pacote /npm//react está associado ao primeiro grupo (/npm/*), enquanto /npm/space/aui.components e /npm/space/amplify-ui-core estão associados ao segundo grupo (/npm/space/*). Embora um pacote possa corresponder a vários grupos, cada pacote está associado somente a um único grupo, a correspondência mais específica, e somente a configuração desse grupo se aplica ao pacote.

Quando um caminho de pacote corresponde a vários padrões, o padrão “mais específico” pode ser considerado o padrão de correspondência mais longo. Alternativamente, o padrão mais específico é aquele que corresponde a um subconjunto próprio dos pacotes que correspondem ao padrão menos específico. Em exemplo anterior, todo pacote que corresponde a /npm/space/* também corresponde a /npm/*, mas o inverso não é verdadeiro, o que torna /npm/space/* o padrão mais específico porque é um subconjunto próprio de /npm/*. Como um grupo é um subconjunto de outro grupo, cria-se uma hierarquia, na qual /npm/space/* é um subgrupo do grupo principal, /npm/*.

Embora somente a configuração mais específica do grupo de pacotes se aplique a um pacote, esse grupo pode ser configurado para herdar da configuração do grupo principal.

Palavras, limites de palavras e correspondência de prefixos

Antes de discutir a correspondência de prefixos, vamos definir alguns termos-chave:

  • Uma palavra é uma letra ou número seguido por zero ou mais letras, números ou caracteres diacríticos (como acentos, tremas etc.).

  • O limite de uma palavra ocorre no final de uma palavra, quando um caractere que não é uma palavra é atingido. Caracteres que não são palavras são caracteres de pontuação, como ., - e _.

Especificamente, o padrão regex para uma palavra é [\p{L}\p{N}][\p{L}\p{N}\p{M}]*, que pode ser detalhado da seguinte forma:

  • \p{L} representa qualquer letra.

  • \p{N} representa qualquer número.

  • \p{M} representa qualquer caractere diacrítico, como acentos, tremas etc.

Portanto, [\p{L}\p{N}] representa um número ou letra, e [\p{L}\p{N}\p{M}]* representa zero ou mais letras, números ou caracteres diacríticos, e um limite de palavra está no final de cada correspondência desse padrão regex.

nota

A correspondência de limites de palavras é baseada nessa definição de “palavra”. Não é baseada em palavras definidas em um dicionário ou em camelCase. Por exemplo, não há limite de palavras em oneword ou OneWord.

Agora que a palavra e o limite da palavra estão definidos, podemos usá-los para descrever a correspondência de prefixos no CodeArtifact. Para indicar uma correspondência de prefixo no limite de uma palavra, um caractere de correspondência (~) é usado após um caractere de palavra. Por exemplo, o padrão /npm/space/foo~ corresponde aos caminhos do pacote /npm/space/foo e /npm/space/foo-bar, mas não /npm/space/food ou /npm/space/foot.

É necessário usar um curinga (*) em vez de ~ após um caractere que não seja uma palavra, como no padrão /npm/*.

Diferenciação de letras maiúsculas e minúsculas

As definições de grupos de pacotes diferenciam maiúsculas de minúsculas, o que significa que padrões que diferem somente por maiúsculas e minúsculas podem existir como grupos de pacotes separados. Por exemplo, um usuário pode criar grupos de pacotes separados com os padrões /npm//AsyncStorage$, /npm//asyncStorage$ e /npm//asyncstorage$ para os três pacotes separados que existem no Registro Público do npm: AsyncStorage, asyncStorage, asyncstorage, que diferem somente por maiúsculas e minúsculas.

Embora a distinção entre maiúsculas e minúsculas seja importante, o CodeArtifact ainda associa pacotes a um grupo de pacotes se o pacote tiver uma variação do padrão que difere por maiúsculas e minúsculas. Se um usuário criar o grupo de pacotes /npm//AsyncStorage$ sem criar os outros dois grupos mostrados acima, todas as variações de maiúsculas e minúsculas do nome AsyncStorage, incluindo asyncStorage e asyncstorage, serão associadas ao grupo de pacotes. Mas, conforme descrito na próxima seção, Correspondência forte e fraca, essas variações serão tratadas de forma diferente do AsyncStorage, que corresponde exatamente ao padrão.

Correspondência forte e fraca

As informações na seção anterior, Diferenciação de letras maiúsculas e minúsculas, afirmam que os grupos de pacotes diferenciam maiúsculas de minúsculas e, em seguida, explicam que não diferenciam. Isso ocorre porque as definições de grupos de pacotes no CodeArtifact têm um conceito de correspondência forte (ou correspondência exata) e correspondência fraca (ou correspondência de variação). Uma correspondência forte é quando o pacote corresponde exatamente ao padrão, sem qualquer variação. Uma correspondência fraca ocorre quando o pacote corresponde a uma variação do padrão, como letras maiúsculas e minúsculas diferentes. O comportamento de correspondência fraca impede que pacotes que são variações do padrão de um grupo de pacotes sejam acumulados em um grupo de pacotes mais geral. Quando um pacote é uma variação (correspondência fraca) do padrão do grupo de correspondência mais específico, o pacote é associado ao grupo, mas é bloqueado em vez de aplicar a configuração de controle de origem do grupo, impedindo que novas versões do pacote sejam retiradas de upstreams ou publicadas. Esse comportamento reduz o risco de ataques à cadeia de suprimentos resultantes da confusão de dependências de pacotes com nomes quase idênticos.

Para ilustrar um comportamento de correspondência fraca, suponha que o grupo de pacotes /npm/* permita a ingestão e bloqueie a publicação. Um grupo de pacotes mais específico, /npm//anycompany-spicy-client$, está configurado para bloquear a ingestão e permitir a publicação. O pacote chamado anycompany-spicy-client é uma correspondência forte do grupo de pacotes, que permite que versões de pacotes sejam publicadas e bloqueia a ingestão de versões de pacotes. A única forma permitida de publicar o nome do pacote com maiúsculas e minúsculas é anycompany-spicy-client, pois é uma correspondência forte com o padrão de definição do pacote. Uma variação diferente, como AnyCompany-spicy-client, é bloqueada para publicação porque é uma correspondência fraca. Mais importante ainda, o grupo de pacotes bloqueia a ingestão de todas as variações de maiúsculas e minúsculas, não somente do nome em minúsculas usado no padrão, reduzindo o risco de um ataque de confusão de dependências.

Variações adicionais

Além das diferenças entre maiúsculas e minúsculas, a correspondência fraca também ignora as diferenças em sequências de traços -, pontos ., sublinhados _ e caracteres que podem ser confundidos (como caracteres de aparência semelhante de alfabetos diferentes). Durante a normalização usada para correspondência fraca, o CodeArtifact realiza a conversão de maiúsculas e minúsculas (semelhante à conversão para minúsculas), substitui sequências de caracteres de traço, ponto e sublinhado por um único ponto e normaliza caracteres que podem ser confundidos.

A correspondência fraca trata traços, pontos e sublinhados como equivalentes, mas não os ignora completamente. Isso significa que foo-bar, foo.bar, foo..bar e foo_bar são todos equivalentes de correspondência fraca, mas foobar não é. Embora vários repositórios públicos implementem etapas para evitar esses tipos de variações, a proteção fornecida pelos repositórios públicos não torna esse recurso de grupos de pacotes desnecessário. Por exemplo, repositórios públicos como o Registro Público do npm só evitarão novas variações do pacote chamado my-package se my-package já estiver publicado nele. Se my-package for um pacote interno e o grupo de pacotes /npm//my-package$ for criado permitindo a publicação e bloqueando a ingestão, você provavelmente não desejará publicar my-package no Registro Público do npm para evitar que uma variante como my.package seja permitida.

Embora alguns formatos de pacote, como o Maven, tratem esses caracteres de forma diferente (o Maven trata . como um separador de hierarquia de namespace, mas não - ou _), algo como com.act-on ainda pode ser confundido com com.act.on.

nota

Observe que sempre que várias variações são associadas a um grupo de pacotes, um administrador pode criar um novo grupo de pacotes para uma variação específica para configurar um comportamento diferente para essa variação.