who needs rust anyway

This commit is contained in:
ptrcnull 2022-07-24 01:44:47 +02:00
parent 378ae1fdbc
commit 608159fd2b
33 changed files with 94 additions and 4912 deletions

9
LICENSE.md Normal file
View file

@ -0,0 +1,9 @@
Copyright 2022 ptrcnull
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,9 +1,11 @@
# gitlab-jobs
quick and dirty app to show all jobs from gitlab account on one screen
quick and dirty web app to show all jobs from gitlab account on one screen
issue tracker: https://git.ddd.rip/ptrcnull/gitlab-jobs/issues
try it out: https://ptrc.pl/gitlab-jobs/
## usage
~~idk figure it out~~

76
common.js Normal file
View file

@ -0,0 +1,76 @@
// native functions
// const invoke = window.__TAURI__.invoke
// const sendNotification = window.__TAURI__.notification.sendNotification
// const isLoggedIn = () => invoke('is_logged_in')
// const logIn = token => invoke('log_in', { token })
// const listRunners = () => invoke('list_runners')
// const listJobsForRunner = id => invoke('list_jobs_for_runner', { runnerId: id })
// const retryJob = (projectId, jobId) => invoke('retry_job', { projectId, jobId })
const API = 'https://gitlab.com/api/v4'
const jsonify = res => res.json()
const isLoggedIn = async () => {
const token = localStorage.getItem('gitlab-jobs-token')
// TODO: check stuff?
return token != null
}
const logIn = async token => {
const res = await fetch(API + '/user', {
headers: {
'PRIVATE-TOKEN': token
}
})
if (res.ok) {
localStorage.setItem('gitlab-jobs-token', token)
return true
}
return false
}
const headers = () => ({ headers: { 'PRIVATE-TOKEN': localStorage.getItem('gitlab-jobs-token') } })
const listRunners = () => fetch(API + '/runners', headers()).then(jsonify)
const listJobsForRunner = id => fetch(API + `/runners/${id}/jobs?order_by=id`, headers()).then(jsonify)
const retryJob = () => {}
const sendNotification = async ({ title, body }) => {
if (Notification.permission !== 'granted') {
const result = await Notification.requestPermission()
if (result !== 'granted') {
console.error('did not get permission :(', result)
return
}
}
return new Notification(title, { body })
}
// shit helpers
const $ = (...args) => {
if (args.length === 1) return document.querySelector(args[0])
return args[0].querySelector(args[1])
}
const $$ = document.querySelectorAll.bind(document)
function initTemplate(template, data) {
const fragment = template.cloneNode(true)
Object.keys(data).forEach(key => {
const field = fragment.querySelector('.' + key)
const value = data[key]
if (typeof value === 'string') {
field.textContent = value
} else if (typeof value === 'number') {
field.textContent = value.toString()
} else if (value.link) {
const a = field.querySelector('a')
a.href = value.link
a.textContent = value.text
}
})
return fragment
}

32
dist/common.js vendored
View file

@ -1,32 +0,0 @@
// native functions
const invoke = window.__TAURI__.invoke
const isLoggedIn = () => invoke('is_logged_in')
const logIn = token => invoke('log_in', { token })
const listRunners = () => invoke('list_runners')
const listJobsForRunner = id => invoke('list_jobs_for_runner', { runnerId: id })
const retryJob = (projectId, jobId) => invoke('retry_job', { projectId, jobId })
// shit helpers
const $ = (...args) => {
if (args.length === 1) return document.querySelector(args[0])
return args[0].querySelector(args[1])
}
const $$ = document.querySelectorAll.bind(document)
function initTemplate(template, data) {
const fragment = template.cloneNode(true)
Object.keys(data).forEach(key => {
const field = fragment.querySelector('.' + key)
const value = data[key]
if (typeof value === 'string') {
field.textContent = value
} else if (typeof value === 'number') {
field.textContent = value.toString()
} else if (value.link) {
const a = field.querySelector('a')
a.href = value.link
a.textContent = value.text
}
})
return fragment
}

310
package-lock.json generated
View file

@ -1,310 +0,0 @@
{
"name": "gitlab-jobs-tauri",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "gitlab-jobs-tauri",
"dependencies": {
"@tauri-apps/api": "^1.0.1"
},
"devDependencies": {
"@tauri-apps/cli": "^1.0.0"
}
},
"node_modules/@tauri-apps/api": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.0.1.tgz",
"integrity": "sha512-TJwKkXxtF52kN9Auu5TWD2AE4ssqTrsfdpIrixYwRb3gQ/FuYwvZjrMc9weYpgsW2cMhVNkvKgneNXF/4n04lw==",
"dependencies": {
"type-fest": "2.13.1"
},
"engines": {
"node": ">= 12.22.0",
"npm": ">= 6.6.0",
"yarn": ">= 1.19.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"node_modules/@tauri-apps/cli": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.0.0.tgz",
"integrity": "sha512-4eHnk3p0xnCXd9Zel3kLvdiiSURnN98GMFvWUAdirm5AjyOjcx8TIET/jqRYmYKE5yd+LMQqYMUfHRwA6JJUkg==",
"dev": true,
"bin": {
"tauri": "tauri.js"
},
"engines": {
"node": ">= 10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
},
"optionalDependencies": {
"@tauri-apps/cli-darwin-arm64": "1.0.0",
"@tauri-apps/cli-darwin-x64": "1.0.0",
"@tauri-apps/cli-linux-arm-gnueabihf": "1.0.0",
"@tauri-apps/cli-linux-arm64-gnu": "1.0.0",
"@tauri-apps/cli-linux-arm64-musl": "1.0.0",
"@tauri-apps/cli-linux-x64-gnu": "1.0.0",
"@tauri-apps/cli-linux-x64-musl": "1.0.0",
"@tauri-apps/cli-win32-ia32-msvc": "1.0.0",
"@tauri-apps/cli-win32-x64-msvc": "1.0.0"
}
},
"node_modules/@tauri-apps/cli-darwin-arm64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0.tgz",
"integrity": "sha512-0ryomgLjdpylXypMPVXLU3PZCde3Sw5nwN4coUhBcHPBLFRb8QPet+nweVK/HiZ3mxg8WeIazvpx2s8hS0l2GQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-darwin-x64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0.tgz",
"integrity": "sha512-oejvYUT4dEfzBi+FWMj+CMz4cZ6C2gEFHrUtKVLdTXr8Flj5UTwdB1YPGQjiOqk73LOI7cB/vXxb9DZT+Lrxgg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0.tgz",
"integrity": "sha512-yAu78v8TeXNx/ETS5F2G2Uw/HX+LQvZkX94zNiqFsAj7snfWI/IqSUM52OBrdh/D0EC9NCdjUJ7Vuo32uxf7tg==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0.tgz",
"integrity": "sha512-YFUN/S58AN317njAynzcQ+EHhRsCDXqmp5g9Oiqmcdg1vU7fPWZivVLc1WHz+0037C7JnsX5PtKpNYewP/+Oqw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0.tgz",
"integrity": "sha512-al+TxMGoNVikEvRQfMyYE/mdjUcUNMo5brkCIAb+fL4rWQlAhAnYVzmg/rM8N4nhdXm1MOaYAagQmxr8898dNA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0.tgz",
"integrity": "sha512-KQmYlYyGpn6/2kSl9QivWG6EIepm6PJd57e6IKmYwAyNhLr2XfGl1CLuocUQQgO+jprjT70HXp+MXD0tcB0+Sw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-linux-x64-musl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0.tgz",
"integrity": "sha512-Qpaq5lZz569Aea6jfrRchgfEJaOrfLpCRBATcF8CJFFwVKmfCUcoV+MxbCIW30Zqw5Y06njC/ffa3261AV/ZIQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0.tgz",
"integrity": "sha512-e2DzFqEMI+s+gv14UupdI91gPxTbUJTbbfQlTHdQlOsTk4HEZTsh+ibAYBcCLAaMRW38NEsFlAUe1lQA0iRu/w==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0.tgz",
"integrity": "sha512-lWSs90pJeQX+L31IqIzmRhwLayEeyTh7mga0AxX8G868hvdLtcXCQA/rKoFtGdVLuHAx4+M+CBF5SMYb76xGYA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/type-fest": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.13.1.tgz",
"integrity": "sha512-hXYyrPFwETT2swFLHeoKtJrvSF/ftG/sA15/8nGaLuaDGfVAaq8DYFpu4yOyV4tzp082WqnTEoMsm3flKMI2FQ==",
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}
},
"dependencies": {
"@tauri-apps/api": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.0.1.tgz",
"integrity": "sha512-TJwKkXxtF52kN9Auu5TWD2AE4ssqTrsfdpIrixYwRb3gQ/FuYwvZjrMc9weYpgsW2cMhVNkvKgneNXF/4n04lw==",
"requires": {
"type-fest": "2.13.1"
}
},
"@tauri-apps/cli": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.0.0.tgz",
"integrity": "sha512-4eHnk3p0xnCXd9Zel3kLvdiiSURnN98GMFvWUAdirm5AjyOjcx8TIET/jqRYmYKE5yd+LMQqYMUfHRwA6JJUkg==",
"dev": true,
"requires": {
"@tauri-apps/cli-darwin-arm64": "1.0.0",
"@tauri-apps/cli-darwin-x64": "1.0.0",
"@tauri-apps/cli-linux-arm-gnueabihf": "1.0.0",
"@tauri-apps/cli-linux-arm64-gnu": "1.0.0",
"@tauri-apps/cli-linux-arm64-musl": "1.0.0",
"@tauri-apps/cli-linux-x64-gnu": "1.0.0",
"@tauri-apps/cli-linux-x64-musl": "1.0.0",
"@tauri-apps/cli-win32-ia32-msvc": "1.0.0",
"@tauri-apps/cli-win32-x64-msvc": "1.0.0"
}
},
"@tauri-apps/cli-darwin-arm64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0.tgz",
"integrity": "sha512-0ryomgLjdpylXypMPVXLU3PZCde3Sw5nwN4coUhBcHPBLFRb8QPet+nweVK/HiZ3mxg8WeIazvpx2s8hS0l2GQ==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-darwin-x64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0.tgz",
"integrity": "sha512-oejvYUT4dEfzBi+FWMj+CMz4cZ6C2gEFHrUtKVLdTXr8Flj5UTwdB1YPGQjiOqk73LOI7cB/vXxb9DZT+Lrxgg==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-linux-arm-gnueabihf": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0.tgz",
"integrity": "sha512-yAu78v8TeXNx/ETS5F2G2Uw/HX+LQvZkX94zNiqFsAj7snfWI/IqSUM52OBrdh/D0EC9NCdjUJ7Vuo32uxf7tg==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-linux-arm64-gnu": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0.tgz",
"integrity": "sha512-YFUN/S58AN317njAynzcQ+EHhRsCDXqmp5g9Oiqmcdg1vU7fPWZivVLc1WHz+0037C7JnsX5PtKpNYewP/+Oqw==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-linux-arm64-musl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0.tgz",
"integrity": "sha512-al+TxMGoNVikEvRQfMyYE/mdjUcUNMo5brkCIAb+fL4rWQlAhAnYVzmg/rM8N4nhdXm1MOaYAagQmxr8898dNA==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-linux-x64-gnu": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0.tgz",
"integrity": "sha512-KQmYlYyGpn6/2kSl9QivWG6EIepm6PJd57e6IKmYwAyNhLr2XfGl1CLuocUQQgO+jprjT70HXp+MXD0tcB0+Sw==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-linux-x64-musl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0.tgz",
"integrity": "sha512-Qpaq5lZz569Aea6jfrRchgfEJaOrfLpCRBATcF8CJFFwVKmfCUcoV+MxbCIW30Zqw5Y06njC/ffa3261AV/ZIQ==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-win32-ia32-msvc": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0.tgz",
"integrity": "sha512-e2DzFqEMI+s+gv14UupdI91gPxTbUJTbbfQlTHdQlOsTk4HEZTsh+ibAYBcCLAaMRW38NEsFlAUe1lQA0iRu/w==",
"dev": true,
"optional": true
},
"@tauri-apps/cli-win32-x64-msvc": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0.tgz",
"integrity": "sha512-lWSs90pJeQX+L31IqIzmRhwLayEeyTh7mga0AxX8G868hvdLtcXCQA/rKoFtGdVLuHAx4+M+CBF5SMYb76xGYA==",
"dev": true,
"optional": true
},
"type-fest": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.13.1.tgz",
"integrity": "sha512-hXYyrPFwETT2swFLHeoKtJrvSF/ftG/sA15/8nGaLuaDGfVAaq8DYFpu4yOyV4tzp082WqnTEoMsm3flKMI2FQ=="
}
}
}

View file

@ -1,12 +0,0 @@
{
"name": "gitlab-jobs-tauri",
"scripts": {
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "^1.0.1"
},
"devDependencies": {
"@tauri-apps/cli": "^1.0.0"
}
}

View file

@ -6,6 +6,7 @@
table {
height: 100vh;
width: 100vw;
display: block;
}
td.status {
font-weight: bold;
@ -63,11 +64,11 @@
const template = $('.template')
const table = $('tbody')
let notifications = true
let notifications = false
$('th.status').addEventListener('click', ev => {
notifications = !notifications
window.__TAURI__.notification.sendNotification({
sendNotification({
title: 'GitLab Jobs',
body: `Notifications are now ${notifications ? 'enabled' : 'disabled'}`
})
@ -93,7 +94,7 @@
existing.className = ''
existing.classList.add(job.status)
if (['success', 'failed'].includes(job.status)) {
window.__TAURI__.notification.sendNotification({
sendNotification({
title: 'GitLab Jobs',
body: `Job ${job.name} for ${job.project.name}: ${job.status}`
})
@ -154,4 +155,4 @@
setInterval(updateJobs, 5000)
</script>
</body>
</html>
</html>

View file

@ -1,3 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/

4270
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["ptrcnull"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.57"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.0.0", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.0.0", features = ["api-all"] }
gitlab = "0.1500.0"
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
[features]
# by default Tauri runs in production mode
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
default = [ "custom-protocol" ]
# this feature is used used for production builds where `devPath` points to the filesystem
# DO NOT remove this
custom-protocol = [ "tauri/custom-protocol" ]

View file

@ -1,3 +0,0 @@
fn main() {
tauri_build::build()
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,77 +0,0 @@
// additional queries not defined in the gitlab crate
use gitlab::{api::{endpoint_prelude::Method, Endpoint}, *};
use serde::{Serialize, Deserialize};
use chrono::{DateTime, Utc};
pub struct RunnerJobs {
pub runner_id: String,
}
impl Endpoint for RunnerJobs {
fn method(&self) -> Method {
Method::GET
}
fn endpoint(&self) -> std::borrow::Cow<'static, str> {
format!("runners/{}/jobs?order_by=id", self.runner_id).into()
}
}
pub struct Runners {}
impl Endpoint for Runners {
fn method(&self) -> Method {
Method::GET
}
fn endpoint(&self) -> std::borrow::Cow<'static, str> {
"runners".into()
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Job {
/// The ID of the job.
pub id: JobId,
/// The status of the job.
pub status: StatusState,
pub stage: String,
/// The name of the job.
pub name: String,
#[serde(rename = "ref")]
/// The name of the reference that was tested.
pub ref_: Option<String>,
pub tag: bool,
pub coverage: Option<f64>,
/// When the job was created or marked as pending.
pub created_at: DateTime<Utc>,
/// When the job was started.
pub started_at: Option<DateTime<Utc>>,
/// When the job completed.
pub finished_at: Option<DateTime<Utc>>,
/// The user which ran the job.
pub user: Option<User>,
/// The artifact file uploaded from the job.
pub artifacts_file: Option<JobArtifactFile>,
/// The commit the job tested.
pub commit: RepoCommit,
/// The runner which ran the job.
pub runner: Option<Runner>,
/// The pipeline the job belongs to.
pub pipeline: PipelineBasic,
pub allow_failure: bool,
pub duration: Option<f64>,
pub artifacts: Option<Vec<JobArtifact>>,
pub artifacts_expire_at: Option<DateTime<Utc>>,
pub web_url: String,
pub project: ProjectInfo,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ProjectInfo {
pub id: ProjectId,
pub name: String,
pub name_with_namespace: String,
pub path: String,
pub path_with_namespace: String,
}

View file

@ -1,103 +0,0 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
use std::sync::Mutex;
use gitlab::{api::{AsyncQuery, projects::jobs::RetryJob}, Runner, AsyncGitlab};
use gitlab_api::Job;
pub mod gitlab_api;
struct AppState {
gl: Option<AsyncGitlab>
}
impl AppState {
fn default() -> Self {
Self {
gl: None
}
}
fn get_client(&self) -> Result<AsyncGitlab, String> {
match &self.gl {
Some(client) => Ok(client.clone()),
None => {
Err("not logged in".to_string())
}
}
}
}
type State<'a> = tauri::State<'a, Mutex<AppState>>;
#[tauri::command]
fn is_logged_in(state: State) -> bool {
state.lock().unwrap().gl.is_some()
}
#[tauri::command]
async fn log_in(token: String, state: State<'_>) -> Result<(), String> {
let gitlab_client = gitlab::GitlabBuilder::new("gitlab.com", token).build_async().await;
match gitlab_client {
Ok(client) => {
state.lock().unwrap().gl.replace(client);
Ok(())
},
Err(error) => Err(error.to_string())
}
}
#[tauri::command]
async fn list_runners(state: State<'_>) -> Result<Vec<Runner>, String> {
let client = {
let appstate = state.lock().unwrap();
appstate.get_client()
}?;
let endpoint = gitlab_api::Runners{};
let response: Result<Vec<Runner>, _> = endpoint.query_async(&client).await;
response.map_err(|err| err.to_string())
}
#[tauri::command]
async fn list_jobs_for_runner(runner_id: String, state: State<'_>) -> Result<Vec<Job>, String> {
let client = {
let appstate = state.lock().unwrap();
appstate.get_client()
}?;
let endpoint = gitlab_api::RunnerJobs{runner_id};
let response: Result<Vec<Job>, _> = endpoint.query_async(&client).await;
response.map_err(|err| err.to_string())
}
#[tauri::command]
async fn retry_job(project_id: String, job_id: u64, state: State<'_>) -> Result<Job, String> {
let client = {
let appstate = state.lock().unwrap();
appstate.get_client()
}?;
let endpoint = RetryJob::builder().project(project_id).job(job_id).build().unwrap();
let response: Result<Job, _> = endpoint.query_async(&client).await;
response.map_err(|err| err.to_string())
}
fn main() {
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(Mutex::new(AppState::default()))
.invoke_handler(tauri::generate_handler![
is_logged_in,
log_in,
list_runners,
list_jobs_for_runner,
retry_job
])
.menu(tauri::Menu::os_default(&context.package_info().name))
.run(context)
.expect("error while running tauri application");
}

View file

@ -1,67 +0,0 @@
{
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"build": {
"beforeBuildCommand": "",
"beforeDevCommand": "",
"devPath": "../dist",
"distDir": "../dist",
"withGlobalTauri": true
},
"package": {
"productName": "gitlab-jobs",
"version": "0.1.0"
},
"tauri": {
"allowlist": {
"all": true
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "me.ptrcnull.gitlab-jobs",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "GitLab Jobs",
"width": 800
}
]
}
}

View file

@ -6,6 +6,7 @@ body {
height: 100%;
background-color: #1f1f1f;
color: #ffffff;
font-family: sans-serif;
}
body {