Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
**/*.swp
**/*.swo
**/.DS_Store
.env
.env.*
!.env.example
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ hs_err_pid*
node_modules/
package-lock.json

# Developer-local environment files
.env
.env.*
!.env.example

# Temporary files
*.tmp
*.bak
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.xtrmetl.etl.config;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.jupiter.api.Test;

/**
* Guards repository boundaries that keep developer-local environment files out of Git and Docker
* build contexts.
*
* <p>The local Compose guidance uses environment overrides for database and service credentials.
* Those files must remain untracked and excluded from Docker build transfer by default, while a
* reviewed non-secret {@code .env.example} template may remain available for source-controlled
* documentation.</p>
*/
class RepositorySecretFilePolicyTest {

@Test
void localEnvironmentFilesAreIgnoredWhileExampleTemplateMayBeTracked() throws IOException {
Path repositoryRoot = findRepositoryRoot(Path.of("").toAbsolutePath().normalize());
assertNotNull(repositoryRoot, "repository root containing .gitignore must be discoverable");

assertEnvironmentFileRules(
Files.readAllLines(repositoryRoot.resolve(".gitignore")),
"root .gitignore"
);
}

@Test
void localEnvironmentFilesAreExcludedFromDockerBuildContext() throws IOException {
Path repositoryRoot = findRepositoryRoot(Path.of("").toAbsolutePath().normalize());
assertNotNull(repositoryRoot, "repository root containing .gitignore must be discoverable");

Path dockerIgnore = repositoryRoot.resolve(".dockerignore");
assertTrue(Files.isRegularFile(dockerIgnore), "root .dockerignore must exist");
assertEnvironmentFileRules(Files.readAllLines(dockerIgnore), "root .dockerignore");
}

private static void assertEnvironmentFileRules(List<String> patterns, String boundary) {
assertTrue(patterns.contains(".env"), boundary + " must ignore .env");
assertTrue(patterns.contains(".env.*"), boundary + " must ignore environment-specific .env files");
assertTrue(
patterns.contains("!.env.example"),
boundary + " must permit a reviewed non-secret .env.example template"
);
}

private static Path findRepositoryRoot(Path start) {
Path candidate = start;
while (candidate != null) {
if (Files.isRegularFile(candidate.resolve(".gitignore"))) {
return candidate;
}
candidate = candidate.getParent();
}
return null;
}
}
Loading