-
Notifications
You must be signed in to change notification settings - Fork 0
feat: shared tag-format check #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # Reject a git tag that does not name a version. | ||
| # | ||
| # The org has accumulated three spellings for the same thing - `1.1.0`, | ||
| # `v1.1.0` and `v.1.1.1` - which is why nothing could reliably resolve "the | ||
| # release that produced this image". One spelling is enforced from here on: | ||
| # | ||
| # git tag vX.Y.Z v2.0.0, v2.1.0-rc.1 | ||
| # image tag X.Y.Z 2.0.0 | ||
| # chart version X.Y.Z 2.0.0 | ||
| # | ||
| # so `appVersion` and the image tag are literally the same string, and the git | ||
| # tag is that string with a `v`. Existing history is not retagged; this only | ||
| # stops new ones. | ||
| # | ||
| # Called by each repo on a tag push. Reusable rather than copied so the grammar | ||
| # lives in one place. | ||
|
|
||
| name: Check tag format | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| tag: | ||
| description: "Tag to check. Defaults to the ref that triggered the caller." | ||
| type: string | ||
| required: false | ||
| default: "" | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| check: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Validate | ||
| env: | ||
| INPUT_TAG: ${{ inputs.tag }} | ||
| CALLER_REF: ${{ github.ref }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| TAG="$INPUT_TAG" | ||
| if [[ -z "$TAG" ]]; then | ||
| case "$CALLER_REF" in | ||
| refs/tags/*) TAG="${CALLER_REF#refs/tags/}" ;; | ||
| *) echo "::notice::not a tag ref (${CALLER_REF}); nothing to check"; exit 0 ;; | ||
| esac | ||
| fi | ||
|
|
||
| echo "checking: ${TAG}" | ||
|
|
||
| # vMAJOR.MINOR.PATCH, optionally -prerelease and +build. | ||
| # Deliberately strict: no `v.`, no bare `1.1.0`, no `release-1.1.0`. | ||
| SEMVER='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$' | ||
| if [[ "$TAG" =~ $SEMVER ]]; then | ||
| echo "::notice::${TAG} is a valid release tag" | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "::error::'${TAG}' is not a valid release tag." | ||
| echo "::error::Expected vMAJOR.MINOR.PATCH, e.g. v2.0.0 or v2.1.0-rc.1." | ||
| case "$TAG" in | ||
| v.*) echo "::error:: '${TAG}' has a dot after the v. Use v${TAG#v.}" ;; | ||
| [0-9]*) echo "::error:: '${TAG}' is missing the leading v. Use v${TAG}" ;; | ||
| V*) echo "::error:: the v is lowercase. Use v${TAG#V}" ;; | ||
| esac | ||
| echo "::error::The image tag and chart version are the same string without the v," | ||
| echo "::error::so a tag that does not parse leaves nothing able to resolve which" | ||
| echo "::error::release produced a given image." | ||
| exit 1 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| #!/usr/bin/env bash | ||
| # The grammar in check-tag-format.yml, exercised against the tags the org has | ||
| # actually produced. Extracted from the workflow rather than restated, so the | ||
| # two cannot drift. | ||
|
|
||
| set -uo pipefail | ||
| ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | ||
| WF="$ROOT/.github/workflows/check-tag-format.yml" | ||
| FAILED=0 | ||
| ok() { printf ' PASS %s\n' "$1"; } | ||
| bad() { printf ' FAIL %s\n' "$1"; FAILED=1; } | ||
|
|
||
| SEMVER=$(yq -r '.jobs.check.steps[0].run' "$WF" | grep -oE "SEMVER='.*'" | sed "s/SEMVER='//;s/'$//") | ||
| [[ -n "$SEMVER" ]] || { echo "could not extract the pattern from $WF"; exit 1; } | ||
| echo "pattern: $SEMVER" | ||
| echo | ||
|
|
||
| accept() { [[ "$1" =~ $SEMVER ]]; } | ||
|
|
||
| echo "=== must accept ===" | ||
| for t in v2.0.0 v1.1.0 v2.1.0-rc.1 v10.20.30 v1.0.0-next.7 v0.1.0 v2.0.0-pr.24.abc1234; do | ||
| accept "$t" && ok "$t" || bad "should accept $t" | ||
| done | ||
|
|
||
| echo | ||
| echo "=== must reject (all three spellings this org has actually used) ===" | ||
| for t in 1.1.0 v.1.1.1 V2.0.0 release-1.1.0 v1.1 v1.1.0.1 latest main "v1.1.0 " "" theia-workspace-garbage-collector-0.1.0; do | ||
| accept "$t" && bad "should reject '${t:-<empty>}'" || ok "rejects '${t:-<empty>}'" | ||
| done | ||
|
|
||
| echo | ||
| [[ $FAILED -eq 0 ]] && echo "ALL PASS" || echo "SOME FAILED" | ||
| exit $FAILED |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: EduIDE/.github
Length of output: 370
🏁 Script executed:
Repository: EduIDE/.github
Length of output: 45648
🌐 Web query:
OCI image tag grammar plus sign maximum 128 characters distribution specification💡 Result:
Under the Open Container Initiative (OCI) Distribution Specification, OCI image tags do not support the plus sign (+) character [1][2]. The specification formally defines a valid tag as a string that must be at most 128 characters in length and must match the following regular expression [1][2]: [a-zA-Z0-9_][a-zA-Z0-9._-]{0,127} Because the plus sign (+) is not included in this allowed character set, it is invalid in OCI image tags [1][2]. While there have been community discussions and feature requests to allow the plus sign to better support Semantic Versioning (SemVer), the specification has not been updated to include it [3][4]. Consequently, tools like Helm often implement workarounds, such as converting plus signs to underscores when interacting with OCI registries [5].
Citations:
🏁 Script executed:
Repository: EduIDE/.github
Length of output: 3503
Enforce the 128-character image-tag limit.
SEMVERaccepts tags whose unprefixed value exceeds 128 characters. The publishing workflow later normalizes the tag and rejectsBASE_TAG, so the tag passes this check but fails in the publishing workflow. Add the length check and a long-tag case totests/test-tag-format.sh. Build metadata does not require rejection here because the publishing workflow converts+to-.🤖 Prompt for AI Agents