Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-for-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
restore-keys: |
${{ runner.os }}-maven-
- name: Build with Maven
run: mvn clean verify -ntp
run: mvn clean verify -ntp
18 changes: 9 additions & 9 deletions .github/workflows/ci-from-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
branches:
- main
paths:
- '{{cookiecutter.app_name}}/**'
- '{{app_name}}/**'
workflow_dispatch:
jobs:
generate-from-template:
Expand All @@ -20,14 +20,14 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install cookiecutter
- name: Install copier
run: |
pip install --upgrade pip cookiecutter
- name: Generate from default context (cookiecutter.json)
pip install --upgrade pip copier
- name: Generate from default context (copier)
run: |
# Generate using the config file test-config.yml from the repo root.
# Use the repo root as the template directory (.) and overwrite any existing generated output.
cookiecutter --no-input --config-file test-config.yml --overwrite-if-exists --output-dir . .
# Use the repo root as the template directory and generate into ./cart-service
# Use copier.yml as the default data file with --defaults and --force to overwrite any existing generated output.
copier copy . . --defaults --force
- name: Upload generated cart-service as artifact
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -59,5 +59,5 @@ jobs:
restore-keys: |
${{ runner.os }}-maven-
- name: Build with Maven
run: git init && mvn clean verify -Dgit-code-format.skip=true -DargLine="--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" -ntp
working-directory: ./cart-service
run: git init && mvn clean verify -ntp
working-directory: ./cart-service
2 changes: 1 addition & 1 deletion .github/workflows/generate-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:

- name: Copy generated template to {{cookiecutter.app_name}}
run: |
rsync -a --delete --exclude='.git' ./example-template/ ./{{cookiecutter.app_name}}/
rsync -a --delete --exclude='.git' ./example-template/ ./{{app_name}}/

- name: Commit and push changes
id: commit
Expand Down
55 changes: 35 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Template project for hexagonal-spring-boot-java
# Template project for hexagonal-spring-boot-java [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/copier-org/copier)

This is a template project for hexagonal-spring-boot-java. This project is generated using [cookiecutter](https://cookiecutter.readthedocs.io/en).
This is a template project for hexagonal-spring-boot-java. This project is generated using [copier](https://copier.readthedocs.io/en/stable/) .

## Pre-requisites

- [cookiecutter](https://cookiecutter.readthedocs.io/en/stable/README.html#installation)
- [copier](https://copier.readthedocs.io/en/stable/#installation)
- Jdk 21
- Maven >3.9.5

Expand All @@ -22,26 +22,41 @@ flowchart LR

### example

This directory contains the maven hexagonal-spring-boot-java template project. This will be used to generate template project for cookiecutter. This project is used for the contributors to make their changes and test it locally.
This directory contains the maven hexagonal-spring-boot-java template project. This will be used to generate template project for copier. This project is used for the contributors to make their changes and test it locally.

Following are the keywords reserved for the template project and their equivalent replacements in {{cookiecutter.app_name}} project:
Following are the keywords reserved for the template project and their equivalent replacements in {{app_name}} project:

| Keyword | Replacement |
|--------------|---------------------------------------------|
| Examples | {{cookiecutter.domain_plural_capitalized}} |
| examples | {{cookiecutter.domain_plural}} |
| Example | {{cookiecutter.domain_capitalized}} |
| example | {{cookiecutter.domain}} |
| packagename | {{cookiecutter.package_name}} |
| artifactName | {{cookiecutter.artifact_id}} |
| group-id | {{cookiecutter.group_id}} |
| EXAMPLES | {{cookiecutter.domain_plural_uppercase}} |
| EXAMPLE | {{cookiecutter.domain_uppercase}} |
| Keyword | Replacement |
|--------------|-------------------------------|
| Examples | {{domain_plural_capitalized}} |
| examples | {{domain_plural}} |
| Example | {{domain_capitalized}} |
| example | {{domain}} |
| packagename | {{package_name}} |
| artifactName | {{artifact_id}} |
| group-id | {{group_id}} |
| EXAMPLES | {{domain_plural_uppercase}} |
| EXAMPLE | {{domain_uppercase}} |

Refer script [generate-cookiecutter-template-from-example-project.sh](generate-cookiecutter-template-from-example-project.sh) which is used to generate the cookiecutter template project. This script is also being used by [`.github/workflows/ci.yaml`](.github/workflows/ci.yaml) pipeline too.
Refer script [generate-copier-template-from-example-project.sh](generate-copier-template-from-example-project.sh) which is used to generate the copier template project. This script is also being used by [generate-template.yaml](.github/workflows/generate-template.yaml) pipeline too.

### {{cookiecutter.app_name}}
### {{app_name}}

> NOTE: DO NOT MODIFY THIS DIRECTORY DIRECTLY
> [!WARNING]
> DO NOT MODIFY THIS DIRECTORY DIRECTLY

This directory contains the generated project from `example` project. The project is generated using the script [generate-cookiecutter-template-from-example-project.sh](generate-cookiecutter-template-from-example-project.sh) which is used to generate the cookiecutter template project.
This directory contains the generated project from `example` project. The project is generated using the script [generate-copier-template-from-example-project.sh](generate-copier-template-from-example-project.sh) which is used to generate the cookiecutter template project.

## Generating a new project

The following command can be used to generate a new project using this template:

```bash
copier copy . <destination_folder>
```

Command to generate with default values without prompt:

```bash
copier copy . . --defaults
```
14 changes: 0 additions & 14 deletions cookiecutter.json

This file was deleted.

57 changes: 57 additions & 0 deletions copier.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
app_name:
type: str
help: "Short project name (e.g., myapp)"
default: "cart-service"

app_title:
type: str
help: "Project title"
default: "{{ app_name|capitalize }}"

domain:
type: str
help: "Domain name (e.g., user, order)"
default: "cart"

domain_capitalized:
type: str
help: "Domain name, capitalized"
default: "{{ domain|capitalize }}"

domain_uppercase:
type: str
help: "Domain name, uppercase"
default: "{{ domain|upper }}"

domain_plural:
type: str
help: "Plural form of domain"
default: "{% if domain.endswith('y') %}{{ domain.replace('y', '') }}ies{% else %}{{ domain.lower() }}s{% endif %}"

domain_plural_capitalized:
type: str
help: "Plural domain, capitalized"
default: "{{ domain_plural|capitalize }}"

domain_plural_uppercase:
type: str
help: "Plural domain, uppercase"
default: "{{ domain_plural|upper }}"

group_id:
type: str
help: "Maven groupId"
default: "org.{{ domain }}"

artifact_id:
type: str
help: "Maven artifactId"
default: "{{ domain }}"

package_name:
type: str
help: "Base package name"
default: "{{ group_id }}"

_copy_without_render:
- .github
37 changes: 0 additions & 37 deletions generate-cookiecutter-template-from-example-project.sh

This file was deleted.

46 changes: 46 additions & 0 deletions generate-copier-template-from-example-project.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
# This script is used to rename files and directories in the example project to that of the cookiecutter template.

# Remove previous example-template directory if it exists
if [ -d "example-template" ]; then
rm -rf "example-template"
fi
# Create a new example-template directory and copy the example project into it
mkdir "example-template"
rsync -a ./example/ ./example-template/
cd ./example-template

# sets the locale for all commands run in the current shell session to the "C" locale, which is the default POSIX locale. This makes programs like sed and find treat files as raw bytes, ignoring any character encoding issues. It helps avoid errors like illegal byte sequence when processing files with mixed or unknown encodings.
export LC_ALL=C

# Detect OS and set sed inline flag
if [[ "$(uname)" == "Darwin" ]]; then
SED_INPLACE=(-i '')
else
SED_INPLACE=(-i)
fi

find . -type f -exec sed "${SED_INPLACE[@]}" -e s/Examples/{{domain_plural_capitalized}}/g '{}' ';'
find . -depth -name '*Examples*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)Examples/\1{{domain_plural_capitalized}}/')"; done
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/examples/{{domain_plural}}/g '{}' ';'
find . -depth -name '*examples*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)examples/\1{{domain_plural}}/')"; done
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/Example/{{domain_capitalized}}/g '{}' ';'
find . -depth -name '*Example*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)Example/\1{{domain_capitalized}}/')"; done
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/example/{{domain}}/g '{}' ';'
find . -depth -name '*example*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)example/\1{{domain}}/')"; done
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/packagename/{{package_name}}/g '{}' ';'
find . -depth -name '*packagename*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)packagename/\1{{package_name}}/')"; done
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/artifactName/{{artifact_id}}/g '{}' ';'
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/group-id/{{group_id}}/g '{}' ';'
## For the following, we need to replace EXAMPLES and EXAMPLE with the domain name
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/EXAMPLES/{{domain_plural_uppercase}}/g '{}' ';'
find . -type f -exec sed "${SED_INPLACE[@]}" -e s/EXAMPLE/{{domain_uppercase}}/g '{}' ';'

# Rename files to add .jinja extension
# Add .jinja extension to files except those under .github
exts=(xml yml java feature sql yaml)
for ext in "${exts[@]}"; do
find . -type d -name .github -prune -o -type f -name "*.${ext}" -print0 | while IFS= read -r -d '' file; do
mv "$file" "$file.jinja"
done
done
18 changes: 18 additions & 0 deletions rename_dir.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# Dry-run: show planned renames
find . -depth -type d -name '{{cookiecutter.*' -print0 | \
while IFS= read -r -d '' d; do
new="$(dirname "$d")/$(basename "$d" | sed 's/^{{cookiecutter\./{{/')"
printf '%s -> %s\n' "$d" "$new"
done

## Apply changes: actually rename (run only after verifying dry-run)
find . -depth -type d -name '{{cookiecutter.*' -print0 | \
while IFS= read -r -d '' d; do
new="$(dirname "$d")/$(basename "$d" | sed 's/^{{cookiecutter\./{{/')"
if [ -e "$new" ]; then
printf 'Skipping %s: target exists %s\n' "$d" "$new" >&2
continue
fi
mv -- "$d" "$new" && printf 'Renamed %s -> %s\n' "$d" "$new"
done
3 changes: 0 additions & 3 deletions test-config.yml

This file was deleted.

7 changes: 7 additions & 0 deletions {{app_name}}/.docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM gcr.io/distroless/java21-debian12

WORKDIR /app

COPY ../../bootstrap/target/{{domain}}-exec.jar .

CMD ["{{domain}}-exec.jar"]
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>{{cookiecutter.group_id}}</groupId>
<artifactId>{{cookiecutter.artifact_id}}-parent</artifactId>
<groupId>{{group_id}}</groupId>
<artifactId>{{artifact_id}}-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>acceptance-test</artifactId>
<dependencies>
<dependency>
<groupId>{{cookiecutter.group_id}}</groupId>
<groupId>{{group_id}}</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
<!-- Important: DO NOT DELETE the below dependencies though might seem like redundant to that of
bootstrap but they are required for jacoco and pitest report aggregation -->
<!-- left adapter -->
<dependency>
<groupId>{{cookiecutter.group_id}}</groupId>
<groupId>{{group_id}}</groupId>
<artifactId>rest-adapter</artifactId>
</dependency>
<!-- domain -->
<dependency>
<groupId>{{cookiecutter.group_id}}</groupId>
<groupId>{{group_id}}</groupId>
<artifactId>domain</artifactId>
</dependency>
<!-- right adapter -->
<dependency>
<groupId>{{cookiecutter.group_id}}</groupId>
<groupId>{{group_id}}</groupId>
<artifactId>jpa-adapter</artifactId>
</dependency>
<!-- Test -->
Expand Down Expand Up @@ -69,8 +69,8 @@
<version>${cukedoctor-maven-plugin.version}</version>
<configuration>
<featuresDir>target/cucumber</featuresDir>
<outputFileName>{{cookiecutter.domain_capitalized}}</outputFileName>
<documentTitle>{{cookiecutter.domain_capitalized}} - Living Documentation</documentTitle>
<outputFileName>{{domain_capitalized}}</outputFileName>
<documentTitle>{{domain_capitalized}} - Living Documentation</documentTitle>
<docVersion>${project.version}</docVersion>
<toc>center</toc>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package {{cookiecutter.package_name}}.cucumber;
package {{package_name}}.cucumber;

import static io.cucumber.junit.platform.engine.Constants.*;

Expand All @@ -10,12 +10,12 @@

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features/{{cookiecutter.domain}}.feature")
@SelectClasspathResource("features/{{domain}}.feature")
@ConfigurationParameters({
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "{{cookiecutter.package_name}}.cucumber"),
@ConfigurationParameter(key = FILTER_TAGS_PROPERTY_NAME, value = "@{{cookiecutter.domain_capitalized}}"),
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "{{package_name}}.cucumber"),
@ConfigurationParameter(key = FILTER_TAGS_PROPERTY_NAME, value = "@{{domain_capitalized}}"),
@ConfigurationParameter(key = JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, value = "long"),
@ConfigurationParameter(key = PLUGIN_PUBLISH_QUIET_PROPERTY_NAME, value = "true"),
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "json:target/cucumber/cucumber.json")
})
public class RunCucumber{{cookiecutter.domain_capitalized}}Test {}
public class RunCucumber{{domain_capitalized}}Test {}
Loading