Skip to content

Commit

Permalink
✨ Support disable image builder
Browse files Browse the repository at this point in the history
  • Loading branch information
tosone committed Jan 4, 2024
1 parent 31ade5c commit ad8fb05
Show file tree
Hide file tree
Showing 9 changed files with 348 additions and 212 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/go-sigma/sigma

go 1.21.4
go 1.21.5

require (
code.gitea.io/sdk/gitea v0.17.1
Expand Down
26 changes: 15 additions & 11 deletions pkg/handlers/builders/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/labstack/echo/v4"

"github.com/go-sigma/sigma/pkg/configs"
"github.com/go-sigma/sigma/pkg/consts"
"github.com/go-sigma/sigma/pkg/dal/dao"
"github.com/go-sigma/sigma/pkg/handlers"
Expand Down Expand Up @@ -119,18 +120,21 @@ type factory struct{}
func (f factory) Initialize(e *echo.Echo) error {
handler := handlerNew()

builderGroup := e.Group(consts.APIV1+"/namespaces/:namespace_id/repositories/:repository_id/builders",
middlewares.AuthWithConfig(middlewares.AuthConfig{}))
builderGroup.POST("/", handler.CreateBuilder)
builderGroup.PUT("/:builder_id", handler.UpdateBuilder)
builderGroup.GET("/:builder_id/runners/", handler.ListRunners)
builderGroup.POST("/:builder_id/runners/run", handler.PostRunnerRun)
builderGroup.GET("/:builder_id/runners/:runner_id", handler.GetRunner)
builderGroup.GET("/:builder_id/runners/:runner_id/stop", handler.GetRunnerStop)
builderGroup.GET("/:builder_id/runners/:runner_id/rerun", handler.GetRunnerRerun)
config := configs.GetConfiguration()
if config.Daemon.Builder.Enabled {
builderGroup := e.Group(consts.APIV1+"/namespaces/:namespace_id/repositories/:repository_id/builders",
middlewares.AuthWithConfig(middlewares.AuthConfig{}))
builderGroup.POST("/", handler.CreateBuilder)
builderGroup.PUT("/:builder_id", handler.UpdateBuilder)
builderGroup.GET("/:builder_id/runners/", handler.ListRunners)
builderGroup.POST("/:builder_id/runners/run", handler.PostRunnerRun)
builderGroup.GET("/:builder_id/runners/:runner_id", handler.GetRunner)
builderGroup.GET("/:builder_id/runners/:runner_id/stop", handler.GetRunnerStop)
builderGroup.GET("/:builder_id/runners/:runner_id/rerun", handler.GetRunnerRerun)

builderWithoutAuthGroup := e.Group(consts.APIV1 + "/namespaces/:namespace_id/repositories/:repository_id/builders")
builderWithoutAuthGroup.GET("/:builder_id/runners/:runner_id/log", handler.GetRunnerLog)
builderWithoutAuthGroup := e.Group(consts.APIV1 + "/namespaces/:namespace_id/repositories/:repository_id/builders")
builderWithoutAuthGroup.GET("/:builder_id/runners/:runner_id/log", handler.GetRunnerLog)
}
return nil
}

Expand Down
24 changes: 14 additions & 10 deletions pkg/handlers/coderepos/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/labstack/echo/v4"

"github.com/go-sigma/sigma/pkg/configs"
"github.com/go-sigma/sigma/pkg/consts"
"github.com/go-sigma/sigma/pkg/dal/dao"
"github.com/go-sigma/sigma/pkg/handlers"
Expand Down Expand Up @@ -110,17 +111,20 @@ type factory struct{}

// Initialize initializes the namespace handlers
func (f factory) Initialize(e *echo.Echo) error {
codereposGroup := e.Group(consts.APIV1+"/coderepos", middlewares.AuthWithConfig(middlewares.AuthConfig{}))

codeRepositoryHandler := handlerNew()
codereposGroup.GET("/providers", codeRepositoryHandler.Providers)
codereposGroup.GET("/:provider", codeRepositoryHandler.List)
codereposGroup.GET("/:provider/repos/:id", codeRepositoryHandler.Get)
codereposGroup.GET("/:provider/user3rdparty", codeRepositoryHandler.User3rdParty)
codereposGroup.GET("/:provider/resync", codeRepositoryHandler.Resync)
codereposGroup.GET("/:provider/owners", codeRepositoryHandler.ListOwners)
codereposGroup.GET("/:provider/repos/:id/branches", codeRepositoryHandler.ListBranches)
codereposGroup.GET("/:provider/repos/:id/branches/:name", codeRepositoryHandler.GetBranch)

config := configs.GetConfiguration()
if config.Daemon.Builder.Enabled {
codereposGroup := e.Group(consts.APIV1+"/coderepos", middlewares.AuthWithConfig(middlewares.AuthConfig{}))
codereposGroup.GET("/providers", codeRepositoryHandler.Providers)
codereposGroup.GET("/:provider", codeRepositoryHandler.List)
codereposGroup.GET("/:provider/repos/:id", codeRepositoryHandler.Get)
codereposGroup.GET("/:provider/user3rdparty", codeRepositoryHandler.User3rdParty)
codereposGroup.GET("/:provider/resync", codeRepositoryHandler.Resync)
codereposGroup.GET("/:provider/owners", codeRepositoryHandler.ListOwners)
codereposGroup.GET("/:provider/repos/:id/branches", codeRepositoryHandler.ListBranches)
codereposGroup.GET("/:provider/repos/:id/branches/:name", codeRepositoryHandler.GetBranch)
}
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/line-clamp": "^0.4.4",
"@tailwindcss/typography": "^0.5.10",
"axios": "^1.6.3",
"axios": "^1.6.4",
"bytemd": "^1.21.0",
"cron-parser": "^4.9.0",
"csstype": "^3.1.3",
Expand All @@ -40,12 +40,12 @@
"xterm-addon-fit": "^0.8.0"
},
"devDependencies": {
"@types/node": "^20.10.5",
"@types/node": "^20.10.6",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.16",
"cssnano": "^6.0.2",
"cssnano": "^6.0.3",
"json-server": "^0.17.4",
"postcss": "^8.4.32",
"tailwindcss": "^3.4.0",
Expand Down
165 changes: 96 additions & 69 deletions web/src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ import { Link, useSearchParams, useNavigate } from 'react-router-dom';
import Regex from "../../utils/regex";
import Toast from "../../components/Notification";
import { setupAutoRefreshToken, teardownAutoRefreshToken } from "../../utils/refreshToken"
import { INamespaceItem, INamespaceList, IHTTPError, IUserSelf, IEndpoint, IVersion } from "../../interfaces";
import { INamespaceItem, INamespaceList, IHTTPError, IUserSelf, IEndpoint, IVersion, ISystemConfig } from "../../interfaces";

export default function ({ localServer, item, namespace, repository, tag, selfClick }: { localServer: string, item: string, namespace?: string, repository?: string, tag?: string, selfClick?: boolean }) {
const [showProfileMenu, setShowProfileMenu] = useState(false);
const [menuActive, setMenuActive] = useState(item === "" ? "home" : item);
const navigate = useNavigate();

const [searchParams] = useSearchParams();
const isAnonymous = (searchParams.get('anonymous') || "false") === "true";
const [isAnonymous, setIsAnonymous] = useState(false);

const ref = useRef<HTMLDivElement>() as React.MutableRefObject<HTMLDivElement>;
useClickAway(ref, () => {
Expand All @@ -48,35 +47,57 @@ export default function ({ localServer, item, namespace, repository, tag, selfCl

// get user info
useEffect(() => {
if (!isAnonymous) {
axios.get(localServer + "/api/v1/users/self").then(response => {
if (response.status === 200) {
const user = response.data as IUserSelf;
setUsername(user.username);
setEmail(user.email);
setUserID(user.id);
} else {
const errorcode = response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
axios.get(localServer + "/api/v1/users/self").then(response => {
if (response.status === 200) {
const user = response.data as IUserSelf;
setUsername(user.username);
setEmail(user.email);
setUserID(user.id);
if (user.role === "Anonymous") {
setIsAnonymous(true);
}
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
} else {
const errorcode = response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
setupAutoRefreshToken(localServer, logout);
const visibilitychangeHandler = () => {
if (document.hidden) {
teardownAutoRefreshToken();
} else {
setupAutoRefreshToken(localServer, logout);
}
}
document.addEventListener("visibilitychange", visibilitychangeHandler);
return () => {
document.removeEventListener("visibilitychange", visibilitychangeHandler);
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
setupAutoRefreshToken(localServer, logout);
const visibilitychangeHandler = () => {
if (document.hidden) {
teardownAutoRefreshToken();
} else {
setupAutoRefreshToken(localServer, logout);
}
}
}, [refresh])
document.addEventListener("visibilitychange", visibilitychangeHandler);
return () => {
document.removeEventListener("visibilitychange", visibilitychangeHandler);
}
}, [refresh]);

const [config, setConfig] = useState<ISystemConfig>({
daemon: {
builder: true
}
} as ISystemConfig)

useEffect(() => {
axios.get(localServer + "/api/v1/systems/config").then(response => {
if (response.status === 200) {
const config = response.data as ISystemConfig;
setConfig(config);
} else {
const errorcode = response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
}
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
}, []);

const [hotNamespaceTotal, setHotNamespaceTotal] = useState(0);
const [hotNamespaceList, setHotNamespaceList] = useState<INamespaceItem[]>([]);
Expand All @@ -101,19 +122,17 @@ export default function ({ localServer, item, namespace, repository, tag, selfCl
}, [])

const logout = () => {
if (!isAnonymous) {
let tokens: string[] = [localStorage.getItem("token") || "", localStorage.getItem("refresh_token") || ""];
axios.post(localServer + "/api/v1/users/logout", {
tokens: tokens
}).then(response => {
localStorage.removeItem("token");
localStorage.removeItem("refresh_token");
navigate("/login");
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
}
let tokens: string[] = [localStorage.getItem("token") || "", localStorage.getItem("refresh_token") || ""];
axios.post(localServer + "/api/v1/users/logout", {
tokens: tokens
}).then(response => {
localStorage.removeItem("token");
localStorage.removeItem("refresh_token");
navigate("/login");
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
}

const [endpoint, setEndpoint] = useState("");
Expand Down Expand Up @@ -268,7 +287,7 @@ export default function ({ localServer, item, namespace, repository, tag, selfCl
</div>
<div className="h-0 flex-1 flex flex-col overflow-y-auto">
{
!isAnonymous && (
(
<div className="px-3 mt-6 relative inline-block text-left" ref={ref}>
<div>
<button type="button" className="group w-full bg-gray-100 rounded-md px-3.5 py-2 text-sm font-medium text-gray-700 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-purple-500" onClick={() => { setShowProfileMenu(!showProfileMenu) }}>
Expand All @@ -286,23 +305,27 @@ export default function ({ localServer, item, namespace, repository, tag, selfCl
</div>
<div className={showProfileMenu ? "" : "hidden"}>
<div className="z-10 mx-3 origin-top absolute right-0 left-0 mt-1 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 divide-y divide-gray-200">
<div className="py-1">
<div className="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={e => {
setShowProfileMenu(false);
setCreateRunnerModal(true);
setUsernameInput(username);
setEmailInput(email);
}}
>Update profile</div>
<div className="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={e => {
setUpdatePasswordModal(true);
setPasswordInput("");
setRepeatPasswordInput("");
}}
>Reset password</div>
</div>
{
!isAnonymous && (
<div className="py-1">
<div className="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={e => {
setShowProfileMenu(false);
setCreateRunnerModal(true);
setUsernameInput(username);
setEmailInput(email);
}}
>Update profile</div>
<div className="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={e => {
setUpdatePasswordModal(true);
setPasswordInput("");
setRepeatPasswordInput("");
}}
>Reset password</div>
</div>
)
}
<div className="py-1">
<div className="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" onClick={logout}>Logout</div>
</div>
Expand Down Expand Up @@ -392,17 +415,21 @@ export default function ({ localServer, item, namespace, repository, tag, selfCl
</Link>
)
}
<Link to={`/coderepos`} className={`text-gray-700 group flex items-center px-2 py-2 text-sm font-medium rounded-md ${menuActive === "coderepos" ? "bg-gray-100" : "hover:bg-gray-50 text-gray-700"}`} onClick={e => {
setMenuActive("coderepos");
item === "coderepos" && e.preventDefault();
}}>
<span className="text-gray-400 mr-3 h-6 w-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3 0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7m0 0a3 3 0 01-3 3m0 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm-3 6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
</svg>
</span>
Code Repository
</Link>
{
!isAnonymous && config.daemon.builder && (
<Link to={`/coderepos`} className={`text-gray-700 group flex items-center px-2 py-2 text-sm font-medium rounded-md ${menuActive === "coderepos" ? "bg-gray-100" : "hover:bg-gray-50 text-gray-700"}`} onClick={e => {
setMenuActive("coderepos");
item === "coderepos" && e.preventDefault();
}}>
<span className="text-gray-400 mr-3 h-6 w-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3 0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7m0 0a3 3 0 01-3 3m0 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm-3 6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
</svg>
</span>
Code Repository
</Link>
)
}
{
!isAnonymous && (
<Link to={`/settings`} className={`text-gray-700 group flex items-center px-2 py-2 text-sm font-medium rounded-md ${menuActive === "settings" ? "bg-gray-100" : "hover:bg-gray-50 text-gray-700"}`} onClick={e => {
Expand Down
6 changes: 6 additions & 0 deletions web/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,9 @@ export interface INamespaceRoleItem {
created_at: string;
updated_at: string;
}

export interface ISystemConfig {
daemon: {
builder: boolean;
};
}
39 changes: 32 additions & 7 deletions web/src/pages/Repository/Summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { Link, useSearchParams, useParams } from "react-router-dom";
import Menu from "../../components/Menu";
import Header from "../../components/Header";
import Toast from "../../components/Notification";
import { IRepositoryItem, IHTTPError } from "../../interfaces";
import { IRepositoryItem, IHTTPError, ISystemConfig } from "../../interfaces";

import "./index.css";

Expand Down Expand Up @@ -81,6 +81,27 @@ export default function ({ localServer }: { localServer: string }) {
})
}

const [config, setConfig] = useState<ISystemConfig>({
daemon: {
builder: false
}
} as ISystemConfig);

useEffect(() => {
axios.get(localServer + "/api/v1/systems/config").then(response => {
if (response.status === 200) {
const config = response.data as ISystemConfig;
setConfig(config);
} else {
const errorcode = response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
}
}).catch(error => {
const errorcode = error.response.data as IHTTPError;
Toast({ level: "warning", title: errorcode.title, message: errorcode.description });
});
}, []);

return (
<>
<HelmetProvider>
Expand All @@ -101,12 +122,16 @@ export default function ({ localServer }: { localServer: string }) {
>
Summary
</span>
<Link
to={`/namespaces/${namespace}/repository/runners?repository=${repositoryObj.name}&repository_id=${repository_id}&namespace_id=${namespaceId}`}
className="inline-flex items-center border-b border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 capitalize"
>
Builder
</Link>
{
config.daemon.builder && (
<Link
to={`/namespaces/${namespace}/repository/runners?repository=${repositoryObj.name}&repository_id=${repository_id}&namespace_id=${namespaceId}`}
className="inline-flex items-center border-b border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 capitalize"
>
Builder
</Link>
)
}
<Link
to={`/namespaces/${namespace}/repository/tags?repository=${repositoryObj.name}&repository_id=${repository_id}`}
className="inline-flex items-center border-b border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 capitalize"
Expand Down
Loading

0 comments on commit ad8fb05

Please sign in to comment.