Skip to content

Commit

Permalink
Improve usability: add available jobs to error message
Browse files Browse the repository at this point in the history
  • Loading branch information
kaklakariada committed Nov 21, 2024
1 parent 76b695a commit 27f90a4
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 36 deletions.
86 changes: 84 additions & 2 deletions .github/workflows/ci-build.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .project-keeper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ build:
- name: "ci-build.yml"
stepCustomizations:
- action: INSERT_AFTER
job: build-and-test
stepId: setup-java
content:
name: Set up Go
Expand All @@ -98,12 +99,14 @@ build:
go-version: "1.22"
cache-dependency-path: .project-keeper.yml
- action: INSERT_AFTER
job: build-and-test
stepId: setup-go
content:
name: Install Go tools
id: install-go-tools
run: go install github.com/google/[email protected]
- action: REPLACE
job: build-and-test
stepId: build-pk-verify
content:
name: Run tests and build with Maven
Expand All @@ -115,12 +118,14 @@ build:
env:
GITHUB_TOKEN: ${{ github.token }} # Required for integration tests
- action: INSERT_AFTER
job: build-and-test
stepId: sonar-analysis
content:
name: Run project-keeper itself
id: build-pk-verify
run: mvn --batch-mode com.exasol:project-keeper-maven-plugin:verify --projects .
- action: INSERT_AFTER
job: build-and-test
stepId: build-pk-verify
content:
name: Verify that metrics.json was created
Expand All @@ -134,6 +139,7 @@ build:
- name: "dependencies_check.yml"
stepCustomizations:
- action: INSERT_AFTER
job: report_security_issues
stepId: setup-jdks
content:
name: Install Project Keeper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,6 @@ private List<StepCustomization> convertSteps(final List<RawStepCustomization> st
}

private StepCustomization convertStep(final RawStepCustomization step) {
if (step.job == null || step.job.isBlank()) {
throw new IllegalArgumentException(ExaError.messageBuilder("E-PK-CORE-208")
.message("Missing job in step customization of file {{config file}}.", CONFIG_FILE_NAME)
.mitigation("Add job to the step customization.").toString());
}
if (step.action == null) {
throw new IllegalArgumentException(ExaError.messageBuilder("E-PK-CORE-200")
.message("Missing action in step customization of file {{config file}}.", CONFIG_FILE_NAME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private FileTemplate createTemplate(final FileTemplateFromResource template, fin
return new ContentCustomizingTemplate(template, new GitHubWorkflowCustomizer( //
javaVersionCustomizer(),
// [impl->dsn~customize-build-process.ci-build~0]
new GitHubWorkflowStepCustomizer(customizations),
new GitHubWorkflowStepCustomizer(workflowName, customizations),
// [impl->dsn~customize-build-process.ci-build.environment~1]
new GitHubWorkflowEnvironmentCustomizer(buildJobId, environmentName)));
}
Expand Down Expand Up @@ -119,7 +119,7 @@ private FileTemplate createCustomizedWorkflow(final String workflowName,
templateCustomizer.accept(template);
final List<StepCustomization> customizations = findCustomizations(workflowName);
return new ContentCustomizingTemplate(template, new GitHubWorkflowCustomizer(javaVersionCustomizer(),
new GitHubWorkflowStepCustomizer(customizations)));
new GitHubWorkflowStepCustomizer(workflowName, customizations)));
}

enum CiTemplateType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,9 @@ private Optional<String> getOptionalString(final String key) {
return Optional.ofNullable((String) rawStep.get(key));
}
}

public Job getJob(final Optional<String> jobId) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getJob'");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,44 @@

import java.util.List;

import com.exasol.errorreporting.ExaError;
import com.exasol.projectkeeper.config.ProjectKeeperConfigReader;
import com.exasol.projectkeeper.shared.config.workflow.StepCustomization;
import com.exasol.projectkeeper.validators.files.GitHubWorkflow.Job;

class GitHubWorkflowStepCustomizer implements GitHubWorkflowCustomizer.WorkflowCustomizer {
private final String workflowName;
private final List<StepCustomization> customizations;

GitHubWorkflowStepCustomizer(final List<StepCustomization> customizations) {
GitHubWorkflowStepCustomizer(final String workflowName, final List<StepCustomization> customizations) {
this.workflowName = workflowName;
this.customizations = customizations;
}

@Override
public void applyCustomization(final GitHubWorkflow workflow) {
for (final StepCustomization customization : customizations) {
final Job job = workflow.getJob(customization.getJobId());
final Job job = getJob(workflow, customization);
applyCustomization(job, customization);
}
}

private Job getJob(final GitHubWorkflow workflow, final StepCustomization customization) {
if (customization.getJobId().isPresent()) {
return workflow.getJob(customization.getJobId().get());
}
final List<Job> allJobs = workflow.getJobs();
if (allJobs.size() == 1) {
return allJobs.get(0);
}
throw new IllegalStateException(ExaError.messageBuilder("E-PK-CORE-208")
.message("Missing job in step customization of workflow {{workflow}} in file {{config file}}.",
workflowName, ProjectKeeperConfigReader.CONFIG_FILE_NAME)
.mitigation("Add job with one of the following values: {{available jobs}}.",
allJobs.stream().map(Job::getId).toList())
.toString());
}

// [impl->dsn~customize-build-process.insert-step-after~0]
// [impl->dsn~customize-build-process.replace-step~0]
private void applyCustomization(final Job job, final StepCustomization customization) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,27 +201,6 @@ static Stream<Arguments> invalidConfig() {
- stepCustomizations:
""", equalTo(
"E-PK-CORE-199: Missing workflow name in file '.project-keeper.yml'. Add a workflow name to the workflow configuration.")),
Arguments.of("workflow: missing job id", """
build:
workflows:
- name: ci-build.yml
stepCustomizations:
- action: REPLACE
content:
id: new-step
""", equalTo(
"E-PK-CORE-208: Missing job in step customization of file '.project-keeper.yml'. Add job to the step customization.")),
Arguments.of("workflow: empty job id", """
build:
workflows:
- name: ci-build.yml
stepCustomizations:
- job: ''
action: REPLACE
content:
id: new-step
""", equalTo(
"E-PK-CORE-208: Missing job in step customization of file '.project-keeper.yml'. Add job to the step customization.")),
Arguments.of("workflow: missing step id", """
build:
workflows:
Expand Down Expand Up @@ -340,6 +319,33 @@ void readWorkflowCustomization() throws IOException {
.build()));
}

@Test
void jobIdIsOptional() throws IOException {
writeProjectKeeperConfig("""
build:
workflows:
- name: ci-build.yml
stepCustomizations:
- action: REPLACE
stepId: step-id-to-replace
content:
name: New Step
id: new-step
run: echo 'new step'
env:
ENV_VARIABLE: 'value'
""");
assertThat(readConfig().getCiBuildConfig().getWorkflows(), contains(CustomWorkflow.builder() //
.workflowName("ci-build.yml") //
.addStep(StepCustomization.builder() //
.type(StepCustomization.Type.REPLACE) //
.stepId("step-id-to-replace") //
.step(WorkflowStep.createStep(Map.of("name", "New Step", "id", "new-step", "run",
"echo 'new step'", "env", Map.of("ENV_VARIABLE", "value")))) //
.build()) //
.build()));
}

@ParameterizedTest
@CsvSource({ "REPLACE, REPLACE", "INSERT_AFTER, INSERT_AFTER" })
void readWorkflowStepAction(final String action, final StepCustomization.Type expected) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

class GitHubWorkflowStepCustomizerTest {

private static final String WORKFLOW_NAME = "workflow.yml";

@Test
void startsWithGeneratedComment() {
final String yaml = getCustomizedContent("""
Expand Down Expand Up @@ -100,6 +102,46 @@ void replaceStep() {
assertThat(getStepIds(workflow.getJob("build")), contains("step0", "custom-step", "step2"));
}

@Test
void missingJobConfigurationWithSingleJob() {
final WorkflowStep newStep = WorkflowStep
.createStep(Map.of("name", "Custom Step", "id", "custom-step", "run", "echo custom-step"));
final GitHubWorkflow workflow = validate("""
jobs:
build:
steps:
- name: step0
id: step0
- name: step1
id: replaced-step
- name: step2
id: step2
""", StepCustomization.builder().jobId(null).type(Type.REPLACE).stepId("replaced-step").step(newStep)
.build());
assertThat(getStepIds(workflow.getJob("build")), contains("step0", "custom-step", "step2"));
}

@Test
void missingJobConfigurationWithMultipleJobsFails() {
final WorkflowStep newStep = WorkflowStep
.createStep(Map.of("name", "Custom Step", "id", "custom-step", "run", "echo custom-step"));
final IllegalStateException exception = assertThrows(IllegalStateException.class, () -> validate("""
jobs:
build1:
steps:
- name: step0
id: step0
build2:
steps:
- name: step0
id: step0
""", StepCustomization.builder().jobId(null).type(Type.REPLACE).stepId("replaced-step").step(newStep)
.build()));
assertThat(exception.getMessage(), equalTo(
"E-PK-CORE-208: Missing job in step customization of workflow 'workflow.yml' in file '.project-keeper.yml'. "
+ "Add job with one of the following values: ['build1', 'build2']."));
}

@Test
void replaceStepNextStepHasMissingId() {
final WorkflowStep newStep = WorkflowStep
Expand Down Expand Up @@ -221,7 +263,7 @@ private GitHubWorkflow validate(final String workflowTemplate, final StepCustomi
}

private String getCustomizedContent(final String workflowTemplate, final StepCustomization... customizations) {
return new GitHubWorkflowCustomizer(new GitHubWorkflowStepCustomizer(asList(customizations)))
return new GitHubWorkflowCustomizer(new GitHubWorkflowStepCustomizer(WORKFLOW_NAME, asList(customizations)))
.customizeContent(workflowTemplate);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.exasol.projectkeeper.shared.config.workflow;

import java.util.Objects;
import java.util.Optional;

/**
* This class defines how a GitHub workflow should be modified by inserting or replacing a step.
Expand All @@ -13,7 +14,7 @@ public final class StepCustomization {
private final WorkflowStep step;

private StepCustomization(final Builder builder) {
this.jobId = Objects.requireNonNull(builder.jobId, "jobId");
this.jobId = builder.jobId;
this.type = Objects.requireNonNull(builder.type, "type");
this.stepId = Objects.requireNonNull(builder.stepId, "stepId");
this.step = Objects.requireNonNull(builder.step, "step");
Expand All @@ -24,8 +25,8 @@ private StepCustomization(final Builder builder) {
*
* @return job ID
*/
public String getJobId() {
return jobId;
public Optional<String> getJobId() {
return Optional.ofNullable(jobId);
}

/**
Expand Down

0 comments on commit 27f90a4

Please sign in to comment.