Skip to content
Open
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
61 changes: 61 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ jobs:
runs-on: ubuntu-latest
permissions:
pull-requests: read # allows SonarCloud to decorate PRs with analysis results
outputs:
ref_name: ${{ steps.set-vars.outputs.ref_name }}
commit_sha: ${{ steps.set-vars.outputs.commit_sha }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -50,3 +53,61 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: target/classes

- name: Set ref_name and commit_sha
id: set-vars
run: |
echo "::set-output name=ref_name::${{ github.ref_name }}"
echo "::set-output name=commit_sha::${{ github.sha }}"

deploy-to-gh-pages:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also use the "GitHub action" approach to reduce complexity in this workflow. Check the official doc here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all transparency, I'm completely new to GitHub Actions.

My proposal is therefore very much open to improvement.

Please feel free to suggest concrete improvements by adding commits directly to this branch.

name: Deploy to GitHub Pages
runs-on: ubuntu-latest
needs: build
# Execute this stage only for main and tags
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
fetch-depth: 0

- name: Define target_data_dir
id: set-target-dir
run: echo "target_data_dir=data/${{ needs.build.outputs.ref_name }}" >> $GITHUB_ENV

- name: Remove old content
run: |
git clean -fd
git reset --hard
rm -rf "${{ env.target_data_dir }}"

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-artifacts
path: "${{ env.target_data_dir }}"

- name: Generate data/index.json of all available already published versions
run: |
find data -name "index.json" | sort | while IFS= read -r indexJsonFile; do
relative_path="$(echo "${indexJsonFile}" | sed -E 's,^data/,,')"
jq --arg file "$relative_path" '.specification | {($file): {title: .title, version: .version, scmRevisionDate: .scmRevisionDate, scmRevisionNumber: .scmRevisionNumber}}' "$indexJsonFile"
done | jq -s 'add' > data/index.json

- name: Commit and push changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "${{ env.target_data_dir }}" "data/index.json"
git commit -m "Deploy ${{ env.target_data_dir }} to GitHub Pages" -m "(from #${{ needs.build.outputs.commit_sha }})"
git push origin gh-pages
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ dependency-reduced-pom.xml

# Ignore IDE files
*.iml

# Data directory is only for `gh-pages` branch
/data/
2 changes: 1 addition & 1 deletion .mvn/extensions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<extension>
<groupId>me.qoomon</groupId>
<artifactId>maven-git-versioning-extension</artifactId>
<version>9.8.1</version>
<version>9.10.2</version>
</extension>
</extensions>
66 changes: 66 additions & 0 deletions build/main/java/org/greencodeinitiative/tools/exporter/Main.java
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't the build folder name be perceived by contributors as a folder with generated files?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. What name would you suggest? As far as I know, there is no convention for naming the directory that should contain resources used only by the build process itself.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.greencodeinitiative.tools.exporter;

import org.greencodeinitiative.tools.exporter.infra.MetadataWriter;

import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static java.util.Collections.emptyList;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;

public class Main implements Runnable {
private final List<String> args;

public Main(String[] args) {
this.args = ofNullable(args).map(List::of).orElse(emptyList());
}

public static void main(String... args) {
new Main(args).run();
}

@Override
public void run() {
Path sourceDir = argAsPath(0, "sourceDir");
Path targetDir = argAsPath(1, "targetDir");
new MetadataWriter(
sourceDir,
targetDir,
Map.of(
"title", arg(2, "specificationTitle"),
"version", arg(3, "specificationVersion"),
"scmRevisionNumber", arg(4, "specificationSCMRevisionNumber"),
"scmRevisionDate", arg(5, "specificationSCMRevisionDate")
),
// indexFile
optionalArg(6)
.map(Path::of)
.orElseGet(() -> targetDir.resolve("index.json")),
// minTermLength
optionalArg(7)
.map(Integer::parseInt)
.orElse(4)
).run();
}

private Optional<String> optionalArg(int index) {
if (args.size() <= index) {
return empty();
}
return Optional.of(args.get(index));
}

private String arg(int index, String description) {
if (args.size() <= index) {
throw new IllegalArgumentException("argument " + (index + 1) + " is required: " + description);
}
return optionalArg(index).orElseThrow(() -> new IllegalArgumentException("argument " + (index + 1) + " is required: " + description));
}

private Path argAsPath(int index, String description) {
return Path.of(arg(index, description));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.greencodeinitiative.tools.exporter.domain;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Optional.empty;
import static java.util.Optional.of;

public class Rule {
/**
* Resources to include
*/
private static final Pattern TARGET_RESOURCES = Pattern.compile("[^/]{1,1000}/(?<ruleKey>GCI\\d{1,20})/(?<language>[^/]{1,100})/[^/]{3,20}\\.html$");

public static Optional<Rule> createFromHtmlDescription(Path htmlDescription) {
final Matcher matcher = TARGET_RESOURCES.matcher(htmlDescription.toString().replace('\\', '/'));
if (!matcher.find()) {
return empty();
}
final String ruleKey = matcher.group("ruleKey");
final Path metadata = htmlDescription.getParent().getParent().resolve(ruleKey + ".json");
final Path specificMetadata = htmlDescription.getParent().resolve(ruleKey + ".json");

if (!Files.isRegularFile(htmlDescription) || !Files.isRegularFile(metadata)) {
return empty();
}

return of(new Rule(
ruleKey,
matcher.group("language"),
htmlDescription,
metadata,
specificMetadata
));
}

private final String ruleKey;
private final String language;
private final Path htmlDescription;
private final Path metadata;
private final Path specificMetadata;

Rule(
String ruleKey,
String language,
Path htmlDescription,
Path metadata,
Path specificMetadata
) {
this.ruleKey = ruleKey;
this.language = language;
this.htmlDescription = htmlDescription;
this.metadata = metadata;
this.specificMetadata = specificMetadata;
}

public Path getHtmlDescriptionTargetPath(Path targetDir) {
return targetDir.resolve(language).resolve(htmlDescription.getFileName());
}

public Path getMetadataTargetPath(Path targetDir) {
return targetDir.resolve(language).resolve(metadata.getFileName());
}

public String ruleKey() {
return ruleKey;
}

public String language() {
return language;
}

public Path htmlDescription() {
return htmlDescription;
}

public Path metadata() {
return metadata;
}

public Path specificMetadata() {
return specificMetadata;
}
}
Loading
Loading