Skip to content

Commit

Permalink
Merge pull request #628 from fortify/develop
Browse files Browse the repository at this point in the history
Prepare for next release
  • Loading branch information
rsenden authored Oct 25, 2024
2 parents 19ceffd + fecf423 commit f597c45
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.nio.file.StandardOpenOption;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -116,14 +115,28 @@ private final String generateOptionDescription(IOptionDescriptor descriptor) {

private final String addLinks(String contents) {
if ( manpageDir==null ) { return contents; }
// TODO Do we want to automatically insert fcli links (which could potentially lead to bugs as seen with
// https://github.com/fortify/fcli/issues/622), or should we allow Markdown syntax in action descriptions?
// We could either add support for new markdownDescription properties, or allow Markdown in existing
// description properties and clean this up in the 'action help' command.
var manPages = listDir(manpageDir).stream().filter(s->s.matches("fcli-[\\w-]+-[\\w-]+-[\\w-]+.adoc"))
.map(s->s.replaceAll("\\.adoc", ""))
.sorted((a,b)->Integer.compare(a.length(), b.length())) // In case of overlapping names, we need to replace longest matching name
.collect(Collectors.toSet());
for ( var manPage : manPages ) {
var pattern = manPage.replace("-", "[ -]");
var replacement = String.format("link:manpage/%s.html[$1]", manPage);
contents = contents.replaceAll("(?<!`)("+pattern+")", replacement);
contents = contents.replaceAll("(`"+pattern+".*`)", replacement);
if ( manPage.matches("fcli-[a-z]+-action-run") ) {
// Replace 'fcli <module> action run' references in synopsis
contents = contents.replaceAll("("+pattern+")", replacement);
} else {
// Replace literal 'fcli *' references embedded in backticks, if not preceded by '['
// as that (likely) means we already generated a link for a longer command name.
// See https://github.com/fortify/fcli/issues/622 for example. The backticks need to
// go into the link text (as otherwise link:... would be rendered literally), so we
// need to include the full text between the backticks in the link text.
contents = contents.replaceAll("(?<!\\[)(`"+pattern+".*`)", replacement);
}
}
return contents;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
FoDReleaseUpdateCommand.class,
FoDReleaseDeleteCommand.class,
FoDReleaseAssessmentTypeListCommand.class,
FoDReleaseScanListCommand.class
FoDReleaseScanListCommand.class,
FoDReleaseWaitForCommand.class
}
)
@DefaultVariablePropertyName("releaseId")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright 2021, 2023 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/

package com.fortify.cli.fod.release.cli.cmd;

import java.util.Set;

import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.rest.cli.cmd.AbstractWaitForCommand;
import com.fortify.cli.common.rest.wait.WaitHelper.WaitHelperBuilder;
import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin;
import com.fortify.cli.fod._common.session.cli.mixin.FoDUnirestInstanceSupplierMixin;
import com.fortify.cli.fod.release.cli.mixin.FoDReleaseByQualifiedNameOrIdResolverMixin;

import kong.unirest.UnirestInstance;
import lombok.Getter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Option;

@Command(name = OutputHelperMixins.WaitFor.CMD_NAME)
public final class FoDReleaseWaitForCommand extends AbstractWaitForCommand {
@Getter @Mixin private FoDUnirestInstanceSupplierMixin unirestInstanceSupplier;
@Mixin private FoDDelimiterMixin delimiterMixin; // Is automatically injected in resolver mixins
@Mixin private FoDReleaseByQualifiedNameOrIdResolverMixin.PositionalParameterMulti releaseResolver;
@Option(names={"-s", "--suspended"}, paramLabel="true|false", required=true, defaultValue="false", arity="1")
private boolean suspended;

@Override
protected final WaitHelperBuilder configure(UnirestInstance unirest, WaitHelperBuilder builder) {
return builder
.recordsSupplier(releaseResolver::getReleaseDescriptorJsonNodes)
.currentStateProperty("suspended")
.knownStates("true", "false")
.failureStates()
.matchStates(Set.of(String.valueOf(suspended)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@

package com.fortify.cli.fod.release.cli.mixin;

import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.databind.JsonNode;
import com.fortify.cli.common.cli.util.EnvSuffix;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.fod._common.cli.mixin.FoDDelimiterMixin;
Expand Down Expand Up @@ -43,6 +48,23 @@ public String getReleaseId(UnirestInstance unirest) {
return descriptor==null ? null : descriptor.getReleaseId();
}
}

public static abstract class AbstractFoDMultiQualifiedReleaseNameOrIdResolverMixin implements IFoDDelimiterMixinAware {
@Setter private FoDDelimiterMixin delimiterMixin;
public abstract String[] getQualifiedReleaseNamesOrIds();

public FoDReleaseDescriptor[] getReleaseDescriptors(UnirestInstance unirest, String... fields) {
return Stream.of(getQualifiedReleaseNamesOrIds()).map(nameOrId->FoDReleaseHelper.getReleaseDescriptor(unirest, nameOrId, delimiterMixin.getDelimiter(), true, fields)).toArray(FoDReleaseDescriptor[]::new);
}

public Collection<JsonNode> getReleaseDescriptorJsonNodes(UnirestInstance unirest, String... fields) {
return Stream.of(getReleaseDescriptors(unirest, fields)).map(FoDReleaseDescriptor::asJsonNode).collect(Collectors.toList());
}

public Integer[] getReleaseIds(UnirestInstance unirest) {
return Stream.of(getReleaseDescriptors(unirest, "releaseId")).map(FoDReleaseDescriptor::getReleaseId).toArray(Integer[]::new);
}
}

public static class RequiredOption extends AbstractFoDQualifiedReleaseNameOrIdResolverMixin {
@Option(names = {"--release", "--rel"}, required = true, paramLabel = "id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.name-or-id")
Expand All @@ -63,4 +85,9 @@ public static class OptionalCopyFromOption extends AbstractFoDQualifiedReleaseNa
@Option(names = {"--copy-from"}, required = false, paramLabel = "id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.copy-from.nameOrId")
@Getter private String qualifiedReleaseNameOrId;
}

public static class PositionalParameterMulti extends AbstractFoDMultiQualifiedReleaseNameOrIdResolverMixin {
@Parameters(index = "0", arity = "1..", paramLabel="id|app[:ms]:rel", descriptionKey = "fcli.fod.release.resolver.multi-name-or-id")
@Getter private String[] qualifiedReleaseNamesOrIds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ valueTemplates:

- name: reviewBody
contents: |
## Fortify vulnerability summary (PREVIEW)
## Fortify vulnerability summary
Any issues listed below are based on comparing the latest scan results against the previous scan results in FoD release [${parameters.release.applicationName}${#isNotBlank(parameters.release.microserviceNae)?'- '+parameters.release.microserviceName:''} - ${parameters.release.releaseName}](${#fod.releaseBrowserUrl(parameters.release)}). This is for informational purposes only and, depending on workflow, may not be an accurate representation of what issues will be introduced into or removed from the target branch when merging this PR.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ parameters:
name: sdlc-status
cliAliases: status
description: "See `fcli fod release create`"
defaultValue: Development
- group: sast_setup_opts
name: assessment-type
required: false
Expand Down Expand Up @@ -95,6 +96,9 @@ steps:
- to: stdout
value: |
Create application release ${parameters.release} (id ${createRelease[0].releaseId}): ${createRelease[0].__action__}
- progress: "Waiting for release to leave suspended state"
- fcli:
- args: fod release wait-for "${parameters.release}" --progress=none
- if: ${parameters["scan-types"].contains("sast")}
steps:
- if: ${parameters.profile=="default"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fcli.fod.scan.in-progress-action = The action to use if a scan is already in pro
fcli.fod.scan.remediation-preference = The remediation preference to use. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.microservice.resolver.name = Microservice name in the format <application>:<microservice>.
fcli.fod.release.resolver.name-or-id = Release id or <application>[:<microservice>]:<release> name.
fcli.fod.release.resolver.multi-name-or-id = One or more release id's or <application>[:<microservice>]:<release> names.
fcli.fod.release.resolver.name = Release name in the format <application>[:<microservice>]:<release>.
fcli.fod.import.sbom-format = The SBOM format to import. If empty Cyclone DX format is assumed.
fcli.fod.user.user-name-or-id = User id or username. Note that numeric values are always interpreted \
Expand Down Expand Up @@ -363,7 +364,11 @@ fcli.fod.release.create.usage.header = Create a new application release. \
fcli.fod.release.create.application-name = The id or name of the application to create the release on.
fcli.fod.release.create.release-name = The name of the release to create for the application.
fcli.fod.release.create.description = Description of the release.
fcli.fod.release.create.copy-from = The id or name of a release to copy existing state from.
fcli.fod.release.create.copy-from = The id or name of a release to copy existing state from. Note that \
FoD will put the release in 'suspended' state until copying is complete, during which time scan \
requests and other operations may be rejected. If you want to run any other operations on the release, \
it is recommended to first invoke the `fcli fod release wait-for` command to wait until the release \
leaves suspended state.
fcli.fod.release.create.microservice = The id or name of the microservice to create the release on.
fcli.fod.release.create.status = SDLC lifecycle status of the release. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.release.create.attr = Attribute id or name and its value to set on the release. \
Expand All @@ -387,6 +392,19 @@ fcli.fod.release.update.attr = Attribute id or name and its value to set on the
fcli.fod.release.list-assessment-types.usage.header = List assessment types for a given release.
fcli.fod.release.list-assessment-types.scan-types = Comma-separated list of scan types for which to list assessment types. Default value: ${DEFAULT-VALUE}. Valid values: ${COMPLETION-CANDIDATES}.
fcli.fod.release.list-scans.usage.header = List scans for a given release.
fcli.fod.release.wait-for.usage.header = Wait for one or more scans to reach or exit suspended state.
fcli.fod.release.wait-for.usage.description.0 = Although this command offers a lot of options to \
cover many different use cases, you can simply pass one or more release names or id's to wait until \
those releases leave 'suspended' state. \
%n%nMost common use case is to invoke this wait-for command after creating a new release through the \
`fcli fod release create` command with the `--copy-from` option; FoD will put the newly created \
release in 'suspended' state until copying is completed, during which time scan requests and other \
operations may be rejected. \
%n%nNote that contrary to other fcli wait-for commands, any options related to unknown or failure state \
handling are not applicable to this wait-for command and will be ignored.
fcli.fod.release.wait-for.until = Wait until either any or all releases match. If neither --until or --while are specified, default is to wait until all releases match.
fcli.fod.release.wait-for.while = Wait while either any or all releases match.
fcli.fod.release.wait-for.suspended = Suspended state against which to match the given releases; may be `false` (default) or `true`.

# fcli fod assessment-type
fcli.fod.assessment-type.usage.header = Manage FoD assessment types.
Expand Down Expand Up @@ -884,6 +902,7 @@ fcli.fod.app.output.table.options = applicationId,applicationName,fcliApplicatio
fcli.fod.app.scan.output.table.options = scanId,scanType,analysisStatusType,applicationName,microserviceName,releaseName,startedDateTime,completedDateTime,scanMethodTypeName
fcli.fod.microservice.output.table.options = microserviceId,microserviceName,applicationName
fcli.fod.release.output.table.options = releaseId,releaseName,microserviceName,applicationName,sdlcStatusType
fcli.fod.release.wait-for.output.table.options = releaseId,releaseName,microserviceName,applicationName,suspended
fcli.fod.release.scan.output.table.options = scanId,scanType,analysisStatusType,applicationName,microserviceName,releaseName,startedDateTime,completedDateTime,scanMethodTypeName
fcli.fod.release.assessment-type.output.table.options = assessmentTypeId,name,scanType,frequencyType,unitInfo,entitlementId,entitlementDescription
fcli.fod.entitlement.output.table.options = entitlementId,entitlementDescription,startDate,endDate,unitInfo
Expand Down
Loading

0 comments on commit f597c45

Please sign in to comment.