{"id":25436651,"url":"https://github.com/kfischer-okarin/cd-atdd-task-bounty-example","last_synced_at":"2026-04-25T21:32:37.736Z","repository":{"id":275305609,"uuid":"925702521","full_name":"kfischer-okarin/cd-atdd-task-bounty-example","owner":"kfischer-okarin","description":"Deployment Pipeline \u0026 Acceptance Test example in Ruby on Rails","archived":false,"fork":false,"pushed_at":"2025-05-14T21:55:55.000Z","size":157,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-15T03:11:22.256Z","etag":null,"topics":["acceptance-testing","attd","continuous-delivery","deployment-pipeline","rails"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kfischer-okarin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2025-02-01T14:36:38.000Z","updated_at":"2025-02-16T16:56:31.000Z","dependencies_parsed_at":"2025-02-01T15:35:09.250Z","dependency_job_id":"aef6b1a6-7e54-48ff-96df-9daa8b562720","html_url":"https://github.com/kfischer-okarin/cd-atdd-task-bounty-example","commit_stats":null,"previous_names":["kfischer-okarin/cd-atdd-task-bounty-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kfischer-okarin/cd-atdd-task-bounty-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfischer-okarin%2Fcd-atdd-task-bounty-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfischer-okarin%2Fcd-atdd-task-bounty-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfischer-okarin%2Fcd-atdd-task-bounty-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfischer-okarin%2Fcd-atdd-task-bounty-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kfischer-okarin","download_url":"https://codeload.github.com/kfischer-okarin/cd-atdd-task-bounty-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfischer-okarin%2Fcd-atdd-task-bounty-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32278249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"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":["acceptance-testing","attd","continuous-delivery","deployment-pipeline","rails"],"created_at":"2025-02-17T08:21:21.195Z","updated_at":"2026-04-25T21:32:37.720Z","avatar_url":"https://github.com/kfischer-okarin.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Continuous Delivery Rails Example\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n\nThis repository demonstrates a possible implementation of a simple Deployment\nPipeline (as proposed by Dave Farley) in a Rails project implemented using\nGitHub Actions.\n\n\u003e [!CAUTION]\n\u003e This example is not fit for production use as-is.\n\u003e Check the [Things out of Scope](#things-out-of-scope) section for details.\n\n## Table of Contents\n- [Implemented Techniques](#implemented-techniques)\n  - [Deployment Pipeline](#deployment-pipeline)\n    - [1. Commit Stage](#1-commit-stage)\n    - [2. Create Artifact](#2-create-artifact)\n    - [3. Acceptance Stage](#3-acceptance-stage)\n  - [4 Layer Acceptance Test Architecture](#4-layer-acceptance-test-architecture)\n    - [1. Test Cases](#1-test-cases)\n    - [2. DSL (Domain-Specific Language)](#2-dsl-domain-specific-language)\n    - [3. Protocol Driver](#3-protocol-driver)\n    - [4. System Under Test](#4-system-under-test)\n- [References for further Study](#references-for-further-study)\n- [Things out of Scope](#things-out-of-scope)\n\n## Implemented Techniques\n### Deployment Pipeline\nThe deployment pipeline consists of three main stages:\n\n#### 1. Commit Stage\nThis stage runs on every pull request and push. It includes jobs for scanning\nRuby and JavaScript code for security vulnerabilities, linting the code for\nconsistent style, and running unit tests.\n\n**Implementation:** [`.github/workflows/commit-stage.yml`](.github/workflows/commit-stage.yml)\n\n#### 2. Create Artifact\nThis stage runs after the successful completion of the Commit Stage on the `main`\nbranch. It builds a Docker image as artifact, tags it with the current commit\nSHA and pushes it to Docker Hub.\n\n**Implementation:** [`.github/workflows/create-artifact.yml`](.github/workflows/create-artifact.yml)\n\n#### 3. Acceptance Stage\nThis stage runs after the successful completion of the Create Artifact stage. It\nstarts a Docker container from the built image and runs acceptance tests against\nit.\n\n**Implementation:** [`.github/workflows/acceptance-stage.yml`](.github/workflows/acceptance-stage.yml)\n\n\n### 4 Layer Acceptance Test Architecture\nThe acceptance tests are written using the 4 Layer Acceptance Test\nArchitecture (also proposed by Dave Farley).\n\n#### 1. Test Cases\nThis layer contains the actual test cases that define the acceptance criteria.\nThe test cases are written solely using the DSL layer.\n\n**Implementation:** [`test/system/`](test/system/) directory\n\n#### 2. DSL (Domain-Specific Language)\nThis layer provides a high-level language to describe actions and assertions\nfrom a business perspective, typically from the point of view of an end user.\nIt is recommended to avoid mentioning technical details or UI elements,\nfocusing instead on *what* is happening or being done in business domain terms.\n\nResponsibilities of the DSL layer include:\n- Providing an easy-to-use and readable API for authoring test cases.\n- Offering sensible default parameter values, allowing test cases to be written\n  without specifying details irrelevant to the scenario.\n- Mapping identifiers to unique aliases before passing them to the driver or\n  performing assertions. This enables test cases to execute in parallel\n  against the same environment without interfering with each other.\n\n**Implementation:** [`test/support/acceptance_test_dsl.rb`](test/support/acceptance_test_dsl.rb) included inside [`test/application_system_test_case.rb`](test/application_system_test_case.rb)\n\n#### 3. Protocol Driver\nThis layer interacts with the system under test using a specific protocol\n(commonly through the UI or a web API). It translates high-level commands from\nthe DSL into low-level operations, handling *how* business actions are executed\nwithin your system.\n\nIf your system offers multiple methods of interaction, you would implement a\nseparate driver for each one, ensuring that the DSL remains agnostic to the\nunderlying protocol.\n\n**Implementation:** [`test/support/capybara_acceptance_test_driver.rb`](test/support/capybara_acceptance_test_driver.rb)\n\n#### 4. System Under Test\nThis is the actual application or system being tested. When executing\nacceptance tests, it is crucial to have an environment that closely mirrors a\nreal production environment to accurately assess whether the application\ncurrently fulfills all its business requirements.\n\nAt the same time, it is equally important to control external variables, such\nas system time or responses from external systems that are beyond your control,\nto ensure deterministic test results. Controlling time, for example, is\nessential for testing time-dependent functionality, as such tests would be\nimpossible to conduct reliably otherwise.\n\nTo achieve this, the system must be designed to allow the injection and\nreplacement of such dependencies through configuration, enabling seamless\nsubstitution of such external factors.\n\n\n## References for further Study\n- [Acceptance Testing Webinar (YouTube)](https://www.youtube.com/watch?v=SuDIYk9GBpE)\n- [Continuous Delivery Webinar (YouTube)](https://www.youtube.com/watch?v=ONnwToAH4bU)\n\n\n## Things out of Scope\nFollowing things are whole sub-areas which would have added a lot of incidental\ncomplexity to this sample and have been left out and/or simplified on purpose.\n\n### Deployment\nCurrently, \"deploying the application\" means just starting a local Docker\ncontainer (see\n[`./bin/deploy-to-acceptance-test-environment`](bin/deploy-to-acceptance-test-environment)\nused in the acceptance stage for details).\n\nI also removed the default Kamal settings generated by Rails from this project\nto not give the impression that this project could be deployed anywhere as it\nis.\n\nSince the Application is not actually deployable - the deployment pipeline just\nfinishes after the acceptance stage and does not push the changes to the\nproduction environment as would be common with a real Continuous Delivery\nworkflow.\n\n### SSL\nI added support for a environment variable to completely disable SSL in\nproduction and enabled it in the acceptance stage.\n\n### User Management \u0026 Authentication\nThe application itself has a concept of users but for simplicity's sake there\nis neither user management (new users are added via a public `/users/new` page)\nnor any kind of authentication (users just login via their user name).\n\n### Beautiful Page Design :wink:\nThis app's page design is powered by ChatGPT and the [Bulma](https://bulma.io/)\nCSS framework.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkfischer-okarin%2Fcd-atdd-task-bounty-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkfischer-okarin%2Fcd-atdd-task-bounty-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkfischer-okarin%2Fcd-atdd-task-bounty-example/lists"}