Stirling-PDF/.github/workflows/file_hash_generation.yml
Anthony Stirling 072de14f38 test
2025-04-16 15:25:34 +01:00

203 lines
8.1 KiB
YAML

name: Generate Template Hashes
on:
push:
branches:
- main
- hashs
paths:
- 'src/main/resources/templates/**'
- 'src/main/resources/static/**'
workflow_dispatch: # Allow manual triggering
jobs:
generate-hash:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Calculate template hashes
id: hash
run: |
# Create a Java program to calculate hashes
cat > HashGenerator.java << 'EOF'
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.CRC32;
public class HashGenerator {
private static final String TEMPLATE_DIR = "src/main/resources/templates";
private static final String STATIC_DIR = "src/main/resources/static";
private static final String OUTPUT_FILE = "src/main/resources/reference-hash.json";
// Text file extensions that need normalization
private static final Set<String> TEXT_EXTENSIONS = new HashSet<>(Arrays.asList(
"html", "htm", "css", "js", "txt", "md", "xml", "json", "csv", "properties"
));
public static void main(String[] args) throws IOException {
List<FileEntry> entries = new ArrayList<>();
// Process templates directory
processDirectory(new File(TEMPLATE_DIR), entries, "templates");
// Process static directory
processDirectory(new File(STATIC_DIR), entries, "static");
// Sort entries for consistent output
Collections.sort(entries);
// Write JSON output
writeJsonOutput(entries);
System.out.println("Generated hashes for " + entries.size() + " files");
}
private static void processDirectory(File dir, List<FileEntry> entries, String basePath) throws IOException {
if (!dir.exists() || !dir.isDirectory()) {
System.out.println("Directory not found: " + dir);
return;
}
processFilesRecursively(dir, dir, entries, basePath);
}
private static void processFilesRecursively(File baseDir, File currentDir, List<FileEntry> entries, String basePath)
throws IOException {
File[] files = currentDir.listFiles();
if (files == null) return;
for (File file : files) {
if (file.isDirectory()) {
processFilesRecursively(baseDir, file, entries, basePath);
} else {
// Get relative path
String relativePath = baseDir.toPath().relativize(file.toPath()).toString()
.replace('\\', '/');
String fullPath = basePath + "/" + relativePath;
// Calculate hash
String hash = calculateFileHash(file.toPath());
entries.add(new FileEntry(fullPath, hash));
System.out.println("Processed: " + fullPath + " => " + hash);
}
}
}
private static String calculateFileHash(Path filePath) throws IOException {
String extension = getFileExtension(filePath.toString()).toLowerCase();
boolean isTextFile = TEXT_EXTENSIONS.contains(extension);
if (isTextFile) {
return calculateNormalizedTextFileHash(filePath);
} else {
return calculateBinaryFileHash(filePath);
}
}
private static String calculateNormalizedTextFileHash(Path filePath) throws IOException {
byte[] content = Files.readAllBytes(filePath);
String text = new String(content, StandardCharsets.UTF_8);
// Normalize line endings to LF (remove CRs)
text = text.replace("\r", "");
byte[] normalizedBytes = text.getBytes(StandardCharsets.UTF_8);
CRC32 checksum = new CRC32();
checksum.update(normalizedBytes, 0, normalizedBytes.length);
return String.valueOf(checksum.getValue());
}
private static String calculateBinaryFileHash(Path filePath) throws IOException {
byte[] content = Files.readAllBytes(filePath);
CRC32 checksum = new CRC32();
checksum.update(content, 0, content.length);
return String.valueOf(checksum.getValue());
}
private static String getFileExtension(String filename) {
int lastDot = filename.lastIndexOf('.');
if (lastDot == -1 || lastDot == filename.length() - 1) {
return "";
}
return filename.substring(lastDot + 1);
}
private static void writeJsonOutput(List<FileEntry> entries) throws IOException {
File outputFile = new File(OUTPUT_FILE);
outputFile.getParentFile().mkdirs();
try (FileWriter writer = new FileWriter(outputFile)) {
writer.write("{\n");
for (int i = 0; i < entries.size(); i++) {
FileEntry entry = entries.get(i);
writer.write(" \"" + entry.path + "\": \"" + entry.hash + "\"");
if (i < entries.size() - 1) {
writer.write(",");
}
writer.write("\n");
}
writer.write("}\n");
}
}
// Class to represent a file and its hash
private static class FileEntry implements Comparable<FileEntry> {
final String path;
final String hash;
FileEntry(String path, String hash) {
this.path = path;
this.hash = hash;
}
@Override
public int compareTo(FileEntry other) {
return path.compareTo(other.path);
}
}
}
EOF
# Compile and run the Java program
javac HashGenerator.java
java HashGenerator
- name: Commit and push if changed
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "GitHub Actions"
git add src/main/resources/reference-hash.json
# Only commit if there are changes
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "Update template reference hashes [skip ci]"
git push
fi