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

add non blocking pipeline creation flow #7241

Merged

Conversation

karthikjeeyar
Copy link
Contributor

@karthikjeeyar karthikjeeyar commented Nov 17, 2020

Fixes:
https://issues.redhat.com/browse/ODC-5048

Analysis / Root cause:
As a user, I'd like to still be able to finish my add flow even if the Pipeline Run cannot be created for the added Pipeline.

Solution Description:
Removed the pipelinerun creation request from the promise collection and added it in a try/catch block seperately.

Screen shots / Gifs for design review:

Before:
Blocks the add flow redirection and shows the error.
image

After:
Does not block the add flow redirection and suppresses the pipelinerun creation error
non-blocking-flow
Topology Sidebar
image

Unit test coverage report:
import-submit-utils.spec.ts
image
PipelineOverview.spec.tsx
image
pipeline-overview-utils.spec.ts
image

Test setup:

  1. Install Openshift pipeilnes operator with preview channel to get 1.2 operator
  2. Go to add from git flow
  3. Use dotnet image https://github.com/redhat-developer/s2i-dotnetcore-ex.git and choose dotnet builder image
  4. Add Pipeline option
  5. click on create button

Browser conformance:

  • Chrome
  • Firefox
  • Safari
  • Edge

cc: @andrewballantyne @bgliwa01 @openshift/team-devconsole-ux

@andrewballantyne
Copy link
Contributor

/assign

@andrewballantyne
Copy link
Contributor

Ah, I missed AC in the Story, apologizes for that @karthikjeeyar - If you look at the design, we have a need to show a message in the sidebar.

🤔 To do this, perhaps we find a way to add some form of sessionStorage (NOT localStorage) value when it fails?

The read-only sessionStorage property accesses a session Storage object for the current origin. sessionStorage is similar to localStorage; the difference is that while data in localStorage doesn't expire, data in sessionStorage is cleared when the page session ends.

Ref: MDN Docs

Our goal here is to just inform the user immediately, not to persist it indefinitely.

@karthikjeeyar
Copy link
Contributor Author

@andrewballantyne I have updated the code to show the alert in the sidebar, updated screenshots and added more tests.

@@ -1 +1,2 @@
export const TOPOLOGY_DISPLAY_FILTERS_LOCAL_STORAGE_KEY = `bridge/topology-display-filters`;
export const PIPELINE_RUN_AUTO_START_FAILED = `bridge/pipeline-run-auto-start-failed`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably should not be Pipeline specific if we are putting it in this file 🤔

Perhaps we just move it and put it in frontend/packages/pipelines-plugin/src/components/pipelines/const.ts

@@ -51,4 +53,10 @@ describe('Pipeline sidebar overview', () => {
const wrapper = shallow(<PipelineOverview {...props} />);
expect(wrapper.find(TriggerLastRunButton)).toHaveLength(1);
});

it('should show the pipeline not started Alert', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should also write one more test to make sure it's not there.

Comment on lines 60 to 69
expect(wrapper.find(PipelineOverviewAlert)).toHaveLength(1);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you "reset" it afterwards? That way if we want other tests, they are not impacted by this value.

Comment on lines 36 to 40
const [showAlert, setShowAlert] = React.useState(isPipelineNotStarted(name));

React.useEffect(() => {
setShowAlert(isPipelineNotStarted(name));
}, [name]);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we want to just live read it on each render... without the hooks. This way wouldn't need to worry so much about unsetting it when the user clicks the 'x'.

Suggested change
const [showAlert, setShowAlert] = React.useState(isPipelineNotStarted(name));
React.useEffect(() => {
setShowAlert(isPipelineNotStarted(name));
}, [name]);
const showAlert = isPipelineNotStarted(name);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed UseEffect but still using local state as the re render is not quick enough to remove the Alert.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah I see... my bad. 🤔

return (
<>
<SidebarSectionHeading text={PipelineRunModel.labelPlural}>
{showAlert && (
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{showAlert && (
{(showAlert && pipelineRuns.length === 0) && (

If they start up a Pipeline Run we don't want to show it.

Comment on lines 15 to 40
export const setPipelineNotStarted = (pipelineName: string): void => {
if (!pipelineName) return;
const pipelineList = getNotStartedPipelines();
if (pipelineList.length === 0 || !pipelineList.includes(pipelineName)) {
pipelineList.push(pipelineName);
}
sessionStorage.setItem(PIPELINE_RUN_AUTO_START_FAILED, JSON.stringify(pipelineList));
};
Copy link
Contributor

Choose a reason for hiding this comment

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

We want to hold onto the namespace as well... if you just do name, I could switch between projects and get unexpected results.

Plus you probably want to only write it back out when you modify it... no need to write the same value you got back to the storage if it didn't change.

Suggested change
export const setPipelineNotStarted = (pipelineName: string): void => {
if (!pipelineName) return;
const pipelineList = getNotStartedPipelines();
if (pipelineList.length === 0 || !pipelineList.includes(pipelineName)) {
pipelineList.push(pipelineName);
}
sessionStorage.setItem(PIPELINE_RUN_AUTO_START_FAILED, JSON.stringify(pipelineList));
};
export const setPipelineNotStarted = (namespace: string, pipelineName: string): void => {
if (!pipelineName || !namespace) return;
const pipelineData = getNotStartedPipelines();
if (!pipelineData[namespace]) {
pipelineData[namespace] = [];
}
if (!pipelineData[namespace].includes(pipelineName)) {
pipelineData[namespace].push(pipelineName);
sessionStorage.setItem(PIPELINE_RUN_AUTO_START_FAILED, JSON.stringify(pipelineData));
}
};

import { PIPELINE_RUN_AUTO_START_FAILED } from '@console/dev-console/src/components/topology/redux/const';

export const getNotStartedPipelines = () => {
return JSON.parse(sessionStorage.getItem(PIPELINE_RUN_AUTO_START_FAILED) ?? '[]');
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on my last comment... needs to be an object

Comment on lines 10 to 11
export const removePipelineNotStarted = (pipelineName: string): void => {
const newList = getNotStartedPipelines().filter((pName) => pName !== pipelineName);
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on my last(last) comment... need namespace 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.

@andrewballantyne Updated the code to store/remove a namespaced session object.

@@ -31,9 +33,20 @@ const PipelinesOverview: React.FC<PipelinesOverviewProps> = ({
const {
metadata: { name, namespace },
} = pipeline;
const [showAlert, setShowAlert] = React.useState(isPipelineNotStarted(name, namespace));
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not reactive 😞

I'll need to do some investigation into why we can't just use it in the render.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay, I see what is happening here... yeah your original solution made more sense. I'm not sure if we can entirely base our data on the sessionStorage 🤔 (which was my original reason for my suggestion)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think we can't get a "single state" of storage here... which is unfortunately. Okay, reset it back to the useEffect hook and we should be good to go.

  const [showAlert, setShowAlert] = React.useState(isPipelineNotStarted(name, namespace));

  React.useEffect(() => {
    setShowAlert(isPipelineNotStarted(name, namespace));
  }, [name, namespace]);

Sorry for this round-about solution... you had it right the first time.

Copy link
Contributor

@andrewballantyne andrewballantyne left a comment

Choose a reason for hiding this comment

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

Just need to rebase and reimplement the hook @karthikjeeyar - Get a LGTM from someone on the team or if I see the push I'll give it. Thanks!

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 24, 2020
@karthikjeeyar
Copy link
Contributor Author

Rebased and added the hook back.

Copy link
Contributor

@andrewballantyne andrewballantyne left a comment

Choose a reason for hiding this comment

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

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Nov 25, 2020
@openshift-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andrewballantyne, karthikjeeyar

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. component/dev-console Related to dev-console lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants