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

fix: prevent reaching the congratulations screen during installation #1942

Merged
merged 5 commits into from
Jan 24, 2025
Merged
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
3 changes: 3 additions & 0 deletions rust/agama-lib/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub enum InstallationPhase {
Config,
/// Installation phase.
Install,
/// Finished installation phase.
Finish,
}

impl TryFrom<u32> for InstallationPhase {
Expand All @@ -77,6 +79,7 @@ impl TryFrom<u32> for InstallationPhase {
0 => Ok(Self::Startup),
1 => Ok(Self::Config),
2 => Ok(Self::Install),
3 => Ok(Self::Finish),
_ => Err(ServiceError::UnknownInstallationPhase(value)),
}
}
Expand Down
6 changes: 6 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jan 24 09:33:31 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

- Introduce a new installation phase "finish"
(gh#agama-project/agama#1616).

-------------------------------------------------------------------
Fri Jan 24 06:43:05 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

Expand Down
2 changes: 2 additions & 0 deletions service/lib/agama/dbus/clients/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def current_installation_phase
InstallationPhase::CONFIG
when DBus::Manager::INSTALL_PHASE
InstallationPhase::INSTALL
when DBus::Manager::FINISH_PHASE
InstallationPhase::FINISH
end
end

Expand Down
5 changes: 4 additions & 1 deletion service/lib/agama/dbus/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def initialize(backend, logger)
STARTUP_PHASE = 0
CONFIG_PHASE = 1
INSTALL_PHASE = 2
FINISH_PHASE = 3

dbus_interface MANAGER_INTERFACE do
dbus_method(:Probe, "") { config_phase }
Expand Down Expand Up @@ -111,7 +112,8 @@ def installation_phases
[
{ "id" => STARTUP_PHASE, "label" => "startup" },
{ "id" => CONFIG_PHASE, "label" => "config" },
{ "id" => INSTALL_PHASE, "label" => "install" }
{ "id" => INSTALL_PHASE, "label" => "install" },
{ "id" => FINISH_PHASE, "label" => "finish" }
]
end

Expand All @@ -122,6 +124,7 @@ def current_installation_phase
return STARTUP_PHASE if backend.installation_phase.startup?
return CONFIG_PHASE if backend.installation_phase.config?
return INSTALL_PHASE if backend.installation_phase.install?
return FINISH_PHASE if backend.installation_phase.finish?
end

# States whether installation runs on iguana
Expand Down
18 changes: 18 additions & 0 deletions service/lib/agama/installation_phase.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class InstallationPhase
STARTUP = "startup"
CONFIG = "config"
INSTALL = "install"
FINISH = "finish"

def initialize
@on_change_callbacks = []
Expand All @@ -53,6 +54,13 @@ def install?
value == INSTALL
end

# Whether the current installation phase value is finish
#
# @return [Boolean]
def finish?
value == FINISH
end

# Sets the installation phase value to startup
#
# @note Callbacks are called.
Expand Down Expand Up @@ -83,6 +91,16 @@ def install
self
end

# Sets the installation phase value to finish
#
# @note Callbacks are called.
#
# @return [self]
def finish
change_to(FINISH)
self
end

# Registers callbacks to be called when the installation phase value changes
#
# @param block [Proc]
Expand Down
1 change: 1 addition & 0 deletions service/lib/agama/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def install_phase
logger.error "Installation error: #{e.inspect}. Backtrace: #{e.backtrace}"
ensure
service_status.idle
installation_phase.finish
imobachgs marked this conversation as resolved.
Show resolved Hide resolved
finish_progress
end
# rubocop:enable Metrics/AbcSize
Expand Down
6 changes: 6 additions & 0 deletions service/package/rubygem-agama-yast.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jan 24 09:33:27 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

- Introduce a new installation phase "finish"
(gh#agama-project/agama#1616).

-------------------------------------------------------------------
Fri Jan 24 06:42:00 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

Expand Down
8 changes: 8 additions & 0 deletions service/test/agama/dbus/clients/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@
expect(subject.current_installation_phase).to eq(Agama::InstallationPhase::INSTALL)
end
end

context "when the current phase is finish" do
let(:current_phase) { Agama::DBus::Manager::FINISH_PHASE }

it "returns the install phase value" do
expect(subject.current_installation_phase).to eq(Agama::InstallationPhase::FINISH)
end
end
end

include_examples "service status"
Expand Down
7 changes: 6 additions & 1 deletion service/test/agama/dbus/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
describe "#installation_phases" do
it "includes all possible values for the installation phase" do
labels = subject.installation_phases.map { |i| i["label"] }
expect(labels).to contain_exactly("startup", "config", "install")
expect(labels).to contain_exactly("startup", "config", "install", "finish")
end

it "associates 'startup' with the id 0" do
Expand All @@ -174,6 +174,11 @@
install = subject.installation_phases.find { |i| i["label"] == "install" }
expect(install["id"]).to eq(described_class::INSTALL_PHASE)
end

it "associates 'finish' with the id 3" do
install = subject.installation_phases.find { |i| i["label"] == "finish" }
expect(install["id"]).to eq(described_class::FINISH_PHASE)
end
end

describe "#current_installation_phase" do
Expand Down
22 changes: 22 additions & 0 deletions service/test/agama/installation_phase_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@
end
end

describe "finish?" do
context "if the installation phase is finish" do
before do
subject.finish
end

it "returns true" do
expect(subject.finish?).to eq(true)
end
end

context "if the installation phase is not finish" do
before do
subject.config
end

it "returns false" do
expect(subject.finish?).to eq(false)
end
end
end

describe "#startup" do
it "sets the installation phase to startup" do
subject.startup
Expand Down
7 changes: 4 additions & 3 deletions service/test/agama/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# find current contact information at www.suse.com.

require_relative "../test_helper"
require_relative "./with_progress_examples"
require_relative "with_progress_examples"
imobachgs marked this conversation as resolved.
Show resolved Hide resolved
require "agama/manager"
require "agama/config"
require "agama/issue"
Expand Down Expand Up @@ -115,9 +115,10 @@
end

describe "#install_phase" do
it "sets the installation phase to install" do
it "sets the installation phase to install and later to finish" do
expect(subject.installation_phase).to receive(:install)
subject.install_phase
expect(subject.installation_phase.install?).to eq(true)
expect(subject.installation_phase.finish?).to eq(true)
end

it "calls #propose on proxy and software modules" do
Expand Down
6 changes: 6 additions & 0 deletions web/package/agama-web-ui.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jan 24 09:34:24 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

- Use the "finish" to decide whether to navigate to the
congratulations screen (gh#agama-project/agama#1616).

-------------------------------------------------------------------
Fri Jan 24 06:43:52 UTC 2025 - Imobach Gonzalez Sosa <[email protected]>

Expand Down
8 changes: 3 additions & 5 deletions web/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,9 @@ describe("App", () => {
});
});

describe("on the busy installation phase", () => {
describe("on the installation phase", () => {
beforeEach(() => {
mockClientStatus.phase = InstallationPhase.Install;
mockClientStatus.isBusy = true;
mockSelectedProduct = tumbleweed;
});

Expand All @@ -216,10 +215,9 @@ describe("App", () => {
});
});

describe("on the idle installation phase", () => {
describe("on the finish phase", () => {
beforeEach(() => {
mockClientStatus.phase = InstallationPhase.Install;
mockClientStatus.isBusy = false;
mockClientStatus.phase = InstallationPhase.Finish;
mockSelectedProduct = tumbleweed;
});

Expand Down
4 changes: 2 additions & 2 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ function App() {
const Content = () => {
if (error) return <ServerError />;

if (phase === InstallationPhase.Install && isBusy) {
if (phase === InstallationPhase.Install) {
return <Navigate to={ROOT.installationProgress} />;
}

if (phase === InstallationPhase.Install && !isBusy) {
if (phase === InstallationPhase.Finish) {
imobachgs marked this conversation as resolved.
Show resolved Hide resolved
return <Navigate to={ROOT.installationFinished} />;
}

Expand Down
2 changes: 1 addition & 1 deletion web/src/components/core/InstallationFinished.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { Encryption } from "~/api/storage/types/config";

jest.mock("~/queries/status", () => ({
...jest.requireActual("~/queries/status"),
useInstallerStatus: () => ({ isBusy: false, useIguana: false, phase: 2, canInstall: false }),
useInstallerStatus: () => ({ isBusy: false, useIguana: false, phase: 3, canInstall: false }),
}));

type storageConfigType = "guided" | "raw";
Expand Down
8 changes: 2 additions & 6 deletions web/src/components/core/InstallationFinished.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,13 @@ function usingTpm(config): boolean {
}

function InstallationFinished() {
const { phase, isBusy, useIguana } = useInstallerStatus({ suspense: true });
const { phase, useIguana } = useInstallerStatus({ suspense: true });
const config = useConfig();

if (phase !== InstallationPhase.Install) {
if (phase !== InstallationPhase.Finish) {
return <Navigate to={PATHS.root} />;
}

if (isBusy) {
return <Navigate to={PATHS.installationProgress} />;
}

return (
<Center>
<Grid hasGutter>
Expand Down
18 changes: 2 additions & 16 deletions web/src/components/core/InstallationProgress.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@ import { InstallationPhase } from "~/types/status";
import InstallationProgress from "./InstallationProgress";
import { ROOT } from "~/routes/paths";

let isBusy = false;
let phase = InstallationPhase.Install;
const mockInstallerStatusChanges = jest.fn();

jest.mock("~/components/core/ProgressReport", () => () => <div>ProgressReport Mock</div>);

jest.mock("~/queries/status", () => ({
...jest.requireActual("~/queries/status"),
useInstallerStatus: () => ({ isBusy, phase }),
useInstallerStatus: () => ({ phase }),
useInstallerStatusChanges: () => mockInstallerStatusChanges(),
}));

Expand All @@ -56,27 +55,14 @@ describe("InstallationProgress", () => {
});
});

describe("when installer in the installation phase and busy", () => {
describe("when installer in the installation phase", () => {
beforeEach(() => {
phase = InstallationPhase.Install;
isBusy = true;
});

it("renders progress report", () => {
installerRender(<InstallationProgress />);
screen.getByText("ProgressReport Mock");
});
});

describe("when installer in the installation phase but not busy", () => {
beforeEach(() => {
phase = InstallationPhase.Install;
isBusy = false;
});

it("redirect to installation finished path", async () => {
installerRender(<InstallationProgress />);
await screen.findByText(`Navigating to ${ROOT.installationFinished}`);
});
});
});
6 changes: 1 addition & 5 deletions web/src/components/core/InstallationProgress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,13 @@ import { Navigate } from "react-router-dom";
import { useInstallerStatus, useInstallerStatusChanges } from "~/queries/status";

function InstallationProgress() {
const { isBusy, phase } = useInstallerStatus({ suspense: true });
const { phase } = useInstallerStatus({ suspense: true });
useInstallerStatusChanges();

if (phase !== InstallationPhase.Install) {
return <Navigate to={PATHS.root} replace />;
}

if (!isBusy) {
return <Navigate to={PATHS.installationFinished} replace />;
}

return <ProgressReport title={_("Installing the system, please wait...")} />;
}

Expand Down
1 change: 1 addition & 0 deletions web/src/types/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum InstallationPhase {
Startup = 0,
Config = 1,
Install = 2,
Finish = 3,
}

/*
Expand Down
Loading