Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ jobs:
GIT_BRANCH: ${{ github.ref_name }}
GIT_COMMIT: ${{ github.sha }}
S3_ENDPOINT: ${{ vars.S3_ENDPOINT_DEV }}
- name: Extract project version
id: get_version
run: |
set -euo pipefail
RAW_VERSION="$(jq -r .version package.json)"
if [ -z "$RAW_VERSION" ] || [ "$RAW_VERSION" = "null" ]; then
echo "ERROR: Could not extract version from package.json" >&2
exit 1
fi
SAFE_VERSION="$(printf '%s' "$RAW_VERSION" | tr -c 'A-Za-z0-9_.-' '-')"
SHORT_SHA="$(echo ${{ github.sha }} | cut -c1-7)"
echo "version=v${SAFE_VERSION}-dev-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
- working-directory: .
name: push the docker image
run: docker compose -f docker-compose.dev.yml push api-server frontend queue-consumer documentation artifact-uploader
- name: Tag and push versioned images
env:
VERSION: ${{ steps.get_version.outputs.version }}
run: |
if docker manifest inspect rslethz/kleinkram:api-server-${VERSION} > /dev/null 2>&1; then
echo "ERROR: Version tag ${VERSION} already exists in registry." >&2
exit 1
fi
docker tag rslethz/kleinkram:api-server-dev rslethz/kleinkram:api-server-${VERSION}
docker push rslethz/kleinkram:api-server-${VERSION}
docker tag rslethz/kleinkram:frontend-dev rslethz/kleinkram:frontend-${VERSION}
docker push rslethz/kleinkram:frontend-${VERSION}
docker tag rslethz/kleinkram:queue-consumer-dev rslethz/kleinkram:queue-consumer-${VERSION}
docker push rslethz/kleinkram:queue-consumer-${VERSION}
docker tag rslethz/kleinkram:docs-dev rslethz/kleinkram:docs-${VERSION}
docker push rslethz/kleinkram:docs-${VERSION}
docker tag rslethz/kleinkram:artifact-uploader-dev rslethz/kleinkram:artifact-uploader-${VERSION}
docker push rslethz/kleinkram:artifact-uploader-${VERSION}
Comment on lines +46 to +59

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Partial overwrite protection — only api-server is guarded

The existence check only inspects rslethz/kleinkram:api-server-${VERSION}. The remaining four images (frontend, queue-consumer, docs, artifact-uploader) are tagged and pushed without any duplicate check.

Two concrete failure scenarios arise:

  1. Partial previous run — if a prior workflow run tagged api-server and frontend but then failed, re-running will correctly error on the api-server check, making the run unrecoverable without bumping the version. No image can be retried.
  2. Stale tags for other services — if api-server-${VERSION} does not yet exist but frontend-${VERSION} does (e.g. from a manual push), the check passes and the frontend image is silently overwritten.

Consider extending the guard to all five services:

for SERVICE in api-server frontend queue-consumer docs artifact-uploader; do
    if docker manifest inspect rslethz/kleinkram:${SERVICE}-${VERSION} > /dev/null 2>&1; then
        echo "ERROR: Version tag ${SERVICE}-${VERSION} already exists in registry." >&2
        exit 1
    fi
done

The same issue exists in production-build.yml lines 44–57.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/dev-build.yml
Line: 46-59

Comment:
**Partial overwrite protection — only `api-server` is guarded**

The existence check only inspects `rslethz/kleinkram:api-server-${VERSION}`. The remaining four images (`frontend`, `queue-consumer`, `docs`, `artifact-uploader`) are tagged and pushed without any duplicate check.

Two concrete failure scenarios arise:

1. **Partial previous run** — if a prior workflow run tagged `api-server` and `frontend` but then failed, re-running will correctly error on the `api-server` check, making the run unrecoverable without bumping the version. No image can be retried.
2. **Stale tags for other services** — if `api-server-${VERSION}` does not yet exist but `frontend-${VERSION}` does (e.g. from a manual push), the check passes and the `frontend` image is silently overwritten.

Consider extending the guard to all five services:

```
for SERVICE in api-server frontend queue-consumer docs artifact-uploader; do
    if docker manifest inspect rslethz/kleinkram:${SERVICE}-${VERSION} > /dev/null 2>&1; then
        echo "ERROR: Version tag ${SERVICE}-${VERSION} already exists in registry." >&2
        exit 1
    fi
done
```

The same issue exists in `production-build.yml` lines 44–57.

How can I resolve this? If you propose a fix, please make it concise.

28 changes: 28 additions & 0 deletions .github/workflows/production-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,34 @@ jobs:
GIT_BRANCH: ${{ github.ref_name }}
GIT_COMMIT: ${{ github.sha }}
S3_ENDPOINT: ${{ vars.S3_ENDPOINT }}
- name: Extract project version
id: get_version
run: |
VERSION="$(jq -r .version package.json)"
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
echo "ERROR: Could not extract version from package.json" >&2
exit 1
fi
VERSION_WITHOUT_BUILD="${VERSION%%+*}"
echo "version=v${VERSION_WITHOUT_BUILD}" >> "$GITHUB_OUTPUT"
Comment on lines +27 to +36

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing set -euo pipefail vs. dev workflow

The dev workflow's "Extract project version" step opens with set -euo pipefail, but the equivalent step in production-build.yml does not. Without pipefail, a failure in a sub-command that feeds into a variable assignment via $() can be silently masked (the assignment itself returns exit 0). Although the explicit null-check guard on lines 31–34 covers the most common failure mode, adding set -euo pipefail makes the script consistently defensive and brings parity with the dev workflow.

Suggested change
- name: Extract project version
id: get_version
run: |
VERSION="$(jq -r .version package.json)"
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
echo "ERROR: Could not extract version from package.json" >&2
exit 1
fi
VERSION_WITHOUT_BUILD="${VERSION%%+*}"
echo "version=v${VERSION_WITHOUT_BUILD}" >> "$GITHUB_OUTPUT"
run: |
set -euo pipefail
VERSION="$(jq -r .version package.json)"
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/production-build.yml
Line: 27-36

Comment:
**Missing `set -euo pipefail` vs. dev workflow**

The dev workflow's "Extract project version" step opens with `set -euo pipefail`, but the equivalent step in `production-build.yml` does not. Without `pipefail`, a failure in a sub-command that feeds into a variable assignment via `$()` can be silently masked (the assignment itself returns exit 0). Although the explicit null-check guard on lines 31–34 covers the most common failure mode, adding `set -euo pipefail` makes the script consistently defensive and brings parity with the dev workflow.

```suggestion
              run: |
                  set -euo pipefail
                  VERSION="$(jq -r .version package.json)"
                  if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +30 to +36

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No version string sanitization for Docker tag compatibility

The dev workflow sanitizes the raw version with tr -c 'A-Za-z0-9_.-' '-' before using it as a Docker tag, guarding against any non-standard characters in package.json. The production workflow only strips SemVer build metadata (%%+*) but does not apply the same sanitization.

Docker tags are restricted to [a-zA-Z0-9_.-]. While valid SemVer strings are already Docker-safe after stripping the + build segment, adding the same tr sanitization step would be a low-cost consistency improvement that prevents surprises if the version string ever contains unexpected characters.

Suggested change
VERSION="$(jq -r .version package.json)"
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
echo "ERROR: Could not extract version from package.json" >&2
exit 1
fi
VERSION_WITHOUT_BUILD="${VERSION%%+*}"
echo "version=v${VERSION_WITHOUT_BUILD}" >> "$GITHUB_OUTPUT"
VERSION_WITHOUT_BUILD="${VERSION%%+*}"
SAFE_VERSION="$(printf '%s' "$VERSION_WITHOUT_BUILD" | tr -c 'A-Za-z0-9_.-' '-')"
echo "version=v${SAFE_VERSION}" >> "$GITHUB_OUTPUT"
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/production-build.yml
Line: 30-36

Comment:
**No version string sanitization for Docker tag compatibility**

The dev workflow sanitizes the raw version with `tr -c 'A-Za-z0-9_.-' '-'` before using it as a Docker tag, guarding against any non-standard characters in `package.json`. The production workflow only strips SemVer build metadata (`%%+*`) but does not apply the same sanitization.

Docker tags are restricted to `[a-zA-Z0-9_.-]`. While valid SemVer strings are already Docker-safe after stripping the `+` build segment, adding the same `tr` sanitization step would be a low-cost consistency improvement that prevents surprises if the version string ever contains unexpected characters.

```suggestion
                  VERSION_WITHOUT_BUILD="${VERSION%%+*}"
                  SAFE_VERSION="$(printf '%s' "$VERSION_WITHOUT_BUILD" | tr -c 'A-Za-z0-9_.-' '-')"
                  echo "version=v${SAFE_VERSION}" >> "$GITHUB_OUTPUT"
```

How can I resolve this? If you propose a fix, please make it concise.

- working-directory: .
name: push the docker image
run: docker compose -f docker-compose.prod.yml push api-server frontend queue-consumer documentation artifact-uploader
- name: Tag and push versioned images
env:
VERSION: ${{ steps.get_version.outputs.version }}
run: |
if docker manifest inspect rslethz/kleinkram:api-server-${VERSION} > /dev/null 2>&1; then
echo "ERROR: Version tag ${VERSION} already exists in registry." >&2
exit 1
fi
docker tag rslethz/kleinkram:api-server-latest rslethz/kleinkram:api-server-${VERSION}
docker push rslethz/kleinkram:api-server-${VERSION}
docker tag rslethz/kleinkram:frontend-latest rslethz/kleinkram:frontend-${VERSION}
docker push rslethz/kleinkram:frontend-${VERSION}
docker tag rslethz/kleinkram:queue-consumer-latest rslethz/kleinkram:queue-consumer-${VERSION}
docker push rslethz/kleinkram:queue-consumer-${VERSION}
docker tag rslethz/kleinkram:docs-latest rslethz/kleinkram:docs-${VERSION}
docker push rslethz/kleinkram:docs-${VERSION}
docker tag rslethz/kleinkram:artifact-uploader-latest rslethz/kleinkram:artifact-uploader-${VERSION}
docker push rslethz/kleinkram:artifact-uploader-${VERSION}
Loading