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
19 changes: 19 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"permissions": {
"allow": [
"Bash(git checkout:*)",
"Bash(./gradlew clean:*)",
"Bash(git add:*)",
"Bash(./gradlew publishToMavenLocal:*)",
"Bash(gradle build:*)",
"Bash(unzip:*)",
"Bash(gradle clean:*)",
"Bash(git:*)",
"Bash(GIT_SEQUENCE_EDITOR=\"/tmp/reword_all.sh\" GIT_EDITOR=\"/tmp/strip_coauthor.sh\" git:*)",
"Bash(gh pr:*)",
"Bash(gh issue:*)",
"Bash(ls:*)",
"WebFetch(domain:github.com)"
]
}
}
4 changes: 2 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ toc::[]
[source,gradle]
----
plugins {
id 'io.github.reqstool' version '0.2.0'
id 'io.github.reqstool.gradle-plugin' version '0.1.0'
}
----

Expand Down Expand Up @@ -104,7 +104,7 @@ When the `maven-publish` plugin is applied, the reqstool ZIP is automatically re
[source,gradle]
----
plugins {
id 'io.github.reqstool' version '0.2.0'
id 'io.github.reqstool.gradle-plugin' version '0.1.0'
id 'maven-publish'
}

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group = 'io.github.reqstool'
version = '0.2.0'
version = '0.1.0'

java {
sourceCompatibility = JavaVersion.VERSION_17
Expand All @@ -24,7 +24,7 @@ gradlePlugin {

plugins {
reqstoolPlugin {
id = 'io.github.reqstool'
id = 'io.github.reqstool.gradle-plugin'
implementationClass = 'io.github.reqstool.gradle.RequirementsToolPlugin'
displayName = 'Reqstool Gradle Plugin'
description = 'Gradle plugin for assembling and attaching reqstool ZIP artifacts'
Expand All @@ -50,7 +50,7 @@ dependencies {
}

javadoc {
options.addStringOption('Xdoclint:none', '-quiet')
options.addBooleanOption('Xdoclint:all', true)
}

test {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,34 +59,71 @@ public RequirementsToolExtension(Project project) {
this.skipAttachZipArtifact.convention(false);
}

/**
* Returns the path to the requirements annotations YAML file generated by the
* annotation processor.
* @return file property for requirements annotations
*/
public RegularFileProperty getRequirementsAnnotationsFile() {
return requirementsAnnotationsFile;
}

/**
* Returns the path to the SVCs (Software Verification Cases) annotations YAML file
* generated by the test annotation processor.
* @return file property for SVCs annotations
*/
public RegularFileProperty getSvcsAnnotationsFile() {
return svcsAnnotationsFile;
}

/**
* Returns the output directory where the ZIP artifact and combined annotations are
* written.
* @return file property for the output directory
*/
public RegularFileProperty getOutputDirectory() {
return outputDirectory;
}

/**
* Returns the dataset directory containing {@code requirements.yml} and optional
* supporting files.
* @return file property for the dataset directory
*/
public RegularFileProperty getDatasetPath() {
return datasetPath;
}

/**
* Returns the list of Ant-style glob patterns used to locate test result XML files.
* @return list property of test result patterns
*/
public ListProperty<String> getTestResults() {
return testResults;
}

/**
* Returns whether the entire plugin execution should be skipped.
* @return boolean property; {@code true} skips all plugin tasks
*/
public Property<Boolean> getSkip() {
return skip;
}

/**
* Returns whether ZIP artifact assembly should be skipped while still combining
* annotations.
* @return boolean property; {@code true} skips ZIP assembly
*/
public Property<Boolean> getSkipAssembleZipArtifact() {
return skipAssembleZipArtifact;
}

/**
* Returns whether attaching the ZIP artifact for Maven publishing should be skipped.
* @return boolean property; {@code true} skips artifact attachment
*/
public Property<Boolean> getSkipAttachZipArtifact() {
return skipAttachZipArtifact;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
*/
public class RequirementsToolPlugin implements Plugin<Project> {

/**
* Applies the plugin to a Gradle project. Registers the {@code assembleRequirements}
* task and automatically configures Maven publishing if the {@code maven-publish}
* plugin is applied.
* @param project the Gradle project
*/
@Override
public void apply(Project project) {
// Create extension for configuration
Expand Down Expand Up @@ -55,6 +61,12 @@ public void apply(Project project) {
});
}

/**
* Configures Maven publishing to automatically attach the reqstool ZIP artifact to
* the publication.
* @param project the Gradle project
* @param assembleTask provider for the assembleRequirements task
*/
private void configureMavenPublishing(Project project, TaskProvider<RequirementsToolTask> assembleTask) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);

Expand Down
89 changes: 89 additions & 0 deletions src/main/java/io/github/reqstool/gradle/RequirementsToolTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,75 +109,132 @@ public class RequirementsToolTask extends DefaultTask {

private final RegularFileProperty zipFile = getProject().getObjects().fileProperty();

/**
* Returns the path to the requirements annotations YAML file.
* @return file property for requirements annotations
*/
@Optional
@InputFile
public RegularFileProperty getRequirementsAnnotationsFile() {
return requirementsAnnotationsFile;
}

/**
* Returns the path to the SVCs (Software Verification Cases) annotations YAML file.
* @return file property for SVCs annotations
*/
@Optional
@InputFile
public RegularFileProperty getSvcsAnnotationsFile() {
return svcsAnnotationsFile;
}

/**
* Returns the absolute path to the output directory.
* @return output directory path as a string
*/
@Input
public String getOutputDirectoryPath() {
File outDir = outputDirectory.getAsFile().getOrNull();
return outDir != null ? outDir.getAbsolutePath() : "";
}

/**
* Returns the output directory file property.
* @return file property for the output directory
*/
@Internal
public RegularFileProperty getOutputDirectory() {
return outputDirectory;
}

/**
* Returns the dataset directory containing requirements and supporting files.
* @return file property for the dataset directory
*/
@InputDirectory
@Optional
public RegularFileProperty getDatasetPath() {
return datasetPath;
}

/**
* Returns the list of test result file glob patterns.
* @return list property of test result patterns
*/
@Input
public ListProperty<String> getTestResults() {
return testResults;
}

/**
* Returns whether this task execution should be skipped.
* @return boolean property
*/
@Input
public Property<Boolean> getSkip() {
return skip;
}

/**
* Returns whether ZIP artifact assembly should be skipped.
* @return boolean property
*/
@Input
public Property<Boolean> getSkipAssembleZipArtifact() {
return skipAssembleZipArtifact;
}

/**
* Returns whether artifact attachment should be skipped.
* @return boolean property
*/
@Input
public Property<Boolean> getSkipAttachZipArtifact() {
return skipAttachZipArtifact;
}

/**
* Returns the name of the project being built.
* @return project name property
*/
@Input
public Property<String> getProjectName() {
return projectName;
}

/**
* Returns the version of the project being built.
* @return project version property
*/
@Input
public Property<String> getProjectVersion() {
return projectVersion;
}

/**
* Returns the base directory of the project.
* @return project base directory property
*/
@Input
public Property<File> getProjectBasedir() {
return projectBasedir;
}

/**
* Returns the path where the reqstool ZIP artifact will be written.
* @return file property for the ZIP artifact
*/
@OutputFile
public RegularFileProperty getZipFile() {
return zipFile;
}

/**
* Executes the task. Combines requirements and test annotations into a single
* annotations file, and optionally assembles a ZIP artifact containing requirements,
* annotations, and test results.
*/
@TaskAction
public void execute() {
if (skip.get()) {
Expand Down Expand Up @@ -226,6 +283,13 @@ public void execute() {
}
}

/**
* Combines implementations and tests nodes into a single requirement annotations
* node.
* @param implementationsNode node containing requirement implementations
* @param testsNode node containing test cases
* @return combined requirement annotations node
*/
static JsonNode combineOutput(JsonNode implementationsNode, JsonNode testsNode) {
ObjectNode requirementAnnotationsNode = yamlMapper.createObjectNode();
if (!implementationsNode.isEmpty()) {
Expand All @@ -241,6 +305,12 @@ static JsonNode combineOutput(JsonNode implementationsNode, JsonNode testsNode)
return newNode;
}

/**
* Writes the combined annotations to a YAML file with language server schema hints.
* @param outputFile the file to write to
* @param combinedOutputNode the combined annotations node
* @throws IOException if writing fails
*/
private void writeCombinedOutputToFile(File outputFile, JsonNode combinedOutputNode) throws IOException {
File reqAnnotFile = requirementsAnnotationsFile.getAsFile().getOrNull();
File svcsAnnotFile = svcsAnnotationsFile.getAsFile().getOrNull();
Expand All @@ -255,6 +325,11 @@ private void writeCombinedOutputToFile(File outputFile, JsonNode combinedOutputN
}
}

/**
* Assembles the reqstool ZIP artifact containing requirements, annotations, and test
* results.
* @throws IOException if ZIP creation or file reading fails
*/
private void assembleZipArtifact() throws IOException {
String zipArtifactFilename = projectName.get() + "-" + projectVersion.get() + "-reqstool.zip";
String topLevelDir = projectName.get() + "-" + projectVersion.get() + "-reqstool";
Expand Down Expand Up @@ -340,6 +415,13 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
getLogger().info("Assembled zip artifact: " + zipFileOutput.getAbsolutePath());
}

/**
* Adds a file to the ZIP artifact at the specified target directory.
* @param zipOut the ZIP output stream
* @param file the file to add
* @param targetDirectory the target directory within the ZIP
* @throws IOException if reading the file or writing to ZIP fails
*/
private void addFileToZipArtifact(ZipOutputStream zipOut, File file, File targetDirectory) throws IOException {
if (file.exists()) {
File entryName;
Expand All @@ -362,6 +444,13 @@ private void addFileToZipArtifact(ZipOutputStream zipOut, File file, File target
}
}

/**
* Creates and adds the reqstool_config.yml file to the ZIP artifact.
* @param zipOut the ZIP output stream
* @param topLevelDir the top-level directory within the ZIP
* @param reqstoolConfigResources map of resource files included in the artifact
* @throws IOException if writing to ZIP fails
*/
private void addReqstoolConfigYamlToZip(ZipOutputStream zipOut, File topLevelDir,
Map<String, Object> reqstoolConfigResources) throws IOException {
DumperOptions options = new DumperOptions();
Expand Down