{"id":21958950,"url":"https://github.com/bitcoder/tutorial-spring","last_synced_at":"2026-04-18T17:34:31.559Z","repository":{"id":231741249,"uuid":"782052409","full_name":"bitcoder/tutorial-spring","owner":"bitcoder","description":"A Spring Boot basic tutorial","archived":false,"fork":false,"pushed_at":"2026-04-17T15:23:06.000Z","size":222,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-17T16:14:31.784Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitcoder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-04-04T14:47:04.000Z","updated_at":"2026-04-17T14:09:22.000Z","dependencies_parsed_at":"2025-03-22T19:45:11.022Z","dependency_job_id":"9040e323-e7b0-4559-a15e-70d41a9ffa9a","html_url":"https://github.com/bitcoder/tutorial-spring","commit_stats":null,"previous_names":["bitcoder/tutorial-spring"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bitcoder/tutorial-spring","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoder%2Ftutorial-spring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoder%2Ftutorial-spring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoder%2Ftutorial-spring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoder%2Ftutorial-spring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitcoder","download_url":"https://codeload.github.com/bitcoder/tutorial-spring/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoder%2Ftutorial-spring/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31978159,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T17:30:12.329Z","status":"ssl_error","status_checked_at":"2026-04-18T17:29:59.069Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T09:17:58.470Z","updated_at":"2026-04-18T17:34:31.546Z","avatar_url":"https://github.com/bitcoder.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring tutorial\n\n[![build workflow](https://github.com/bitcoder/tutorial-spring/actions/workflows/maven.yml/badge.svg)](https://github.com/bitcoder/tutorial-spring/actions/workflows/maven.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=bitcoder_tutorial-spring\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=bitcoder_tutorial-spring)\n[![Jira](https://img.shields.io/badge/jira-%230A0FFF.svg?style=for-the-badge\u0026logo=jira\u0026logoColor=white)](https://sergiofreire.atlassian.net/browse/ST)\n[![Xray](https://byob.yarr.is/bitcoder/tutorial-spring/xray)](https://sergiofreire.atlassian.net/plugins/servlet/ac/com.xpandit.plugins.xray/test-coverage-report-page?project.key=ST\u0026project.id=10007)\n\n\nThis is a simple Spring Boot tutorial to showcase the CI flow:\n\n- make local changes \u0026 push them\n- CI tool runs build\n- CI tool runs tests\n- merge\n\nThis tutorial also pushes the results to Jira; the results are visible and its impacts can be tracked in Jira using a test management tool called Xray; this integration is optional but is shown as an example of how CI related results can be tracked elsewhere, including in the popular Jira issue tracker.\n\n## Testing\n\nThis project contains unit and integration tests. \nUnit tests are run using `surefire`, while integration tests can be run using `failsafe` maven plugin.\n\n\n```bash\nmvn test\n```\n\n```bash\nmvn integration-test\n```\n\nIf we want to fail the build whenever running the IT, we can execute the maven target `failsafe:verify` or just `verify` after running the IT.\n\n```bash\nmvn integration-test verify\n```\n\n## CI and CD\n\nCI is implemented using GH actions, on a [workflow](https://github.com/bitcoder/tutorial-spring/blob/main/.github/workflows/maven.yml) that is triggered:\n\n- on the main branch\n- on PRs (pull-requests)\n\nWe can also trigger the workflow/build on demand, right from the [Actions page](https://github.com/bitcoder/tutorial-spring/actions/workflows/maven.yml).\n\nCommits on `main` branch will deploy to production.\n\n## SonarCloud\n\nThis project is integrated with [SonarCloud](https://sonarcloud.io/project/overview?id=bitcoder_tutorial-spring), and PRs will have information about code quality.\n\n## Environments\n\nThe Spring Boot app is deployed to:\n- *production*, upon a commit on the `main` branch\n- *staging*, upon a PR (Pull Request); this is only showcased on the `lh_tests_on_staging` branch and corresponding PR as an example; this hasn't been merged just for demo purpose and also because it would make the PR demo a bit slower to show.\n\nWe're using Render.com to host the app; upon a trigger, Render will start a build (based on a Dockerfile) and deploy the app.\n\n- The production site is available at: https://tutorial-spring.onrender.com\n- The staging site is available at: https://tutorial-spring-staging.onrender.com\n\n## Jira (using Xray Test Management)\n\nThe testing results are pushed to [Xray](https://www.getxray.app/), a test management tool, in Jira; only the integration tests are pushed.\n\n- test automation results will be tracked on a Test Plan issue\n- automated test entities will be provisioned on Jira/Xray, if they don't exist yet\n- (some) automated test are linked automatically to existing stories, if they're annotated with `@Requirement(\u003cstory_issue_key\u003e)` ([example](https://github.com/bitcoder/tutorial-spring/blob/2f0f43779c5f207409600997eb1d1320413e76b3/src/test/java/com/sergiofreire/xray/tutorials/springboot/IndexControllerMockedIT.java#L29)); that requires using the [xray-junit-extensions](https://github.com/Xray-App/xray-junit-extensions) dependency\n\nTo push the results to Jira, a maven plugin [xray-maven-plugin](https://github.com/Xray-App/xray-maven-plugin) is used; an alternative to that would be to use the GH action [xray-action](https://github.com/mikepenz/xray-action) instead. You choose :)\n\n## Contact\n\nIf you're having the TQS classes, you can reach out using my email account at sergio dot freire (you know the rest).\n\nAny questions related with this code, please raise issues in this GitHub project. Feel free to contribute and submit PR's\nYou may also find me on [X](https://x.com/darktelecom), where I write once in a while about testing (don't use that for TQS class related topics though).\n \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitcoder%2Ftutorial-spring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitcoder%2Ftutorial-spring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitcoder%2Ftutorial-spring/lists"}