diff --git a/.github/workflows/ci-with-codeql.yml b/.github/workflows/ci-with-codeql.yml index 72474cb..e49270f 100644 --- a/.github/workflows/ci-with-codeql.yml +++ b/.github/workflows/ci-with-codeql.yml @@ -32,6 +32,7 @@ jobs: uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} + queries: +security-extended - name: Set up JDK 11 uses: actions/setup-java@v4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b98da6d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Eficode + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 12e56bc..f00395b 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,66 @@ The project includes unit and integration tests. mvn verify ``` +## Linting and Code Style + +This project uses [Checkstyle](https://checkstyle.org/) to enforce consistent code style and formatting. + +* **Configuration:** The Checkstyle rules are defined in `checkstyle.xml` at the root of the repository. +* **Key rules enforced:** + - Maximum line length: 120 characters + - Indentation: 4 spaces (no tabs) + - Braces required for all control structures + - Javadoc required for classes and methods + - Naming conventions for variables, methods, constants, and packages +* **How to run Checkstyle:** + 1. Make sure you are in the project root directory. + 2. Run the following Maven command: + ```bash + mvn checkstyle:check + ``` + 3. The build will fail if there are any style violations. To see a detailed report, run: + ```bash + mvn checkstyle:checkstyle + open target/site/checkstyle.html + ``` + 4. Fix any reported issues before submitting code or opening a pull request. + +## Continuous Integration / Continuous Delivery (CI/CD) + +Automated tests and code style checks are run in CI/CD pipelines to ensure code quality and reliability. A typical pipeline for this project includes: + +1. **Build:** + - Compile the code using Maven. +2. **Lint:** + - Run Checkstyle to enforce code style (`mvn checkstyle:check`). +3. **Test:** + - Run all unit and integration tests (`mvn verify`). + +If you use GitHub Actions, GitLab CI, Jenkins, or another CI/CD tool, ensure your pipeline includes these steps. Example GitHub Actions workflow snippet: + +```yaml +name: Java CI +on: [push, pull_request] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Build with Maven + run: mvn clean package + - name: Run Checkstyle + run: mvn checkstyle:check + - name: Run Tests + run: mvn verify +``` + +> **Note:** Update the workflow as needed for your CI/CD environment. Always ensure that code style and tests pass before merging changes. + ## Project Structure The project follows standard Maven directory layout: diff --git a/src/main/java/com/weather/app/WeatherApp.java b/src/main/java/com/weather/app/WeatherApp.java index ef7542d..3cb8a8d 100644 --- a/src/main/java/com/weather/app/WeatherApp.java +++ b/src/main/java/com/weather/app/WeatherApp.java @@ -10,9 +10,9 @@ * Main entry point for the Weather Application */ public class WeatherApp { - + private static final Logger LOGGER = Logger.getLogger(WeatherApp.class.getName()); - + // Initialize logging configuration static { try (InputStream is = WeatherApp.class.getClassLoader().getResourceAsStream("logging.properties")) { @@ -27,23 +27,23 @@ public class WeatherApp { e.printStackTrace(); } } - + // Flag to control System.exit behavior (for testing) private static boolean exitOnError = true; /** * Set whether the application should exit on error. * This method is primarily used for testing. - * + * * @param shouldExit true if the application should exit on error, false otherwise */ public static void setExitOnError(boolean shouldExit) { exitOnError = shouldExit; } - + /** * Exit the application with the given status code if exitOnError is true. - * + * * @param status the exit status code * @return true if the application would exit (for testing) */ @@ -63,8 +63,6 @@ public static void main(String[] args) { return; } - - // Get the city name from command line arguments String city = args[0]; LOGGER.log(Level.INFO, "Weather request for city: {0}", city); @@ -72,7 +70,7 @@ public static void main(String[] args) { try { // Get API key from environment or config file String apiKey = ConfigUtil.getApiKey(); - + // Initialize services WeatherApiClient weatherApiClient = new OpenWeatherMapClient(apiKey); WeatherService weatherService = new WeatherService(weatherApiClient); @@ -80,12 +78,12 @@ public static void main(String[] args) { // Get and display weather data WeatherData weatherData = weatherService.getWeather(city); LOGGER.log(Level.FINE, weatherData.toString()); - + // Display weather data to the user System.out.println("Current Weather for " + city + ":"); System.out.println("-------------------------------------"); System.out.println(weatherData); - + } catch (ConfigUtil.ConfigException e) { LOGGER.log(Level.SEVERE, "Configuration error: " + e.getMessage(), e); LOGGER.log(Level.SEVERE, diff --git a/src/test/java/com/weather/app/ConfigUtilTest.java b/src/test/java/com/weather/app/ConfigUtilTest.java index b2f5dc0..712f766 100644 --- a/src/test/java/com/weather/app/ConfigUtilTest.java +++ b/src/test/java/com/weather/app/ConfigUtilTest.java @@ -1,4 +1,4 @@ -package test.java.com.weather.app; +package com.weather.app; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/com/weather/app/OpenWeatherMapClientTest.java b/src/test/java/com/weather/app/OpenWeatherMapClientTest.java index fac0eae..4186415 100644 --- a/src/test/java/com/weather/app/OpenWeatherMapClientTest.java +++ b/src/test/java/com/weather/app/OpenWeatherMapClientTest.java @@ -1,4 +1,4 @@ -package test.java.com.weather.app; +package com.weather.app; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/weather/app/WeatherAppTest.java b/src/test/java/com/weather/app/WeatherAppTest.java index 5eb7b62..29d8a8b 100644 --- a/src/test/java/com/weather/app/WeatherAppTest.java +++ b/src/test/java/com/weather/app/WeatherAppTest.java @@ -1,4 +1,4 @@ -package test.java.com.weather.app; +package com.weather.app; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/com/weather/app/WeatherAppTestSuite.java b/src/test/java/com/weather/app/WeatherAppTestSuite.java index f35b79a..1912b80 100644 --- a/src/test/java/com/weather/app/WeatherAppTestSuite.java +++ b/src/test/java/com/weather/app/WeatherAppTestSuite.java @@ -1,4 +1,4 @@ -package test.java.com.weather.app; +package com.weather.app; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; diff --git a/src/test/java/com/weather/app/WeatherServiceTest.java b/src/test/java/com/weather/app/WeatherServiceTest.java index 9397ed1..eff7c22 100644 --- a/src/test/java/com/weather/app/WeatherServiceTest.java +++ b/src/test/java/com/weather/app/WeatherServiceTest.java @@ -1,4 +1,4 @@ -package test.java.com.weather.app; +package com.weather.app; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach;