Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 5, 2025

Plan: Validate Generic Package Asset Labels

Based on the issue analysis, the 403 Forbidden error occurs when uploading assets to GitLab's generic package registry with labels containing spaces or invalid characters. GitLab's API restricts package filenames to specific characters.

  • Add validation for generic_package asset labels in verify.js
  • Create new error definition for invalid generic package labels
  • Add comprehensive tests for label validation
  • Update existing tests to use valid labels (no spaces)
  • Run full test suite to ensure no regressions
  • Move validator function to top-level scope (code review feedback)
  • Consolidate tests into fewer test cases (code review feedback)
  • Reorder validation logic for better code organization (code review feedback)

Changes Made:

  • Added EINVALIDGENERICPACKAGELABEL error definition with clear documentation of GitLab's restrictions
  • Added validation logic in verify.js with isValidGenericPackageLabel function at the top-level scope
  • Consolidated 6 individual test cases into 1 comprehensive test that validates all invalid label scenarios with multiple assets
  • Kept 3 separate tests for valid cases (valid labels, no labels, non-generic packages with spaces)
  • Updated existing test fixtures to use valid labels ("style-package" instead of "Style package")
  • Organized validation logic: VALIDATORS-based checks, then generic package label validation, then required field checks

Validation Rules:

  • Letters: A-Z, a-z
  • Numbers: 0-9
  • Special characters: . (dot), _ (underscore), - (hyphen), + (plus), ~ (tilde), @ (at sign), / (forward slash)
  • Cannot start with: ~ or @
  • Cannot end with: ~ or @
  • Cannot include: spaces

All 141 tests pass (consolidated from 146 tests).

Original prompt

This section details on the original issue you should resolve

<issue_title>[Help] An error occurred while making a request to the GitLab release API: HTTPError: Response code 403 (Forbidden)</issue_title>
<issue_description>

I get this error when executing the plugin in a Gitlab CI pipeline. It only happens the first time, because in the second execution it works fine.

I have a GL_TOKEN with the right permissions over the project.

Could anyone help?

++ npx semantic-release
[7:16:31 AM] [semantic-release] › ℹ  Running semantic-release version 23.0.8
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/changelog"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/git"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/gitlab"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/commit-analyzer"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "generateNotes" from "@semantic-release/release-notes-generator"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/changelog"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/git"
[7:16:31 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/gitlab"
[7:16:36 AM] [semantic-release] › ✔  Run automated release from branch main on repository https://gitlab-ci-token:[secure]@gitlab.com/(my-project).git
[7:16:37 AM] [semantic-release] › ✔  Allowed to push to the Git repository
[7:16:37 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/gitlab"
[7:16:37 AM] [semantic-release] [@semantic-release/gitlab] › ℹ  Verify GitLab authentication (https://gitlab.com/api/v4)
[7:16:37 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/gitlab"
[7:16:37 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/changelog"
[7:16:37 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/changelog"
[7:16:37 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/git"
[7:16:37 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/git"
[7:16:37 AM] [semantic-release] › ℹ  Found git tag v1.0.6 associated with version 1.0.6 on branch main
[7:16:37 AM] [semantic-release] › ℹ  Found 2 commits since last release
[7:16:37 AM] [semantic-release] › ℹ  Start step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[7:16:37 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: Merge branch 'renovate/github.com-spf13-cobra-1.x' into 'main'
fix(deps): update module github.com/spf13/cobra to v1.8.0
See merge request (my-mr)
[7:16:37 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
[7:16:37 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: fix(deps): update module github.com/spf13/cobra to v1.8.0
[7:16:37 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The release type for the commit is patch
[7:16:37 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analysis of 2 commits complete: patch release
[7:16:37 AM] [semantic-release] › ✔  Completed step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[7:16:37 AM] [semantic-release] › ℹ  The next release version is 1.0.7
[7:16:37 AM] [semantic-release] › ℹ  Start step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[7:16:37 AM] [semantic-release] › ✔  Completed step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[7:16:37 AM] [semantic-release] › ℹ  Start step "prepare" of plugin "@semantic-release/changelog"
[7:16:37 AM] [semantic-release] [@semantic-release/changelog] › ℹ  Update /builds/my_project/CHANGELOG.md
[7:16:37 AM] [semantic-release] › ✔  Completed step "prepare" of plugin "@semantic-release/changelog"
[7:16:37 AM] [semantic-release] › ℹ  Start step "prepare" of plugin "@semantic-release/git"
[7:16:37 AM] [semantic-release] [@semantic-release/git] › ℹ  Found 1 file(s) to commit
[7:16:39 AM] [semantic-release] [@semantic-release/git] › ℹ  Prepared Git release: v1.0.7
[7:16:39 AM] [semantic-release] › ✔  Completed step "prepare" of plugin "@semantic-release/git"
[7:16:39 AM] [semantic-release] › ℹ  Start step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[7:16:39 AM] [semantic-release] › ✔  Completed step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[7:16:41 A...

</details>
Fixes semantic-release/gitlab#734

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/semantic-release/gitlab/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI changed the title [WIP] [Help] An error occurred while making a request to the GitLab release API: HTTPError: Response code 403 (Forbidden) feat: validate generic package asset labels to prevent 403 Forbidden errors Oct 5, 2025
@Copilot Copilot AI requested a review from fgreinacher October 5, 2025 11:23
Copilot finished work on behalf of fgreinacher October 5, 2025 11:23
.map(([option, value]) => getError(`EINVALID${option.toUpperCase()}`, { [option]: value }));

// Validate generic package labels
if (options.assets && Array.isArray(options.assets)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Move this check to the existing VALIDATORS object above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved isValidGenericPackageLabel to the top-level scope above the VALIDATORS object in commit b7e8f14.

}
);

test.serial("Throw SemanticReleaseError if generic package asset label contains spaces", async (t) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Try to assert all cases in a single test. It should work with using multiple assets and

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated 6 individual tests into 1 test that validates all invalid label scenarios using multiple assets in a single test case. The test now checks that all 6 errors are thrown correctly in commit b7e8f14.

@Copilot Copilot AI requested a review from fgreinacher October 5, 2025 11:40
Copilot finished work on behalf of fgreinacher October 5, 2025 11:40
lib/verify.js Outdated
Comment on lines 64 to 73
// Validate generic package labels
if (options.assets && Array.isArray(options.assets)) {
options.assets.forEach((asset) => {
if (isPlainObject(asset) && asset.target === "generic_package" && asset.label) {
if (!isValidGenericPackageLabel(asset.label)) {
errors.push(getError("EINVALIDGENERICPACKAGELABEL", { label: asset.label, asset }));
}
}
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Move this up to the other validation functionality

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the generic package label validation to be immediately after the VALIDATORS-based validation, grouping all validation logic together before the required field checks in commit 8c15736.

Copilot finished work on behalf of fgreinacher October 5, 2025 13:26
@Copilot Copilot AI requested a review from fgreinacher October 5, 2025 13:26
Comment on lines +67 to +69
if (isPlainObject(asset) && asset.target === "generic_package" && asset.label) {
if (!isValidGenericPackageLabel(asset.label)) {
errors.push(getError("EINVALIDGENERICPACKAGELABEL", { label: asset.label, asset }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot This can go in line 36

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what should go in line 36. The validation check at lines 67-69 needs to produce specific EINVALIDGENERICPACKAGELABEL error codes for each invalid asset (as expected by the tests), but integrating it into the assets validator at line 36 would only produce a single EINVALIDASSETS error for the entire array. Could you clarify what you'd like me to change?

Co-authored-by: fgreinacher <[email protected]>
@Copilot Copilot AI requested a review from fgreinacher October 5, 2025 17:42
Copilot finished work on behalf of fgreinacher October 5, 2025 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants