Skip to content

Feature/cd#147

Closed
theaskou wants to merge 2 commits into
mainfrom
feature/CD
Closed

Feature/cd#147
theaskou wants to merge 2 commits into
mainfrom
feature/CD

Conversation

@theaskou
Copy link
Copy Markdown
Contributor

@theaskou theaskou commented Apr 18, 2025

Description

Please provide a summary of the change and explain what problem it solves. Include any relevant motivation and context.

Related Issue:
If applicable, please reference the issue number that this pull request fixes:
Fixes #[issue-number]

Type of Change

Please check the type(s) of changes your code introduces:

  • Bug fix: Non-breaking change which fixes an issue.
  • New feature: Non-breaking change which adds functionality.
  • Breaking change: Fix or feature that would cause existing functionality to change.
  • Documentation update: Changes to documentation only.

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce the testing environment.

  • Test A
  • Test B

Include any details regarding your testing environment, test configuration, or steps to reproduce.

Checklist

Before creating this pull request, please ensure that your code meets the following requirements:

  • My code follows the style guidelines of this project.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings.
  • Any dependent changes have been merged and published in downstream modules.

Screenshots (if applicable)

If your pull request includes visual changes, please include screenshots or animated GIFs to help explain your changes.

Additional Context

Add any other context or screenshots about your pull request here.

Summary by CodeRabbit

  • New Features

    • Introduced automated end-to-end testing using Playwright, including test suites for about, login, registration, search, and weather features.
    • Added new continuous deployment workflow for automated deployment to the development environment.
    • Added Docker Compose services for Nginx and Certbot, and enhanced log persistence for the Sinatra app.
  • Chores

    • Restructured CI workflows to separate Ruby tests, Ruby linting, and Dockerfile linting for improved clarity and modularity.
    • Updated continuous delivery workflow triggers to only run on main and dev branches.
    • Added and updated .gitignore files to exclude logs and test artifacts.
  • Bug Fixes

    • Ensured correct permissions for log directories within the Sinatra app container.
  • Refactor

    • Renamed and reformatted helper methods and SQL queries for clarity.
    • Improved session secret assignment and code comments for maintainability.
  • Tests

    • Added Playwright configuration and package files for cross-browser testing.
    • Implemented comprehensive end-to-end test coverage for key user flows.
  • Documentation

    • Added a new SQL schema for test database setup.

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented Apr 18, 2025

Here's the code health analysis summary for commits b39de12..6c5197a. View details on DeepSource ↗.

Analysis Summary

AnalyzerStatusSummaryLink
DeepSource Ruby LogoRuby✅ SuccessView Check ↗
DeepSource Docker LogoDocker✅ SuccessView Check ↗

💡 If you’re a repository administrator, you can configure the quality gates from the settings.

@theaskou theaskou closed this Apr 18, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2025

Walkthrough

This update introduces substantial changes to CI/CD and testing infrastructure, as well as several improvements to the Sinatra application and its Docker deployment. The CI workflow is split into separate jobs for Ruby tests, Ruby linting, and Dockerfile linting. New workflows are added for continuous deployment to a development environment and for running Playwright end-to-end tests. The Docker Compose files are restructured for both development and production, adding Nginx, Certbot, and persistent logging. The Sinatra app receives minor code refactoring and logging directory handling. New Playwright E2E test suites and supporting configuration files are added, along with a test SQL schema.

Changes

File(s) / Path(s) Change Summary
.github/workflows/ci.yaml Restructured CI workflow into three jobs: Ruby tests, Ruby linting (RuboCop), and Dockerfile linting (Hadolint); improved dependency installation and modularity.
.github/workflows/continuous_delivery.yml Modified workflow triggers to only run on main and dev branches; minor formatting update.
.github/workflows/continuous_deployment.yml Added new workflow for automated deployment to the dev environment via SSH and Docker Compose on Azure VM.
.github/workflows/playwright.yml Added new workflow to run Playwright end-to-end tests on push, PR, and manual dispatch.
.gitignore Added redundant *.log.* pattern under "Django stuff" section.
sinatra/app.rb Refactored session secret assignment; moved log rotation comment above logger instantiation.
sinatra/benchmark_search.rb Reformatted SQL query string for readability; logic unchanged.
sinatra/docker-compose.dev.yml Major restructure: use prebuilt app image, add Nginx and Certbot services, persistent volumes for data/logs/certs, improved environment variable handling.
sinatra/docker-compose.prod.yml Added persistent named volume for logs in app service.
sinatra/docker-entrypoint.sh Ensured /app/log directory exists and has correct ownership for logging.
sinatra/helpers/application_helpers.rb Renamed method get_cached_forecast to cached_forecast.
sinatra/routes/api.rb, sinatra/routes/pages.rb Updated calls to use cached_forecast instead of the old method name.
sinatra/schema_test.sql Added new SQL schema for testing: creates users and pages tables with initial data.
sinatra/tests/.gitignore Added ignore rules for node_modules, test results, Playwright reports, and cache.
sinatra/tests/e2e/about.spec.js Added Playwright E2E test for the about page.
sinatra/tests/e2e/login.spec.js Added Playwright E2E tests for login page, including error and (skipped) success scenarios.
sinatra/tests/e2e/register.spec.js Added Playwright E2E tests for registration page, covering rendering, error, and success cases.
sinatra/tests/e2e/search.spec.js Added Playwright E2E tests for search functionality, covering valid and invalid search terms.
sinatra/tests/e2e/weather.spec.js Added Playwright E2E tests for weather API and UI, covering both success and error scenarios.
sinatra/tests/package.json Added Node.js package definition for Playwright tests with dependencies and test script.
sinatra/tests/playwright.config.js Added Playwright configuration for cross-browser E2E testing with web server startup.

Sequence Diagram(s)

sequenceDiagram
    participant GitHubActions
    participant AzureVM
    participant DockerCompose
    participant SinatraApp
    participant Nginx
    participant Certbot

    GitHubActions->>AzureVM: SSH (after successful CI/CD on dev)
    GitHubActions->>AzureVM: SCP docker-compose and nginx config
    AzureVM->>DockerCompose: docker-compose pull, up -d
    DockerCompose->>SinatraApp: Start app container
    DockerCompose->>Nginx: Start Nginx container
    DockerCompose->>Certbot: Start Certbot container
    Certbot->>Nginx: Share certs via volume
    Nginx->>SinatraApp: Proxy requests
Loading
sequenceDiagram
    participant GitHubActions
    participant Playwright
    participant SinatraApp

    GitHubActions->>SinatraApp: Start test server (webServer)
    GitHubActions->>Playwright: Install dependencies & browsers
    Playwright->>SinatraApp: Run E2E tests (API/UI)
    Playwright->>GitHubActions: Upload test report
Loading

Possibly related PRs

Suggested reviewers

  • Aleksandergreg

Poem

🐇
CI hops in three neat rows,
Docker logs where the carrot grows.
Playwright tests on every page,
Weather, search, and user stage.
Nginx and Certbot join the show—
E2E dreams in YAML flow!

(From a rabbit who loves to deploy and test,
This code is ready—let’s hop to the rest!)

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@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: 7

🧹 Nitpick comments (28)
.gitignore (1)

58-60: Remove duplicate ignore pattern.

The pattern *.log.* appears twice in the Django section (lines 58 and 60), which is redundant. Please remove one of the duplicates to keep the file clean and maintainable.

sinatra/helpers/application_helpers.rb (1)

78-105: Consider refactoring for readability and testability.

The cached_forecast method’s complexity (ABC size ≈ 25.2) exceeds the recommended threshold. Splitting cache validation, fetch logic, and cache update into smaller private methods will improve maintainability and make unit testing more granular.

🧰 Tools
🪛 RuboCop (1.73)

[convention] 78-105: Assignment Branch Condition size for cached_forecast is too high. [<5, 24, 6> 25.24/23]

(Metrics/AbcSize)


[convention] 89-99: Do not use unless with else. Rewrite these with the positive case first.

(Style/UnlessElse)

sinatra/tests/package.json (1)

1-16: Mark package as private and enrich metadata.

This package.json defines your E2E test harness and should not be published to NPM. Consider adding:

{
  "private": true,
  "repository": { "type": "git", "url": "<repo-url>" },
  "description": "Playwright end-to-end tests for Sinatra app",
  "author": "<your-name>"
}

to prevent accidental publication and improve package metadata.

sinatra/schema_test.sql (2)

15-21: Improve the pages table schema with default timestamp.

The last_updated column should ideally have a default value of the current timestamp to ensure it's always populated.

CREATE TABLE IF NOT EXISTS pages (
    title TEXT PRIMARY KEY UNIQUE,
    url TEXT NOT NULL UNIQUE,
    language TEXT NOT NULL CHECK(language IN ('en', 'da')) DEFAULT 'en', -- How you define ENUM type in SQLite
-    last_updated TIMESTAMP,
+    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    content TEXT NOT NULL
);

22-23: Use a more realistic URL in test data.

The URL value 'www' is not a valid URL. Consider using a more realistic URL to better represent production data.

INSERT INTO pages (title, url, language, content)
- VALUES ('JavaScript Page','www','en','This page contains information about JavaScript.');
+ VALUES ('JavaScript Page','https://example.com/javascript','en','This page contains information about JavaScript.');
.github/workflows/continuous_delivery.yml (1)

21-21: Remove trailing whitespace.

There's a trailing space after with: which is flagged by linters. While it doesn't affect functionality, fixing it maintains consistent code style.

-        with: 
+        with:
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 21-21: trailing spaces

(trailing-spaces)

sinatra/tests/e2e/about.spec.js (1)

1-8: Great addition of end-to-end test for the about page

This test effectively verifies the key elements of the about page. The test structure is clear and follows Playwright best practices.

Consider using a more specific selector for the paragraph instead of the generic page.locator('p'), since multiple paragraphs might exist on the page. For example:

-await expect(page.locator('p')).toContainText("We intend to build the world's best search engine!");
+await expect(page.locator('p:has-text("We intend")')).toContainText("We intend to build the world's best search engine!");

Or use a more specific container if there's a section or div that contains the mission statement:

await expect(page.locator('.mission-section p')).toContainText("We intend to build the world's best search engine!");
sinatra/tests/e2e/login.spec.js (2)

23-32: Consider documenting test data setup requirements

The skipped test is correctly marked with a comment about requiring seeded test data, but it would be helpful to add instructions on how to set up this test user or modify the test to create its own test user.


30-30: Use more flexible URL validation

The strict URL equality check might be fragile if the base URL varies across environments or if query parameters are present.

- expect(page.url()).toBe('/');
+ expect(page.url()).toContain('/');

Or even better, check for the path specifically:

- expect(page.url()).toBe('/');
+ expect(new URL(page.url()).pathname).toBe('/');
sinatra/tests/e2e/search.spec.js (3)

42-43: Fix duplicate comment

The comment on line 42 is duplicated from line 39 but the code is checking for empty results.

- // Check the URL updates with the search term
+ // Verify no results are shown

43-44: Consider consolidating redundant checks

Lines 43-44 both check for the absence of search results in slightly different ways. Consider consolidating to a single, clear assertion.

- await expect(page.locator('.search-result-title')).toHaveCount(0);
- await expect(page.locator('#results')).toBeEmpty();
+ // Check that there are no search results
+ await expect(page.locator('#results')).toBeEmpty();

8-9: Consider making the test data more robust

The hardcoded search term "JavaScript" assumes this will always return results, which might not be true if test data changes.

Consider:

  1. Ensuring test data always contains this term
  2. Creating test data within the test
  3. Using a selector that's less dependent on specific content
// Example approach - dynamically find a term from available data
test('should return results for a valid search term', async ({ page }) => {
  // First find an available term from the page content
  await page.goto('/');
  const availableText = await page.locator('.some-content').first().textContent();
  const searchableTerm = availableText.split(' ')[0]; // Use first word
  
  // Then search for it
  const input = page.getByPlaceholder('Search...');
  await input.fill(searchableTerm);
  // Continue test as before...
});
sinatra/tests/e2e/register.spec.js (2)

4-6: Fix indentation inconsistency

The indentation in the beforeEach block doesn't match the rest of the file. Consider standardizing to 2 spaces for consistency.

  test.beforeEach(async ({ page }) => {
-        await page.goto('/register');
-      });
+    await page.goto('/register');
+  });

40-40: Consider more flexible URL validation

Similar to the login tests, using a strict URL check might be fragile across different environments.

- await expect(page).toHaveURL('/');
+ await expect(page.url()).toContain('/');

Or better:

- await expect(page).toHaveURL('/');
+ await expect(new URL(page.url()).pathname).toBe('/');
.github/workflows/continuous_deployment.yml (1)

27-33: Fix trailing spaces in YAML file

There are trailing spaces on lines 27, 30, and 33. Remove these for cleaner code.

  scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx
-          
+
  ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
    echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
-            
+
    docker-compose pull
    docker-compose up -d
-            
+
    docker image prune -f
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 27-27: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 33-33: trailing spaces

(trailing-spaces)

sinatra/tests/e2e/weather.spec.js (1)

4-23: Consider adding more specific error case tests

The current test handles both success and error paths elegantly. To make the tests more robust, consider adding specific test cases that explicitly test the error scenario by mocking a failure response from the weather API.

 test('JSON API returns valid forecast or error', async ({ request }) => {
   const response = await request.get('/api/weather');
   // API should respond with either 200 (OK) or 503 (Service Unavailable)
   const status = response.status();
   expect([200, 503]).toContain(status);

   const body = await response.json();
   if (response.ok()) {
     // Expect city name + forecast data
     expect(body).toHaveProperty('city_name');
     expect(body).toHaveProperty('data');
     expect(Array.isArray(body.data)).toBe(true);
     expect(body.data.length).toBeGreaterThan(0);
   } else {
     // Error response should include status: 'error' and a message
     expect(body).toHaveProperty('status', 'error');
     expect(body).toHaveProperty('message');
     expect(typeof body.message).toBe('string');
   }
 });
+
+// Additional test case for error scenario
+test('API handles errors properly when weather service is unavailable', async ({ request, page }) => {
+  // This would require mocking the external API failure in your test environment
+  // or testing with an invalid API key
+  const response = await request.get('/api/weather?test_error=true');
+  expect(response.status()).toBe(503);
+  
+  const body = await response.json();
+  expect(body).toHaveProperty('status', 'error');
+  expect(body).toHaveProperty('message');
+});
.github/workflows/playwright.yml (3)

37-37: Fix the trailing whitespace

There's a trailing space after true which should be removed to address the YAMLlint warning.

-        bundler-cache: true 
+        bundler-cache: true
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 37-37: trailing spaces

(trailing-spaces)


68-70: Consider documenting the WEATHERBIT_API_KEY secret requirement

The workflow uses the WEATHERBIT_API_KEY secret but there's no documentation about how to set up this secret in the repository. Consider adding a comment explaining what this key is used for and how to obtain it.

      env:
+        # Required: Add WEATHERBIT_API_KEY to your GitHub repository secrets
+        # This key is used for the weather API calls during tests
+        # Obtain a key from: https://www.weatherbit.io/
        WEATHERBIT_API_KEY: ${{ secrets.WEATHERBIT_API_KEY }}
      run: npx playwright test --reporter=html

40-53: Document why Sinatra startup is commented out

The commented-out Sinatra startup section might confuse future developers. Consider adding a comment explaining that this approach has been replaced by the web server configuration in the Playwright config file.

+    # Note: Sinatra startup is now handled by the webServer configuration in playwright.config.js
     # - name: Start Sinatra app
     #   working-directory: sinatra
     #   run: bundle exec rackup -p 4568 &
sinatra/docker-compose.dev.yml (1)

35-35: Add a newline at the end of the file

Add a newline at the end of the file to comply with YAML best practices and fix the linting warning.

   certbot_www:
   sinatra_logs:
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 35-35: no new line character at the end of file

(new-line-at-end-of-file)

sinatra/tests/playwright.config.js (2)

16-21: Consider adding comments about the database setup

The web server configuration assumes a specific database path and setup. Consider adding a comment explaining how this relates to the database setup in the CI workflow.

   webServer: {
+    // Uses the test database that's prepared in the CI workflow (see .github/workflows/playwright.yml)
+    // This database is populated with schema_test.sql and fts5.sql
     command: 'DATABASE_PATH=./test/test_whoknows.db bundle exec rackup -p 4568',
     url: 'http://127.0.0.1:4568',
     cwd: '../',
     reuseExistingServer: !process.env.CI,
   },

38-38: Fix array formatting

The closing bracket of the projects array is on the same line as the last element, which is inconsistent with the opening style. Consider moving it to a new line for better readability.

     {
       name: 'webkit',
       use: { ...devices['Desktop Safari'] },
-    },]
+    },
+  ]
.github/workflows/ci.yaml (6)

1-2: Add concurrency to prevent redundant workflow runs.

It’s recommended to add a concurrency key at the root of the workflow to cancel in‐flight runs for the same PR or branch, avoiding wasteful duplicate executions.

Example:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

3-9: Scope manual triggers with branch filters.

Currently workflow_dispatch allows manual runs on any branch. Consider constraining it to main and dev (or other relevant branches) to avoid unintended executions.

Example:

on:
  workflow_dispatch:
    branches:
      - main
      - dev

11-24: DRY up the Ruby setup across jobs.

The Set up Ruby steps (with ruby/setup-ruby@v1 and bundler-cache) are duplicated in multiple jobs. You could extract them into a reusable job or use job-level defaults to reduce boilerplate and ensure consistency.


25-28: Optimize system dependency installation.

To speed up and slim down the runner image, you can combine flags and drop recommended packages:

- sudo apt-get update
- sudo apt-get install -y sqlite3 libsqlite3-dev
+ sudo apt-get update && \
+   sudo apt-get install -y --no-install-recommends sqlite3 libsqlite3-dev && \
+   sudo rm -rf /var/lib/apt/lists/*

30-33: Enhance bundler install resilience.

Add parallelism and retries to bundle install:

- run: bundle install
+ run: |
+   bundle install --jobs 4 --retry 3

This speeds up installs and handles transient network glitches.


40-44: Run all tests rather than a single file.

Instead of targeting one test file, use a glob to exercise the full suite:

- run: bundle exec ruby -Itest test/app_test.rb
+ run: bundle exec ruby -Itest test/**/*_test.rb

This ensures new tests are automatically picked up.

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de9dfaa and 6c5197a.

⛔ Files ignored due to path filters (1)
  • sinatra/tests/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • .github/workflows/ci.yaml (1 hunks)
  • .github/workflows/continuous_delivery.yml (2 hunks)
  • .github/workflows/continuous_deployment.yml (1 hunks)
  • .github/workflows/playwright.yml (1 hunks)
  • .gitignore (1 hunks)
  • sinatra/app.rb (2 hunks)
  • sinatra/benchmark_search.rb (1 hunks)
  • sinatra/docker-compose.dev.yml (1 hunks)
  • sinatra/docker-compose.prod.yml (2 hunks)
  • sinatra/docker-entrypoint.sh (1 hunks)
  • sinatra/helpers/application_helpers.rb (1 hunks)
  • sinatra/routes/api.rb (1 hunks)
  • sinatra/routes/pages.rb (1 hunks)
  • sinatra/schema_test.sql (1 hunks)
  • sinatra/tests/.gitignore (1 hunks)
  • sinatra/tests/e2e/about.spec.js (1 hunks)
  • sinatra/tests/e2e/login.spec.js (1 hunks)
  • sinatra/tests/e2e/register.spec.js (1 hunks)
  • sinatra/tests/e2e/search.spec.js (1 hunks)
  • sinatra/tests/e2e/weather.spec.js (1 hunks)
  • sinatra/tests/package.json (1 hunks)
  • sinatra/tests/playwright.config.js (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
sinatra/tests/e2e/login.spec.js (5)
sinatra/tests/e2e/about.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/register.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/search.spec.js (1)
  • require (1-1)
sinatra/tests/playwright.config.js (1)
  • require (2-2)
sinatra/tests/e2e/weather.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/search.spec.js (5)
sinatra/tests/e2e/login.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/about.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/register.spec.js (1)
  • require (1-1)
sinatra/tests/playwright.config.js (1)
  • require (2-2)
sinatra/tests/e2e/weather.spec.js (1)
  • require (1-1)
sinatra/routes/api.rb (1)
sinatra/helpers/application_helpers.rb (1)
  • cached_forecast (78-105)
sinatra/routes/pages.rb (1)
sinatra/helpers/application_helpers.rb (1)
  • cached_forecast (78-105)
sinatra/tests/e2e/about.spec.js (5)
sinatra/tests/e2e/login.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/register.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/search.spec.js (1)
  • require (1-1)
sinatra/tests/playwright.config.js (1)
  • require (2-2)
sinatra/tests/e2e/weather.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/weather.spec.js (5)
sinatra/tests/e2e/login.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/about.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/register.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/search.spec.js (1)
  • require (1-1)
sinatra/tests/playwright.config.js (1)
  • require (2-2)
sinatra/tests/playwright.config.js (5)
sinatra/tests/e2e/login.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/about.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/register.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/search.spec.js (1)
  • require (1-1)
sinatra/tests/e2e/weather.spec.js (1)
  • require (1-1)
🪛 YAMLlint (1.35.1)
.github/workflows/playwright.yml

[error] 37-37: trailing spaces

(trailing-spaces)

sinatra/docker-compose.dev.yml

[error] 35-35: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/continuous_deployment.yml

[error] 27-27: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 33-33: trailing spaces

(trailing-spaces)

.github/workflows/continuous_delivery.yml

[error] 21-21: trailing spaces

(trailing-spaces)

🪛 RuboCop (1.73)
sinatra/helpers/application_helpers.rb

[convention] 78-105: Assignment Branch Condition size for cached_forecast is too high. [<5, 24, 6> 25.24/23]

(Metrics/AbcSize)

🪛 actionlint (1.7.4)
.github/workflows/continuous_deployment.yml

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: e2e
🔇 Additional comments (22)
sinatra/tests/.gitignore (1)

1-5: E2E test artifacts correctly ignored.

The new ignore rules for Playwright outputs and dependencies (node_modules/, /test‑results/, /playwright-report/, /blob-report/, /playwright/.cache/) are comprehensive and align with the new E2E test setup.

sinatra/docker-entrypoint.sh (1)

9-10: Ensure log directory exists with correct ownership.

Adding mkdir -p /app/log and recursively chown-ing to appuser:appuser aligns the entrypoint with the new sinatra_logs volume. This guarantees the container can drop privileges safely while preserving write access to logs.

sinatra/helpers/application_helpers.rb (1)

78-78: Approve method rename to cached_forecast.

The helper has been renamed consistently across routes and tests, and its behavior remains unchanged.

🧰 Tools
🪛 RuboCop (1.73)

[convention] 78-105: Assignment Branch Condition size for cached_forecast is too high. [<5, 24, 6> 25.24/23]

(Metrics/AbcSize)

sinatra/routes/pages.rb (1)

53-53: Method rename looks good.

The change from get_cached_forecast to cached_forecast is consistent with Ruby's naming conventions, which typically omit the "get_" prefix for accessor methods. This makes the code more idiomatic.

sinatra/routes/api.rb (1)

45-45: Method rename looks good.

The change from get_cached_forecast to cached_forecast is consistent with Ruby's naming conventions and matches the same change made in other files. This ensures consistency throughout the codebase.

.github/workflows/continuous_delivery.yml (1)

4-5: Branch trigger restriction looks good.

Restricting the workflow to only run on "main" and "dev" branches is a good practice. It helps control when Docker images are built and pushed, avoiding unnecessary builds for feature branches.

sinatra/docker-compose.prod.yml (1)

8-8: Good addition of persistent logging in production

Adding a persistent volume for logs is an excellent practice for production environments. This ensures log data survives container restarts, making troubleshooting much easier.

Also applies to: 37-37

sinatra/app.rb (2)

25-26: Good refactoring of session secret configuration

Separating the default secret generation into a variable improves readability while maintaining the same secure functionality with the random hex suffix.


71-72: Better comment placement

Moving the comment about log rotation directly above the logger instantiation improves documentation clarity.

sinatra/benchmark_search.rb (1)

46-48: Improved SQL query readability

Breaking the long SQL query into multiple lines with proper backslash continuation improves readability while maintaining the same functionality. Each SQL clause is now visually distinct, making the query easier to understand and maintain.

sinatra/tests/e2e/login.spec.js (1)

1-32: Well-structured Playwright test suite for login functionality

The test suite is well-organized with appropriate setup and covers essential test cases: form rendering, error handling for invalid credentials, and successful login flow. Good use of test hooks and Playwright selectors.

sinatra/tests/e2e/search.spec.js (2)

8-11: Good use of constants for test data

Using constants for search terms improves maintainability and makes the test intent clear.


15-31: The valid search test looks good

This test appropriately checks that the search URL updates and verifies that results contain the search term.

sinatra/tests/e2e/register.spec.js (1)

32-42: Good approach for creating unique test users

Using a timestamp to generate unique usernames and emails is an excellent strategy to prevent test conflicts from repeated runs.

.github/workflows/continuous_deployment.yml (1)

1-35:

Details

✅ Verification successful

Consider adding database migrations or setup steps

The workflow doesn't include any steps for database migrations or other setup that might be needed when deploying new versions.

If your application requires database migrations, consider adding steps to the SSH commands:


🏁 Script executed:

#!/bin/bash
# Check if there are any migration files in the repository
find . -path "*/db/migrate/*.rb" | wc -l

Length of output: 44


🏁 Script executed:

#!/bin/bash
echo "Checking for Ruby on Rails migrations (db/migrate):"
find . -path '*/db/migrate/*.rb'
echo "Checking for generic migrations directory:"
find . -type d -iname 'migrations'
echo "Checking for SQL migration files:"
find . -path '*/migrations/*.sql'
echo "Checking for Alembic migrations (Python):"
find . -path '*/alembic/versions/*.py'
echo "Searching for 'migrat' keyword in docker-compose.dev.yml:"
grep -Rin 'migrat' docker-compose.dev.yml || true

Length of output: 760


No database migrations detected—no deployment changes needed
The repository contains no migration files or directories (e.g., db/migrate, migrations/, Alembic, SQL scripts), so adding migration steps to this workflow isn’t necessary. If you introduce database migrations in the future, remember to include a migration step (for example, running rails db:migrate, alembic upgrade head, or your custom migration command) in the SSH deploy block.

🧰 Tools
🪛 actionlint (1.7.4)

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)

[error] 27-27: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 33-33: trailing spaces

(trailing-spaces)

sinatra/tests/e2e/weather.spec.js (1)

1-42: Well-structured test suite with good coverage for the weather feature!

The test suite appropriately verifies both the API endpoint and UI rendering, handling both success and error scenarios. The assertions are comprehensive and validate the expected structure of responses and UI elements.

.github/workflows/playwright.yml (1)

1-87: Well-structured CI workflow for Playwright tests

The workflow is properly configured to set up the necessary dependencies, prepare the test database, run the tests, and upload the test reports. The use of environment variables for API keys and the conditional logic for CI environments are well implemented.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 37-37: trailing spaces

(trailing-spaces)

sinatra/docker-compose.dev.yml (3)

3-9: Good use of prebuilt image and persistent volumes

Using a prebuilt image with environment variables from a .env file improves reproducibility and simplifies development setup. The persistent volumes for data and logs are a good practice.


11-22: Well-configured Nginx service with SSL support

The Nginx configuration with port mapping and volume mounts for SSL certificates is well structured. The dependency on the app service ensures proper startup order.


24-29: Good implementation of automatic SSL certificate renewal

The certbot service is configured to automatically renew SSL certificates every 12 hours, which is a good practice for maintaining valid SSL certificates.

sinatra/tests/playwright.config.js (1)

1-39: Well-structured Playwright configuration

The configuration properly sets up the test environment with appropriate settings for different environments (CI vs local), configures the web server for testing, and supports cross-browser testing.

.github/workflows/ci.yaml (1)

81-89: Lint Dockerfiles step is well configured.

The use of hadolint/hadolint-action@v3.1.0 for both Dockerfile.dev and Dockerfile.prod is correct and pins the action version. No issues detected.

Comment thread sinatra/schema_test.sql
Comment on lines +10 to +12
-- Create a default user, The password is 'password' (MD5 hashed)
INSERT INTO users (username, email, password)
VALUES ('test', 'keamonk1@stud.kea.dk', '123');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix inconsistency between comment and implementation for password hashing.

The comment states that the password is 'password' (MD5 hashed), but the actual inserted value '123' is not hashed. This is a security concern even in test environments.

Suggested improvement:

- -- Create a default user, The password is 'password' (MD5 hashed)
- INSERT INTO users (username, email, password) 
-     VALUES ('test', 'keamonk1@stud.kea.dk', '123');
+ -- Create a default user with hashed password (using a secure algorithm)
+ INSERT INTO users (username, email, password) 
+     VALUES ('test', 'test@example.com', '$2a$12$K3JNi5hYfLdnIF9Pb4bg3u3Z6L2UGjTsUqpX5.OMZGGgHMnB9YZpe');

Note: The suggested hash is a bcrypt hash of '123'. Consider using a secure algorithm like bcrypt, Argon2, or PBKDF2 instead of MD5 which is no longer considered secure for password storage.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
-- Create a default user, The password is 'password' (MD5 hashed)
INSERT INTO users (username, email, password)
VALUES ('test', 'keamonk1@stud.kea.dk', '123');
-- Create a default user with hashed password (using a secure algorithm)
INSERT INTO users (username, email, password)
VALUES ('test', 'test@example.com', '$2a$12$K3JNi5hYfLdnIF9Pb4bg3u3Z6L2UGjTsUqpX5.OMZGGgHMnB9YZpe');

if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout code
uses: actions/checkout@v3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update the checkout action version

The version of actions/checkout is outdated. Update to the latest version for improved functionality and security.

- uses: actions/checkout@v3
+ uses: actions/checkout@v4
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uses: actions/checkout@v3
uses: actions/checkout@v4
🧰 Tools
🪛 actionlint (1.7.4)

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx

ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid exposing GitHub token in command output

Using echo ${{ secrets.GITHUB_TOKEN }} can expose the token in logs. Use input redirection instead.

- echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
+ docker login ghcr.io -u ${{ github.actor }} --password-stdin <<< "${{ secrets.GITHUB_TOKEN }}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker login ghcr.io -u ${{ github.actor }} --password-stdin <<< "${{ secrets.GITHUB_TOKEN }}"

Comment on lines +25 to +26
scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Security concern: SSH strict host key checking is disabled

Disabling StrictHostKeyChecking makes the deployment vulnerable to man-in-the-middle attacks. Consider alternatives:

  1. Add the VM's host key to known_hosts before connecting:
- scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
+ mkdir -p ~/.ssh
+ echo "${{ secrets.AZURE_VM_HOST_KEY }}" >> ~/.ssh/known_hosts
+ scp docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
  1. Or use GitHub Actions' knownhosts input:
  uses: webfactory/ssh-agent@v0.7.0
  with:
    ssh-private-key: ${{ secrets.AZURE_VM_SSH_KEY }}
+   known-hosts: ${{ secrets.AZURE_VM_HOST_KEY }}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +24 to +35
run: | # Copy the docker-compose file and any other necessary files
scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx

ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin

docker-compose pull
docker-compose up -d

docker image prune -f
EOF
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and deployment verification

The deployment steps don't include any error handling or verification that the deployment was successful.

  run: | # Copy the docker-compose file and any other necessary files
    scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
    scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx
    
    ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
      echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
      
      docker-compose pull
      docker-compose up -d
      
      docker image prune -f
+     
+     # Verify deployment
+     echo "Verifying deployment..."
+     timeout=60
+     while [ $timeout -gt 0 ]; do
+       if curl -s http://localhost:80 | grep -q "Success"; then
+         echo "Deployment verified successfully!"
+         exit 0
+       fi
+       sleep 5
+       timeout=$((timeout-5))
+     done
+     echo "Deployment verification failed!"
+     docker-compose logs
+     exit 1
    EOF
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: | # Copy the docker-compose file and any other necessary files
scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx
ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker-compose pull
docker-compose up -d
docker image prune -f
EOF
run: | # Copy the docker-compose file and any other necessary files
scp -o StrictHostKeyChecking=no docker-compose.dev.yml ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/docker-compose.yml
scp -o StrictHostKeyChecking=no -r nginx ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }}:~/nginx
ssh -o StrictHostKeyChecking=no ${{ secrets.AZURE_VM_USER }}@${{ secrets.AZURE_VM_IP }} << 'EOF'
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker-compose pull
docker-compose up -d
docker image prune -f
# Verify deployment
echo "Verifying deployment..."
timeout=60
while [ $timeout -gt 0 ]; do
if curl -s http://localhost:80 | grep -q "Success"; then
echo "Deployment verified successfully!"
exit 0
fi
sleep 5
timeout=$((timeout-5))
done
echo "Deployment verification failed!"
docker-compose logs
exit 1
EOF
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 27-27: trailing spaces

(trailing-spaces)


[error] 30-30: trailing spaces

(trailing-spaces)


[error] 33-33: trailing spaces

(trailing-spaces)

Comment thread .github/workflows/ci.yaml
Comment on lines 65 to 72
- name: Auto-correct RuboCop issues
working-directory: sinatra
run: bundle exec rubocop -A || true # Ensure CI doesn't fail on auto-fixes
run: bundle exec rubocop -A || true

- name: Run RuboCop (Code Linter)
- name: Run RuboCop
working-directory: sinatra
run: bundle exec rubocop || true # Allow non-critical failures

- name: Install Hadolint
run: |
wget -O hadolint "https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64"
chmod +x hadolint
sudo mv hadolint /usr/local/bin/hadolint
run: bundle exec rubocop || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enforce RuboCop failures on violations.

The use of || true on RuboCop steps masks lint errors. Remove || true so that violations cause the job to fail and enforce code style.

- run: bundle exec rubocop -A || true
+ run: bundle exec rubocop -A

- run: bundle exec rubocop || true
+ run: bundle exec rubocop
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Auto-correct RuboCop issues
working-directory: sinatra
run: bundle exec rubocop -A || true # Ensure CI doesn't fail on auto-fixes
run: bundle exec rubocop -A || true
- name: Run RuboCop (Code Linter)
- name: Run RuboCop
working-directory: sinatra
run: bundle exec rubocop || true # Allow non-critical failures
- name: Install Hadolint
run: |
wget -O hadolint "https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64"
chmod +x hadolint
sudo mv hadolint /usr/local/bin/hadolint
run: bundle exec rubocop || true
- name: Auto-correct RuboCop issues
working-directory: sinatra
- run: bundle exec rubocop -A || true
+ run: bundle exec rubocop -A
- name: Run RuboCop
working-directory: sinatra
- run: bundle exec rubocop || true
+ run: bundle exec rubocop

Comment thread .github/workflows/ci.yaml
Comment on lines +54 to +59
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.4.2
bundler-cache: true
# working-directory: ./sinatra # Add if Gemfile.lock is in ./sinatra
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix bundler-cache detection in the Lint Ruby job.

The RuboCop job’s Set up Ruby step needs the working-directory: sinatra so bundler-cache can find the Gemfile.lock. Otherwise caching won’t work as expected.

-      - name: Set up Ruby
-        uses: ruby/setup-ruby@v1
-        with:
-          ruby-version: 3.4.2
-          bundler-cache: true
+      - name: Set up Ruby
+        uses: ruby/setup-ruby@v1
+        with:
+          ruby-version: 3.4.2
+          bundler-cache: true
+        working-directory: sinatra

@theaskou theaskou reopened this Apr 18, 2025
@theaskou theaskou closed this Apr 18, 2025
@Aleksandergreg Aleksandergreg deleted the feature/CD branch April 29, 2025 06:24
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