Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Release Engineering
Public
distrobuild
Commits
cb19eb49
Commit
cb19eb49
authored
Feb 25, 2021
by
Mustafa Gezen
🏗
Browse files
restructure before oidc
parent
f132a6d3
Changes
11
Hide whitespace changes
Inline
Side-by-side
distrobuild/app.py
View file @
cb19eb49
...
...
@@ -28,6 +28,7 @@ templates = Jinja2Templates(directory="ui/dist/templates")
async
def
serve_frontend
(
request
:
Request
):
return
templates
.
TemplateResponse
(
"index.html"
,
{
"request"
:
request
,
"distribution"
:
settings
.
settings
.
distribution
,
"koji_weburl"
:
session
.
koji_config
.
get
(
"weburl"
),
"gitlab_url"
:
f
"https://
{
settings
.
settings
.
gitlab_host
}{
settings
.
settings
.
repo_prefix
}
"
})
...
...
distrobuild/common/__init__.py
0 → 100644
View file @
cb19eb49
from
typing
import
List
,
Tuple
,
Optional
from
pydantic
import
BaseModel
,
validator
from
distrobuild.models
import
Import
,
Package
,
PackageModule
,
BuildStatus
class
BuildRequest
(
BaseModel
):
package_id
:
Optional
[
int
]
package_name
:
Optional
[
str
]
@
validator
(
'package_name'
)
def
validate
(
cls
,
package_name
,
values
):
if
(
not
values
.
get
(
'package_id'
)
and
not
package_name
)
or
(
values
.
get
(
'package_id'
)
and
package_name
):
raise
ValueError
(
'either package_id or package_name is required'
)
return
package_name
class
BatchBuildRequest
(
BaseModel
):
packages
:
List
[
BuildRequest
]
def
gen_body_filters
(
body_in
)
->
dict
:
body
=
BuildRequest
(
**
body_in
)
if
body
.
package_id
:
return
{
"id"
:
body
.
package_id
}
if
body
.
package_name
:
return
{
"name"
:
body
.
package_name
}
async
def
create_build_order
(
package
:
Package
)
->
List
[
Tuple
[
int
,
int
]]:
pkg_list
=
[]
if
package
.
is_package
:
package_import
=
await
Import
.
create
(
package_id
=
package
.
id
,
status
=
BuildStatus
.
QUEUED
,
version
=
8
)
pkg_list
.
append
((
package
.
id
,
package_import
.
id
))
if
package
.
is_module
:
subpackages
=
await
PackageModule
.
filter
(
module_parent_package_id
=
package
.
id
).
all
()
for
subpackage
in
subpackages
:
imports
=
await
Import
.
filter
(
package_id
=
subpackage
.
package_id
).
all
()
if
not
imports
or
len
(
imports
)
==
0
:
subpackage_package
=
await
Package
.
filter
(
id
=
subpackage
.
package_id
).
get
()
pkg_list
+=
await
create_build_order
(
subpackage_package
)
package_module_import
=
await
Import
.
create
(
package_id
=
package
.
id
,
status
=
BuildStatus
.
QUEUED
,
version
=
8
,
module
=
True
)
pkg_list
.
append
((
package
.
id
,
package_module_import
.
id
))
return
pkg_list
distrobuild/routes/build.py
View file @
cb19eb49
from
typing
import
Optional
,
List
,
Tuple
from
fastapi
import
APIRouter
,
Depends
,
HTTPException
from
fastapi.responses
import
PlainTextResponse
from
fastapi_pagination
import
Page
,
pagination_params
from
fastapi_pagination.ext.tortoise
import
paginate
from
pydantic
import
BaseModel
,
validator
from
distrobuild.common
import
BuildRequest
,
gen_body_filters
,
BatchBuildRequest
from
distrobuild.models
import
Build
,
Import
,
ImportCommit
,
Package
,
PackageModule
,
BuildStatus
from
distrobuild.serialize
import
Build_Pydantic
from
distrobuild_scheduler
import
build_package_task
from
distrobuild_scheduler
import
import_package_task
,
build_package_task
router
=
APIRouter
(
prefix
=
"/build"
)
class
BuildRequest
(
BaseModel
):
package_id
:
Optional
[
int
]
package_name
:
Optional
[
str
]
@
validator
(
'package_name'
)
def
validate
(
cls
,
package_name
,
values
):
if
(
not
values
.
get
(
'package_id'
)
and
not
package_name
)
or
(
values
.
get
(
'package_id'
)
and
package_name
):
raise
ValueError
(
'either package_id or package_name is required'
)
return
package_name
class
BatchBuildRequest
(
BaseModel
):
packages
:
List
[
BuildRequest
]
def
gen_body_filters
(
body_in
)
->
dict
:
body
=
BuildRequest
(
**
body_in
)
if
body
.
package_id
:
return
{
"id"
:
body
.
package_id
}
if
body
.
package_name
:
return
{
"name"
:
body
.
package_name
}
router
=
APIRouter
(
prefix
=
"/builds"
)
@
router
.
get
(
"/"
,
response_model
=
Page
[
Build_Pydantic
],
dependencies
=
[
Depends
(
pagination_params
)])
...
...
@@ -44,23 +15,6 @@ async def list_builds():
return
await
paginate
(
Build
.
all
().
order_by
(
'-created_at'
).
prefetch_related
(
"package"
))
# response_model causes some weird errors with Import. why?
# TODO: find out (removing response_model for now)
@
router
.
get
(
"/imports/"
,
dependencies
=
[
Depends
(
pagination_params
)])
async
def
list_imports
():
return
await
paginate
(
Import
.
all
().
order_by
(
'-created_at'
).
prefetch_related
(
"package"
))
@
router
.
get
(
"/imports/{import_id}/logs"
,
response_class
=
PlainTextResponse
)
async
def
get_import_logs
(
import_id
:
int
):
import_obj
=
await
Import
.
filter
(
id
=
import_id
).
get
()
try
:
with
open
(
f
"/tmp/import-
{
import_obj
.
id
}
.log"
)
as
f
:
return
f
.
read
()
except
FileNotFoundError
:
raise
HTTPException
(
404
,
detail
=
"import not started"
)
@
router
.
post
(
"/"
,
status_code
=
202
)
async
def
queue_build
(
body
:
BuildRequest
):
filters
=
gen_body_filters
(
body
)
...
...
@@ -90,46 +44,3 @@ async def batch_queue_build(body: BatchBuildRequest):
await
queue_build
(
build_request
)
return
{}
async
def
create_build_order
(
package
:
Package
)
->
List
[
Tuple
[
int
,
int
]]:
pkg_list
=
[]
if
package
.
is_package
:
package_import
=
await
Import
.
create
(
package_id
=
package
.
id
,
status
=
BuildStatus
.
QUEUED
,
version
=
8
)
pkg_list
.
append
((
package
.
id
,
package_import
.
id
))
if
package
.
is_module
:
subpackages
=
await
PackageModule
.
filter
(
module_parent_package_id
=
package
.
id
).
all
()
for
subpackage
in
subpackages
:
imports
=
await
Import
.
filter
(
package_id
=
subpackage
.
package_id
).
all
()
if
not
imports
or
len
(
imports
)
==
0
:
subpackage_package
=
await
Package
.
filter
(
id
=
subpackage
.
package_id
).
get
()
pkg_list
+=
await
create_build_order
(
subpackage_package
)
package_module_import
=
await
Import
.
create
(
package_id
=
package
.
id
,
status
=
BuildStatus
.
QUEUED
,
version
=
8
,
module
=
True
)
pkg_list
.
append
((
package
.
id
,
package_module_import
.
id
))
return
pkg_list
@
router
.
post
(
"/imports/"
,
status_code
=
202
)
async
def
import_package_route
(
body
:
BuildRequest
):
filters
=
gen_body_filters
(
body
)
package
=
await
Package
.
filter
(
**
filters
).
get_or_none
()
if
not
package
:
raise
HTTPException
(
404
,
detail
=
"package does not exist"
)
build_order
=
await
create_build_order
(
package
)
await
import_package_task
(
build_order
[
0
][
0
],
build_order
[
0
][
1
],
build_order
[
1
:])
return
{}
@
router
.
post
(
"/imports/batch"
,
status_code
=
202
)
async
def
batch_import_package
(
body
:
BatchBuildRequest
):
for
build_request
in
body
.
packages
:
await
import_package_route
(
build_request
)
return
{}
distrobuild/routes/import.py
0 → 100644
View file @
cb19eb49
from
fastapi
import
APIRouter
,
Depends
,
HTTPException
from
fastapi_pagination
import
pagination_params
from
fastapi_pagination.ext.tortoise
import
paginate
from
starlette.responses
import
PlainTextResponse
from
distrobuild.common
import
BuildRequest
,
gen_body_filters
,
BatchBuildRequest
,
create_build_order
from
distrobuild.models
import
Import
,
Package
from
distrobuild_scheduler
import
import_package_task
router
=
APIRouter
(
prefix
=
"/imports"
)
# response_model causes some weird errors with Import. why?
# TODO: find out (removing response_model for now)
@
router
.
get
(
"/"
,
dependencies
=
[
Depends
(
pagination_params
)])
async
def
list_imports
():
return
await
paginate
(
Import
.
all
().
order_by
(
'-created_at'
).
prefetch_related
(
"package"
))
@
router
.
get
(
"/{import_id}/logs"
,
response_class
=
PlainTextResponse
)
async
def
get_import_logs
(
import_id
:
int
):
import_obj
=
await
Import
.
filter
(
id
=
import_id
).
get_or_none
()
if
not
import_obj
:
raise
HTTPException
(
404
,
detail
=
"import does not exist"
)
try
:
with
open
(
f
"/tmp/import-
{
import_obj
.
id
}
.log"
)
as
f
:
return
f
.
read
()
except
FileNotFoundError
:
raise
HTTPException
(
412
,
detail
=
"import not started or log has expired"
)
@
router
.
post
(
"/"
,
status_code
=
202
)
async
def
import_package_route
(
body
:
BuildRequest
):
filters
=
gen_body_filters
(
body
)
package
=
await
Package
.
filter
(
**
filters
).
get_or_none
()
if
not
package
:
raise
HTTPException
(
404
,
detail
=
"package does not exist"
)
build_order
=
await
create_build_order
(
package
)
await
import_package_task
(
build_order
[
0
][
0
],
build_order
[
0
][
1
],
build_order
[
1
:])
return
{}
@
router
.
post
(
"/batch"
,
status_code
=
202
)
async
def
batch_import_package
(
body
:
BatchBuildRequest
):
for
build_request
in
body
.
packages
:
await
import_package_route
(
build_request
)
return
{}
distrobuild/settings.py
View file @
cb19eb49
...
...
@@ -3,6 +3,10 @@ from pydantic import BaseSettings
class
Settings
(
BaseSettings
):
bugs_api_key
:
str
gitlab_api_key
:
str
# srpmproc
gitlab_host
:
str
repo_prefix
:
str
storage_addr
:
str
...
...
@@ -10,8 +14,18 @@ class Settings(BaseSettings):
ssh_port
:
int
=
22
ssh_key_location
:
Optional
[
str
]
version
:
int
=
8
bugs_api_key
:
str
gitlab_api_key
:
str
no_storage_download
:
bool
=
False
no_storage_upload
:
bool
=
False
# oidc
oidc_issuer
:
str
oidc_client_id
:
str
oidc_client_secret
:
str
# appearance
distribution
:
str
=
"Rocky Linux"
# scheduler options
broker_url
:
str
routing_key
:
str
=
"distrobuild"
workers
:
int
=
10
...
...
distrobuild/srpmproc.py
View file @
cb19eb49
import
asyncio
import
json
from
typing
import
Optional
from
distrobuild.settings
import
settings
async
def
import_project
(
import_id
:
int
,
source_rpm
:
str
,
module_mode
:
bool
=
False
)
->
dict
:
async
def
import_project
(
import_id
:
int
,
source_rpm
:
str
,
module_mode
:
bool
=
False
,
single_tag
:
Optional
[
str
]
=
None
)
->
dict
:
upstream_prefix
=
f
"ssh://
{
settings
.
ssh_user
}
@
{
settings
.
gitlab_host
}
:
{
settings
.
ssh_port
}{
settings
.
repo_prefix
}
"
args
=
[
...
...
@@ -17,16 +20,26 @@ async def import_project(import_id: int, source_rpm: str, module_mode: bool = Fa
"--storage-addr"
,
settings
.
storage_addr
,
"--ssh-user"
,
settings
.
ssh_user
settings
.
ssh_user
,
]
if
settings
.
ssh_key_location
:
args
.
append
(
"--ssh-key-location"
)
args
.
append
(
settings
.
ssh_key_location
)
if
settings
.
no_storage_download
:
args
.
append
(
"--no-storage-download"
)
if
settings
.
no_storage_upload
:
args
.
append
(
"--no-storage-upload"
)
if
module_mode
:
args
.
append
(
"--module-mode"
)
if
single_tag
:
args
.
append
(
"--single-tag"
)
args
.
append
(
single_tag
)
f
=
open
(
f
"/tmp/import-
{
import_id
}
.log"
,
"w"
)
proc
=
await
asyncio
.
create_subprocess_exec
(
"srpmproc"
,
*
args
,
stdout
=
asyncio
.
subprocess
.
PIPE
,
stderr
=
f
)
...
...
ui/public/index.html
View file @
cb19eb49
...
...
@@ -8,7 +8,11 @@
<div
id=
"root"
></div>
<script>
window
.
SETTINGS
=
{
'
kojiWeburl
'
:
'
{{ koji_weburl}}
'
,
'
gitlabUrl
'
:
'
{{ gitlab_url }}
'
};
window
.
SETTINGS
=
{
'
kojiWeburl
'
:
'
{{ koji_weburl}}
'
,
'
gitlabUrl
'
:
'
{{ gitlab_url }}
'
,
'
distribution
'
:
'
{{ distribution }}
'
,
};
</script>
</body>
</html>
\ No newline at end of file
</html>
ui/src/components/Dashboard.tsx
View file @
cb19eb49
...
...
@@ -15,7 +15,7 @@ import { IPaginated, Axios, IImport, IBuild } from '../api';
import
Link
from
'
carbon-components-react/lib/components/UIShell/Link
'
;
const
importHeaders
=
[
'
ID
'
,
'
Initiated
'
,
'
Package
'
,
'
Status
'
,
''
];
const
buildHeaders
=
[
'
ID
'
,
'
Initiated
'
,
'
Package
'
,
'
Koji ID
'
,
'
Status
'
];
const
buildHeaders
=
[
'
ID
'
,
'
Initiated
'
,
'
Package
'
,
'
Status
'
,
''
];
const
statusToTag
=
(
status
)
=>
{
switch
(
status
)
{
...
...
@@ -38,13 +38,13 @@ export const Dashboard = () => {
React
.
useEffect
(()
=>
{
(
async
()
=>
{
const
[
err
,
res
]
=
await
to
(
Axios
.
get
(
'
/build/imports/?size=5
0
'
));
const
[
err
,
res
]
=
await
to
(
Axios
.
get
(
'
/build/imports/?size=5
'
));
if
(
res
)
{
setImports
(
res
.
data
);
}
})().
then
();
(
async
()
=>
{
const
[
err
,
res
]
=
await
to
(
Axios
.
get
(
'
/build/?size=5
0
'
));
const
[
err
,
res
]
=
await
to
(
Axios
.
get
(
'
/build/?size=5
'
));
if
(
res
)
{
setBuilds
(
res
.
data
);
}
...
...
@@ -78,6 +78,7 @@ export const Dashboard = () => {
{
new
Date
(
item
.
created_at
).
toLocaleString
()
}
</
TableCell
>
<
TableCell
>
{
item
.
package
.
name
}
</
TableCell
>
<
TableCell
>
{
statusToTag
(
item
.
status
)
}
</
TableCell
>
<
TableCell
>
<
Link
target
=
"_blank"
...
...
@@ -86,7 +87,6 @@ export const Dashboard = () => {
{
item
.
koji_id
}
</
Link
>
</
TableCell
>
<
TableCell
>
{
statusToTag
(
item
.
status
)
}
</
TableCell
>
</
TableRow
>
))
}
</
TableBody
>
...
...
ui/src/components/Root.tsx
View file @
cb19eb49
...
...
@@ -15,19 +15,25 @@ import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import
{
Packages
}
from
'
./Packages
'
;
import
{
Dashboard
}
from
'
./Dashboard
'
;
import
'
../styles/header.css
'
;
export
const
Root
=
()
=>
{
return
(
<
BrowserRouter
>
<
Header
aria
-
label
=
"Distrobuild"
>
<
HeaderName
element
=
{
Link
}
to
=
"/"
prefix
=
"Distrobuild"
>
[
Rocky Linux
]
[
{
window
.
SETTINGS
.
distribution
}
]
</
HeaderName
>
<
HeaderNavigation
>
<
HeaderMenuItem
element
=
{
Link
}
to
=
"/packages"
>
Packages
</
HeaderMenuItem
>
</
HeaderNavigation
>
<
HeaderGlobalBar
></
HeaderGlobalBar
>
<
HeaderNavigation
className
=
"right"
>
<
HeaderMenuItem
element
=
{
Link
}
to
=
"/packages"
>
Packages
</
HeaderMenuItem
>
</
HeaderNavigation
>
</
Header
>
<
div
style
=
{
{
marginTop
:
'
48px
'
}
}
>
<
Switch
>
...
...
ui/src/index.d.ts
View file @
cb19eb49
export
{};
interface
IState
{
authenticated
:
boolean
;
}
declare
global
{
interface
Window
{
SETTINGS
:
any
;
STATE
:
IState
;
}
}
ui/src/styles/header.css
0 → 100644
View file @
cb19eb49
.bx--header__nav.right
{
margin-left
:
auto
;
}
.bx--header__nav.right
::before
{
display
:
none
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment