Skip to content

Added publish scripts #6

Merged
HardMax71 merged 4 commits intomainfrom
dev
Dec 5, 2025
Merged

Added publish scripts #6
HardMax71 merged 4 commits intomainfrom
dev

Conversation

@HardMax71
Copy link
Owner

@HardMax71 HardMax71 commented Dec 5, 2025

Summary by CodeRabbit

  • New Features

    • Automated Docker image build & publish pipeline; production-ready frontend build served via a static webserver; secured dashboard access.
  • Documentation

    • Added contributor guidelines, updated readme with correct service URLs, provided sample environment and dashboard auth examples.
  • Improvements

    • Stricter runtime env handling for sensitive passwords; frontend robustness, accessibility and typings enhancements; CI env setup refined.

✏️ Tip: You can customize this high-level summary in your review settings.

…ssword)

- moved main passwords to dotenv file, same for traefik password
- added CONTRBUTING.md
- added cicd job to create and push packages to ghcr.io
- fixed TS errors in frontend
@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds environment templates and auth examples, a GitHub Actions workflow to build/publish Docker images, Traefik v3.6 and docker-compose updates enforcing required secrets, a multi-stage frontend Dockerfile with nginx + SPA config, TypeScript declaration files, docs, and small frontend type/null-safety adjustments.

Changes

Cohort / File(s) Summary
Configuration & Secrets
\.env.example, \.gitignore, traefik-dashboard-users.example
Adds a sample .env.example with Neo4j/Grafana passwords, API/Grafana URLs, and frontend target; ignores .env and traefik-dashboard-users; adds example htpasswd file and generation instructions.
CI/CD Workflow
.github/workflows/publish-images.yml
New workflow: matrix builds for backend and frontend, GHCR login, docker metadata tagging (semver/branch/sha/latest), build args for frontend, conditional push, SBOM/provenance attestation, and a summary job.
Local CI Tests
.github/workflows/tests.yml
Adjusted step to copy .env.example to .env (renamed step to "Create .env files") and removed a confirmation echo.
Documentation
CONTRIBUTING.md, README.md
Adds contributor guidelines (backend setup, pre-commit, lint/test/run instructions) and updates README to describe frontend stack and deployment URLs.
Orchestration (docker-compose)
docker-compose.yaml
Upgrades Traefik to v3.6, removes dashboard port mapping, adds dashboard users volume, labels and middleware, enforces required env vars (NEO4J_PASSWORD, GRAFANA_ADMIN_PASSWORD), and passes VITE_API_BASE_URL / VITE_GRAFANA_URL to frontend build with explicit build context/target.
Frontend Build & Serve
frontend/Dockerfile, frontend/nginx.conf
Introduces multi-stage frontend Dockerfile (base, builder, prod) with build args for API/Grafana URLs; prod served by nginx. Adds nginx.conf for SPA routing and long-term static caching.
Frontend Components & Types
frontend/src/components/Badge.tsx, frontend/src/components/ResultCard.tsx, frontend/src/components/SearchFilters.tsx, frontend/src/components/styled/Button.tsx, frontend/src/pages/Error.tsx, frontend/src/pages/JobStatus.tsx
Exports BadgeProps with expanded variants and optional title; null-safety defaults for skills/topSkills and simplified bullet rendering in ResultCard; SearchFilters uses nullish coalescing for role/company; IconButton props extended (href,target,rel,title); minor typing clarifications in Error.tsx and JobStatus.tsx.
Type Declarations
frontend/src/types/plantuml-encoder.d.ts, frontend/src/vite-env.d.ts
Adds plantuml-encoder declarations (encode, decode, default export) and a Vite client types reference directive.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

-重点 review areas:

  • docker-compose.yaml — Traefik v3.6 flags, router/service/middleware labels and htpasswd path.
  • .github/workflows/publish-images.yml — matrix/tagging logic, conditional push behavior, secrets usage.
  • frontend/Dockerfile + nginx.conf — build-arg propagation, dev vs prod targets, nginx SPA routing and caching.
  • Frontend component type changes (Badge.tsx, Button.tsx) — ensure exported types match consuming code.

Poem

🐇 I hopped through envs and CI in tow,
Built images, served pages in nginx glow,
Types and guards tucked safely in place,
Traefik's dashboard hides behind a brace,
A little rabbit celebrates the deploy flow.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Added publish scripts' does not accurately reflect the primary changes in this pull request, which include environment configuration setup (.env.example), Docker Compose updates with mandatory environment variables, GitHub Actions workflow for CI/CD (publish-images.yml), frontend Dockerfile refactoring for multi-stage builds, nginx configuration, and multiple frontend component improvements. The title is misleading as it suggests only publish scripts were added. Consider a more descriptive title that captures the main changes, such as 'Setup CI/CD pipeline with Docker image publishing, environment configuration, and frontend production build' or 'Add GitHub Actions workflow, environment configuration, and frontend production build support'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad11c44 and 3e0592b.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@HardMax71 HardMax71 merged commit f7862a9 into main Dec 5, 2025
3 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (10)
frontend/src/pages/JobStatus.tsx (1)

2003-2005: Avoid widening to any for section data lookup

Casting the reduce result to any drops type safety and makes downstream misuse easier to miss. Consider typing the reducer explicitly (e.g., a union based on the resume shape or unknown | null) instead of an any assertion.

traefik-dashboard-users.example (1)

1-6: Sample htpasswd file is clear and safely annotated

The generation command, format description, and explicit warning about the example credentials make this a useful reference without encouraging insecure reuse.

README.md (1)

34-35: Documentation updates are clear; optional tweak for markdownlint

The added frontend description and explicit backend/frontend localhost URLs make the quick-start story clearer. If you want to satisfy MD034 (“no bare URLs”), you could wrap the URLs as links, e.g. [http://localhost:8000](http://localhost:8000) and [http://localhost:5173](http://localhost:5173).

Also applies to: 58-58

CONTRIBUTING.md (1)

1-155: Backend contributing guide is thorough and aligned with the toolchain

This lays out pre-commit, Ruff/MyPy usage, pytest, and Docker workflows in a way that should make onboarding and PR hygiene much smoother. When you expand frontend contributions, you can mirror this structure with a short section for the React/Vite stack.

frontend/src/components/ResultCard.tsx (1)

338-338: Optional: Simplify redundant null coalescing.

The || [] operators are redundant since the parent conditional at line 329 already ensures result.skills exists and is non-empty. Within this block, both result.skills and topSkills are guaranteed to be defined arrays.

Apply this diff to simplify:

-            {(expanded ? result.skills || [] : topSkills || []).map((skill, idx) => (
+            {(expanded ? result.skills : topSkills).map((skill, idx) => (
.github/workflows/publish-images.yml (2)

82-82: Consider multi-architecture support.

The workflow currently builds only for linux/amd64. Consider adding linux/arm64 support for broader compatibility with ARM-based systems (e.g., AWS Graviton, Apple Silicon).

Apply this diff to add ARM64 support:

-          platforms: linux/amd64
+          platforms: linux/amd64,linux/arm64

111-116: Improve summary to distinguish individual image build status.

The current summary logic shows the same status for both backend and frontend images based on the overall job result. If one image fails while the other succeeds, this won't be reflected accurately.

Consider using the matrix outputs to show individual status per image, though this would require more complex logic to access matrix results. For now, this is acceptable for a simple summary.

frontend/nginx.conf (1)

1-14: Consider adding compression and security headers.

The configuration correctly handles SPA routing and caching, but could be enhanced with:

  • gzip compression for text assets
  • Security headers (X-Frame-Options, X-Content-Type-Options, X-XSS-Protection)

Add this configuration after the index directive:

    # Enable gzip compression
    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1000;
    
    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
frontend/Dockerfile (1)

2-23: Consider running nginx as non-root user for better security.

The multi-stage build is well-structured with proper ARG/ENV handling for build-time variables. However, the prod stage runs nginx as root by default.

Apply this diff to run nginx as a non-root user:

 FROM nginx:alpine AS prod
+RUN chown -R nginx:nginx /usr/share/nginx/html && \
+    chown -R nginx:nginx /var/cache/nginx && \
+    touch /var/run/nginx.pid && \
+    chown -R nginx:nginx /var/run/nginx.pid
+USER nginx
 COPY --from=builder /app/dist /usr/share/nginx/html
 COPY nginx.conf /etc/nginx/conf.d/default.conf
 EXPOSE 80

Note: You may need to adjust nginx.conf to listen on a port >1024 or use capabilities to bind to port 80 as non-root.

docker-compose.yaml (1)

181-182: Add environment variable validation for frontend URLs.

VITE_API_BASE_URL and VITE_GRAFANA_URL are now injected from environment variables but lack the error-checking syntax (:?) used for sensitive passwords. Consider requiring these explicitly:

-      - VITE_API_BASE_URL=${VITE_API_BASE_URL}
-      - VITE_GRAFANA_URL=${VITE_GRAFANA_URL}
+      - VITE_API_BASE_URL=${VITE_API_BASE_URL:?VITE_API_BASE_URL required}
+      - VITE_GRAFANA_URL=${VITE_GRAFANA_URL:?VITE_GRAFANA_URL required}

This prevents silent failures from missing configuration.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00b965a and ad11c44.

📒 Files selected for processing (17)
  • .env.example (1 hunks)
  • .github/workflows/publish-images.yml (1 hunks)
  • .gitignore (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • README.md (2 hunks)
  • docker-compose.yaml (5 hunks)
  • frontend/Dockerfile (1 hunks)
  • frontend/nginx.conf (1 hunks)
  • frontend/src/components/Badge.tsx (1 hunks)
  • frontend/src/components/ResultCard.tsx (2 hunks)
  • frontend/src/components/SearchFilters.tsx (1 hunks)
  • frontend/src/components/styled/Button.tsx (1 hunks)
  • frontend/src/pages/Error.tsx (1 hunks)
  • frontend/src/pages/JobStatus.tsx (1 hunks)
  • frontend/src/types/plantuml-encoder.d.ts (1 hunks)
  • frontend/src/vite-env.d.ts (1 hunks)
  • traefik-dashboard-users.example (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/SearchFilters.tsx (1)
frontend/src/components/filters/SearchableDropdown.tsx (1)
  • SearchableDropdown (25-93)
🪛 dotenv-linter (4.0.0)
.env.example

[warning] 2-2: [UnorderedKey] The GRAFANA_ADMIN_PASSWORD key should go before the NEO4J_PASSWORD key

(UnorderedKey)

🪛 LanguageTool
CONTRIBUTING.md

[style] ~136-~136: Consider shortening or rephrasing this to strengthen your wording.
Context: ...r-cleanup ``` ## Common Workflows ### Making Changes to Backend Code 1. Make your changes 2. R...

(MAKE_CHANGES)


[style] ~142-~142: Consider using a different verb for a more formal wording.
Context: ...ll run automatically) 5. If hooks fail, fix issues and commit again ### Adding New...

(FIX_RESOLVE)

🪛 markdownlint-cli2 (0.18.1)
README.md

58-58: Bare URL used

(MD034, no-bare-urls)


58-58: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (14)
frontend/src/pages/Error.tsx (1)

48-53: Error branch normalization looks good

Using a local const e = error as Error and reading message, stack, and name from it keeps the native Error path explicit without changing behavior.

.gitignore (1)

5-6: Good to ignore env and Traefik users files

Ignoring .env and the traefik-dashboard-users file is the right call to keep local secrets and dashboard credentials out of version control.

frontend/src/vite-env.d.ts (1)

1-1: Vite client types reference is appropriate

Adding /// <reference types="vite/client" /> under src/ correctly wires Vite’s TS types into the project.

frontend/src/components/SearchFilters.tsx (1)

52-52: Normalizing dropdown values to null improves controlled behavior

Using value={value.role ?? null} and value={value.company ?? null} ensures the dropdowns see a consistent string | null instead of undefined, which helps avoid React controlled/uncontrolled warnings and matches the onChange(null) semantics.

Also applies to: 60-60

frontend/src/components/ResultCard.tsx (1)

481-488: LGTM!

The use of the array form in map((point, pidx, arr)) is a good practice that makes the spacing calculation more robust and independent of the outer scope. The simplified rendering of point directly also improves readability.

frontend/src/types/plantuml-encoder.d.ts (1)

1-5: LGTM!

The type declarations for the plantuml-encoder module are correctly structured with both named exports and a default export containing the functions.

frontend/src/components/Badge.tsx (1)

3-22: LGTM!

The changes improve the component's public API by exporting BadgeProps, enhance accessibility with the title attribute, and simplify the className generation. The specific variant types provide better type safety.

.github/workflows/publish-images.yml (1)

43-45: Verify frontend build-time environment variables.

The VITE_API_BASE_URL=/api differs from the .env.example value (http://localhost:8000), and VITE_GRAFANA_URL is empty. Ensure these values are correct for the production build context where the frontend will be served behind a reverse proxy.

.env.example (1)

1-7: LGTM!

The environment variable template provides clear examples for all required configuration values. The static analysis warning about key ordering is purely stylistic and can be safely ignored.

frontend/Dockerfile (1)

12-18: LGTM!

The builder stage correctly uses ARGs with ENV variables to propagate build-time configuration into the Vite build process. This pattern ensures the environment variables are available during the npm run build step.

frontend/src/components/styled/Button.tsx (1)

41-41: The anchor-like props (href, target, rel) won't function on button elements without the as="a" prop.

These props are included in the IconButton TypeScript type definition but won't actually work when rendered as a button element—they need as="a" to be functional (e.g., <IconButton as="a" href="..." />). Current usage in Health.tsx correctly applies the as="a" prop when these anchor attributes are needed, but the type definition should either use transient props syntax (e.g., $href) to prevent passing them to the DOM, or document this constraint to prevent misuse.

docker-compose.yaml (3)

128-128: Approve mandatory password validation for Grafana.

The switch to ${GRAFANA_ADMIN_PASSWORD:?...} correctly enforces explicit password configuration, improving security posture by preventing accidental deployments with default credentials.


172-174: Approve frontend build configuration refactor with target selection.

The expansion to explicit context and target with ${FRONTEND_TARGET:-dev} default allows flexible builds (dev vs. prod). This is a clean pattern. Ensure corresponding Dockerfile stages exist.


94-94: The :? variable validation syntax is supported in docker-compose and should work correctly.

Line 94 uses ${NEO4J_PASSWORD:?NEO4J_PASSWORD required} for variable validation, which is a standard feature of docker-compose environment variable substitution. The nested substitution within the connection string will be properly evaluated. Consider testing that the neo4j-exporter service starts correctly and authenticates to neo4j when NEO4J_PASSWORD is not set (should display the error message) and when it is set (should authenticate successfully).

services:
traefik:
image: traefik:v2.9
image: traefik:v3.6
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "docker-compose.yaml" -o -name "docker-compose.yml" | head -5

Repository: HardMax71/ResuMariner

Length of output: 86


🏁 Script executed:

cat -n docker-compose.yaml | head -50

Repository: HardMax71/ResuMariner

Length of output: 2176


🏁 Script executed:

ls -la traefik-dashboard-users 2>/dev/null || echo "File not found"

Repository: HardMax71/ResuMariner

Length of output: 79


🌐 Web query:

Traefik v3.0 breaking changes from v2.9 command flags labels migration

💡 Result:

Brief summary — key breaking changes and migration steps when moving from Traefik v2.9 → v3.x affecting CLI flags, Docker/Swarm labels and rule syntax:

  • Default rule matcher syntax changed to v3 (v2 syntax deprecated). You can keep v2 behavior globally with static option core.defaultRuleSyntax: v2 or per-router with ruleSyntax=v2 label (or CLI --core.defaultRuleSyntax=v2) while you migrate. (doc.traefik.io)

  • Rule matcher renames/behavior changes (affects router rules in labels/Ingress):

    • Headers → Header, HeadersRegexp → HeaderRegexp; HostHeader removed (use Host).
    • PathPrefix no longer uses regex; many matchers now take a single value and must be combined explicitly. Adjust your traefik.http.routers.*.rule labels accordingly. (v2.doc.traefik.io)
  • Docker vs Swarm providers split (affects provider labels & flags):

    • v2 combined Docker+Swarm; v3 splits into docker (no Swarm) and swarm providers. Remove swarmMode from docker provider and switch to the new swarm provider config/flags. CLI flags changed to match providers (e.g. --providers.swarm.*). (doc.traefik.io)
  • Label renames / deprecations (note recent v3.x changes):

    • Some docker/swarm labels were renamed (example: traefik.docker.network and traefik.docker.lbswarm deprecated in favor of traefik.swarm.network and traefik.swarm.lbswarm for Swarm usage). Check provider-specific label renames for your version. (v2.doc.traefik.io)
  • CLI/static option name changes:

    • Some static options moved under new keys (example core.defaultRuleSyntax exposed as --core.defaultRuleSyntax). Review your startup flags and map them to v3 static keys. (doc.traefik.io)
  • Compatibility path & recommended process:

    • v3 keeps backward compatibility for dynamic (v2) format while you progressively migrate; recommended: enable core.defaultRuleSyntax: v2 for testing, then convert routers/labels one-by-one and remove compatibility when done. Follow the v2→v3 migration guide. (doc.traefik.io)

If you want, tell me your specific CLI flags or Docker labels (examples from your compose files or service labels) and I’ll map each to the v3 equivalent.

Citations:


🏁 Script executed:

cat .gitignore | grep -i traefik

Repository: HardMax71/ResuMariner

Length of output: 88


🏁 Script executed:

find . -name "*traefik*" -o -name "*users*" | grep -v ".git"

Repository: HardMax71/ResuMariner

Length of output: 98


🏁 Script executed:

rg "traefik-dashboard-users" --type yaml

Repository: HardMax71/ResuMariner

Length of output: 138


🏁 Script executed:

rg "dashboard.users" -i --type md

Repository: HardMax71/ResuMariner

Length of output: 47


Ensure traefik-dashboard-users file is created before deployment.

The dashboard authentication requires the traefik-dashboard-users file (mounted at line 17), but it is not committed to the repository. An example file traefik-dashboard-users.example exists; users must copy and configure it with their own credentials. Document this requirement or add a setup step to the README.

The command flags (lines 5–10) and dashboard labels (lines 23–27) are compatible with Traefik v3.6.

🤖 Prompt for AI Agents
In docker-compose.yaml at line 3 (image: traefik:v3.6) and the volume mount at
line 17 referencing traefik-dashboard-users, the deployment will fail or the
dashboard will be inaccessible because traefik-dashboard-users is not committed;
update the repo to ensure this file exists before deployment by (A) adding a
README setup step instructing users to copy traefik-dashboard-users.example to
traefik-dashboard-users and configure credentials, and (B) optionally add a
small setup script (e.g., scripts/setup-traefik.sh) that checks for the file and
copies the example if missing (and document running it in the README);
alternatively modify docker-compose to mount the file as optional or use an
env-driven choice so missing file won’t break startup, and include the exact
path and permission guidance in the README.

- "8081:8081"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik-dashboard-users:/dashboard-users:ro
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for the traefik-dashboard-users file in the repository
find . -name "*traefik-dashboard-users*" -o -name "*dashboard-users*" 2>/dev/null | head -20

Repository: HardMax71/ResuMariner

Length of output: 98


🏁 Script executed:

# List files in the root directory to understand structure
ls -la | grep -E "^\." | head -20

Repository: HardMax71/ResuMariner

Length of output: 47


🏁 Script executed:

# Search for documentation files (README, setup guides, .env files)
fd -e md -e txt -e env 2>/dev/null | head -30

Repository: HardMax71/ResuMariner

Length of output: 373


🏁 Script executed:

# Search for references to traefik-dashboard-users in docker-compose and other files
rg "traefik-dashboard-users|dashboard-users" --type yaml --type json --type md --type txt 2>/dev/null

Repository: HardMax71/ResuMariner

Length of output: 245


🏁 Script executed:

# Check the monitoring README for setup instructions
cat monitoring/README.md

Repository: HardMax71/ResuMariner

Length of output: 5338


🏁 Script executed:

# Check the content of the .example file
cat traefik-dashboard-users.example

Repository: HardMax71/ResuMariner

Length of output: 325


🏁 Script executed:

# Also check root README for setup instructions
cat README.md | grep -A 10 -B 5 -i "traefik\|dashboard\|setup"

Repository: HardMax71/ResuMariner

Length of output: 1468


Ensure traefik-dashboard-users file exists.

The volume mount at line 17 expects ./traefik-dashboard-users to be present on the host. A .example file exists showing the htpasswd format with instructions to generate it using docker run --rm httpd:alpine htpasswd -nb username password, but the actual file is missing from the repository and not documented in any setup guide. The Traefik container will fail to start without this file.

Add setup documentation to README.md or monitoring/README.md explaining that developers must copy traefik-dashboard-users.example to traefik-dashboard-users and populate it with htpasswd credentials, or include the actual file in the PR.

🤖 Prompt for AI Agents
In docker-compose.yaml around line 17, the volume mount references
./traefik-dashboard-users which is missing from the repo causing Traefik to fail
on startup; add documentation or the file: either include a committed
traefik-dashboard-users file with appropriate htpasswd entries (secure and
reviewed) or update README.md (or monitoring/README.md) with explicit setup
steps instructing developers to copy traefik-dashboard-users.example to
traefik-dashboard-users and generate credentials (e.g., docker run --rm
httpd:alpine htpasswd -nb username password) before running docker-compose;
ensure the README adds the exact filename, path, and a security note that the
file contains basic auth credentials.

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.

1 participant