Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for new 2.x release #571

Merged
merged 17 commits into from
Aug 13, 2024
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
8 changes: 3 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -26,12 +26,11 @@ jobs:
- name: PROD - Prepare GitHub release
id: create_prod_release
uses: GoogleCloudPlatform/release-please-action@v3
if: github.ref == 'refs/heads/main'
if: github.ref == 'refs/heads/v2.x'
with:
command: github-release
release-type: simple
package-name: ${{ github.event.repository.name }}
default-branch: main

- name: PROD - Define release info
if: steps.create_prod_release.outputs.release_created
@@ -266,13 +265,12 @@ jobs:
name: combined-artifacts

- name: PROD - Prepare release PR
if: github.ref == 'refs/heads/main'
if: github.ref == 'refs/heads/v2.x'
uses: GoogleCloudPlatform/release-please-action@v3
with:
command: release-pr
release-type: simple
package-name: ${{ github.event.repository.name }}
default-branch: main

- name: DEV - Prepare GitHub release
if: needs.build.outputs.do_dev_release
@@ -322,7 +320,7 @@ jobs:
rm -rf docs/.git*

# Extract top-level documentation resources
# TODO Should we do this only when building a release, or also for dev_main,
# TODO Should we do this only when building a release, or also for dev_v2.x,
# or for all (dev & release) versions like we do now?
unzip -o artifacts/docs-gh-pages.zip -d "docs"

Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
import com.fortify.cli.common.progress.helper.ProgressWriterType;
import com.fortify.cli.common.util.DisableTest;
import com.fortify.cli.common.util.DisableTest.TestType;
import com.fortify.cli.common.util.EnvHelper;

import lombok.SneakyThrows;
import picocli.CommandLine.Mixin;
@@ -68,7 +69,26 @@ public final Integer call() {
private Callable<Integer> run(ActionRunner actionRunner, IProgressWriterI18n progressWriter) {
actionRunner.getSpelEvaluator().configure(context->configure(actionRunner, context));
progressWriter.writeProgress("Executing action %s", actionRunner.getAction().getMetadata().getName());
return actionRunner.run(actionArgs);
// We need to set the FCLI_DEFAULT_<module>_SESSION environment variable to allow fcli: statements to
// pick up the current session name, and (although probably not needed currently), reset the default
// session name to the previous value once the action completes.
var sessionEnvName = String.format("%s_%s_SESSION", System.getProperty("fcli.env.default.prefix", "FCLI_DEFAULT"), getType().toUpperCase());
var sessionPropertyName = EnvHelper.envSystemPropertyName(sessionEnvName);
var sessionEnvOrgValue = EnvHelper.env(sessionEnvName);
try {
setOrClearSystemProperty(sessionPropertyName, getSessionName());
return actionRunner.run(actionArgs);
} finally {
setOrClearSystemProperty(sessionPropertyName, sessionEnvOrgValue);
}
}

private void setOrClearSystemProperty(String name, String value) {
if ( value==null ) {
System.clearProperty(name);
} else {
System.setProperty(name, value);
}
}

private ParameterException onValidationErrors(OptionsParseResult optionsParseResult) {
@@ -79,5 +99,6 @@ private ParameterException onValidationErrors(OptionsParseResult optionsParseRes
}

protected abstract String getType();
protected abstract String getSessionName();
protected abstract void configure(ActionRunner actionRunner, SimpleEvaluationContext context);
}
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/
package com.fortify.cli.ssc.artifact.cli.cmd.import_debricked;
package com.fortify.cli.common.cli.cmd.import_debricked;

import java.io.File;
import java.nio.file.StandardCopyOption;
@@ -24,85 +24,35 @@
import com.fasterxml.jackson.databind.util.RawValue;
import com.fortify.cli.common.http.proxy.helper.ProxyHelper;
import com.fortify.cli.common.json.JsonHelper;
import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.progress.helper.IProgressWriterI18n;
import com.fortify.cli.common.rest.unirest.GenericUnirestFactory;
import com.fortify.cli.common.rest.unirest.config.UnirestJsonHeaderConfigurer;
import com.fortify.cli.common.rest.unirest.config.UnirestUnexpectedHttpResponseConfigurer;
import com.fortify.cli.common.rest.unirest.config.UnirestUrlConfigConfigurer;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.ssc.artifact.cli.cmd.AbstractSSCArtifactUploadCommand;
import com.fortify.cli.ssc.artifact.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedAccessTokenCredentialOptions;
import com.fortify.cli.ssc.artifact.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedAuthOptions;
import com.fortify.cli.ssc.artifact.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedUserCredentialOptions;
import com.fortify.cli.common.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedAccessTokenCredentialOptions;
import com.fortify.cli.common.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedAuthOptions;
import com.fortify.cli.common.cli.cmd.import_debricked.DebrickedLoginOptions.DebrickedUserCredentialOptions;

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

@Command(name = "import-debricked")
public class SSCArtifactImportDebrickedCommand extends AbstractSSCArtifactUploadCommand {
@Mixin @Getter private OutputHelperMixins.TableNoQuery outputHelper;
@Mixin private DebrickedLoginOptions debrickedLoginOptions;

@Option(names = {"-e", "--engine-type"}, required = true, defaultValue = "DEBRICKED")
@Getter private String engineType;

@Option(names = {"-f", "--save-sbom-as"}, required = false)
private String fileName;

@Option(names = {"-r", "--repository"}, required = true)
private String repository;

@Option(names = {"-b", "--branch"}, required = true)
private String branch;

@Override
public boolean isSingular() {
return true;
}

@Override @SneakyThrows
protected File getFile() {
File sbomFile = null;
if ( StringUtils.isNotBlank(fileName) ) {
sbomFile = new File(fileName);
} else {
sbomFile = File.createTempFile("debricked", ".json");
sbomFile.deleteOnExit();
}
return sbomFile;
}

@Override
protected void preUpload(UnirestInstance unirest, IProgressWriterI18n progressWriter, File file) {
progressWriter.writeProgress("Status: Generating & downloading SBOM");
try ( var debrickedUnirest = GenericUnirestFactory.createUnirestInstance() ) {
downloadSbom(debrickedUnirest, file);
}
progressWriter.writeProgress("Status: Uploading SBOM to SSC");
}

@Override
protected void postUpload(UnirestInstance unirest, IProgressWriterI18n progressWriter, File file) {
if ( StringUtils.isBlank(fileName) ) {
file.delete();
}
progressWriter.writeProgress("Status: SBOM uploaded to SSC");
progressWriter.clearProgress();
}
public final class DebrickedHelper {

private Void downloadSbom(UnirestInstance debrickedUnirest, File file) {
private DebrickedLoginOptions debrickedLoginOptions;
private String repository;
private String branch;

public DebrickedHelper(DebrickedLoginOptions debrickedLoginOptions, String repository, String branch) {
this.debrickedLoginOptions = debrickedLoginOptions;
this.repository = repository;
this.branch = branch;
}

public final void downloadSbom(UnirestInstance debrickedUnirest, File file) {
configureDebrickedUnirest(debrickedUnirest);
String reportUuid = startSbomGeneration(debrickedUnirest);
waitSbomGeneration(debrickedUnirest, reportUuid, file);
return null;
}

private void configureDebrickedUnirest(UnirestInstance debrickedUnirest) {
public final void configureDebrickedUnirest(UnirestInstance debrickedUnirest) {
UnirestUnexpectedHttpResponseConfigurer.configure(debrickedUnirest);
DebrickedUrlConfigOptions debrickedUrlConfig = debrickedLoginOptions.getUrlConfigOptions();
UnirestUrlConfigConfigurer.configure(debrickedUnirest, debrickedUrlConfig);
@@ -113,7 +63,7 @@ private void configureDebrickedUnirest(UnirestInstance debrickedUnirest) {
debrickedUnirest.config().setDefaultHeader("Authorization", authHeader);
}

private String getDebrickedJwtToken(UnirestInstance debrickedUnirest) {
public final String getDebrickedJwtToken(UnirestInstance debrickedUnirest) {
DebrickedAuthOptions authOptions = debrickedLoginOptions.getAuthOptions();
DebrickedUserCredentialOptions userCredentialsOptions = authOptions.getUserCredentialsOptions();
DebrickedAccessTokenCredentialOptions tokenOptions = authOptions.getTokenOptions();
@@ -126,7 +76,7 @@ private String getDebrickedJwtToken(UnirestInstance debrickedUnirest) {
}
}

private String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedAccessTokenCredentialOptions tokenOptions) {
public final String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedAccessTokenCredentialOptions tokenOptions) {
return debrickedUnirest.post("/api/login_refresh")
.header("Content-Type", "application/x-www-form-urlencoded")
.field("refresh_token", new String(tokenOptions.getAccessToken()))
@@ -136,7 +86,7 @@ private String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedA
.asText();
}

private String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedUserCredentialOptions userCredentialsOptions) {
public final String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedUserCredentialOptions userCredentialsOptions) {
return debrickedUnirest.post("/api/login_check")
.header("Content-Type", "application/x-www-form-urlencoded")
.field("_username", userCredentialsOptions.getUser())
@@ -147,7 +97,7 @@ private String getDebrickedJwtToken(UnirestInstance debrickedUnirest, DebrickedU
.asText();
}

private String getRepositoryId(UnirestInstance debrickedUnirest) {
public final String getRepositoryId(UnirestInstance debrickedUnirest) {
try {
Integer.parseInt(repository);
return repository;
@@ -166,7 +116,7 @@ private String getRepositoryId(UnirestInstance debrickedUnirest) {
}
}

private String startSbomGeneration(UnirestInstance debrickedUnirest) {
public final String startSbomGeneration(UnirestInstance debrickedUnirest) {
ObjectNode body = new ObjectMapper().createObjectNode()
// TODO generate a proper ArrayNode
.putRawValue("repositoryIds", new RawValue("["+getRepositoryId(debrickedUnirest)+"]"))
@@ -184,7 +134,7 @@ private String startSbomGeneration(UnirestInstance debrickedUnirest) {
}

@SneakyThrows
private void waitSbomGeneration(UnirestInstance debrickedUnirest, String reportUuid, File outputFile) {
public final void waitSbomGeneration(UnirestInstance debrickedUnirest, String reportUuid, File outputFile) {
int status = 202;
while ( status==202 ) {
Thread.sleep(5000L);
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/
package com.fortify.cli.ssc.artifact.cli.cmd.import_debricked;
package com.fortify.cli.common.cli.cmd.import_debricked;

import com.fortify.cli.common.rest.unirest.config.IUserCredentialsConfig;

Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/
package com.fortify.cli.ssc.artifact.cli.cmd.import_debricked;
package com.fortify.cli.common.cli.cmd.import_debricked;

import com.fortify.cli.common.rest.cli.mixin.ConnectionConfigOptions;
import com.fortify.cli.common.rest.unirest.config.IUrlConfig;
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ public JSONDateTimeConverter(DateTimeFormatter fmtDateTime, ZoneId defaultZoneId
}

public static final DateTimeFormatter createDefaultDateTimeFormatter() {
return DateTimeFormatter.ofPattern("yyyy-MM-dd[['T'][' ']HH:mm:ss[.SSS][.SS]][ZZZZ][Z][XXX][XX][X]");
return DateTimeFormatter.ofPattern("yyyy-MM-dd[['T'][' ']HH:mm:ss[.SSS][.SS][.S]][ZZZZ][Z][XXX][XX][X]");
}

@Override
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@
package com.fortify.cli.common.progress.cli.mixin;

import com.fortify.cli.common.cli.mixin.CommandHelperMixin;
import com.fortify.cli.common.progress.cli.mixin.ProgressWriterTypeConverter.ProgressWriterTypeIterable;
import com.fortify.cli.common.progress.helper.IProgressWriterI18n;
import com.fortify.cli.common.progress.helper.ProgressWriterI18n;
import com.fortify.cli.common.progress.helper.ProgressWriterType;
@@ -24,7 +23,7 @@

public class ProgressWriterFactoryMixin {
@Mixin private CommandHelperMixin commandHelper;
@Getter @Option(names="--progress", defaultValue = "auto", completionCandidates = ProgressWriterTypeIterable.class, converter = ProgressWriterTypeConverter.class )
@Getter @Option(names="--progress", defaultValue = "auto")
private ProgressWriterType type;

public final IProgressWriterI18n create() {

This file was deleted.

Original file line number Diff line number Diff line change
@@ -28,6 +28,13 @@ public enum ProgressWriterType {
single_line(SingleLineProgressWriter::new),
ansi(AnsiProgressWriter::new);

@Override
public String toString() {
// Show and accept dashes instead of underscores when this
// enum is used in picocli options.
return name().replace('_', '-');
}

private final Supplier<IProgressWriter> factory;

public IProgressWriter create() {
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import com.fortify.cli.common.output.transform.IActionCommandResultSupplier;
import com.fortify.cli.common.session.cli.mixin.SessionNameMixin;
import com.fortify.cli.common.session.helper.ISessionDescriptor;
import com.fortify.cli.common.session.helper.SessionLogoutException;

import lombok.Getter;
import picocli.CommandLine.Mixin;
@@ -36,11 +37,15 @@ public JsonNode getJsonNode() {
result = sessionHelper.sessionSummaryAsObjectNode(sessionName);
try {
logout(sessionName, sessionHelper.get(sessionName, false));
} catch (Exception e){
LOG.warn("Logout failed");
LOG.debug("Exception details:", e);
} finally {
getSessionHelper().destroy(sessionName);
} catch (Exception e) {
if ( e instanceof SessionLogoutException && !((SessionLogoutException)e).isDestroySession() ) {
throw e;
} else {
LOG.warn("Logout failed");
LOG.debug("Exception details:", e);
getSessionHelper().destroy(sessionName);
}
}
}
return result;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.fortify.cli.common.session.helper;

import lombok.Getter;

public class SessionLogoutException extends RuntimeException {
private static final long serialVersionUID = 1L;
@Getter private boolean destroySession;
public SessionLogoutException(String message, boolean destroySession) {
this(message, null, destroySession);
}

public SessionLogoutException(Throwable cause, boolean destroySession) {
this(null, cause, destroySession);
}

public SessionLogoutException(String message, Throwable cause, boolean destroySession) {
super(message, cause);
this.destroySession = destroySession;
}
}
Loading
Loading