├── .dockerignore ├── .editorconfig ├── .gitignore ├── .prettierrc ├── Dockerfile ├── Dockerfile.worker ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── abstruse-server │ └── main.go └── abstruse-worker │ └── main.go ├── configs ├── demo │ └── default │ │ └── docker-compose.yml └── testing │ ├── e2e │ ├── data │ │ ├── gitea │ │ │ ├── git │ │ │ │ ├── .gitconfig │ │ │ │ ├── .ssh │ │ │ │ │ └── environment │ │ │ │ └── repositories │ │ │ │ │ └── gitea │ │ │ │ │ ├── chisel.git │ │ │ │ │ ├── HEAD │ │ │ │ │ ├── config │ │ │ │ │ ├── description │ │ │ │ │ ├── hooks │ │ │ │ │ │ ├── applypatch-msg.sample │ │ │ │ │ │ ├── commit-msg.sample │ │ │ │ │ │ ├── post-receive │ │ │ │ │ │ ├── post-receive.d │ │ │ │ │ │ │ └── gitea │ │ │ │ │ │ ├── post-update.sample │ │ │ │ │ │ ├── pre-applypatch.sample │ │ │ │ │ │ ├── pre-commit.sample │ │ │ │ │ │ ├── pre-merge-commit.sample │ │ │ │ │ │ ├── pre-push.sample │ │ │ │ │ │ ├── pre-rebase.sample │ │ │ │ │ │ ├── pre-receive │ │ │ │ │ │ ├── pre-receive.d │ │ │ │ │ │ │ └── gitea │ │ │ │ │ │ ├── pre-receive.sample │ │ │ │ │ │ ├── prepare-commit-msg.sample │ │ │ │ │ │ ├── update │ │ │ │ │ │ ├── update.d │ │ │ │ │ │ │ └── gitea │ │ │ │ │ │ └── update.sample │ │ │ │ │ ├── info │ │ │ │ │ │ ├── exclude │ │ │ │ │ │ └── refs │ │ │ │ │ ├── objects │ │ │ │ │ │ ├── info │ │ │ │ │ │ │ └── packs │ │ │ │ │ │ └── pack │ │ │ │ │ │ │ ├── pack-240a97588b15c19566b570d8f679902d93b64069.idx │ │ │ │ │ │ │ └── pack-240a97588b15c19566b570d8f679902d93b64069.pack │ │ │ │ │ └── refs │ │ │ │ │ │ └── heads │ │ │ │ │ │ └── master │ │ │ │ │ └── d3-bundle.git │ │ │ │ │ ├── HEAD │ │ │ │ │ ├── config │ │ │ │ │ ├── description │ │ │ │ │ ├── hooks │ │ │ │ │ ├── applypatch-msg.sample │ │ │ │ │ ├── commit-msg.sample │ │ │ │ │ ├── post-receive │ │ │ │ │ ├── post-receive.d │ │ │ │ │ │ └── gitea │ │ │ │ │ ├── post-update.sample │ │ │ │ │ ├── pre-applypatch.sample │ │ │ │ │ ├── pre-commit.sample │ │ │ │ │ ├── pre-merge-commit.sample │ │ │ │ │ ├── pre-push.sample │ │ │ │ │ ├── pre-rebase.sample │ │ │ │ │ ├── pre-receive │ │ │ │ │ ├── pre-receive.d │ │ │ │ │ │ └── gitea │ │ │ │ │ ├── pre-receive.sample │ │ │ │ │ ├── prepare-commit-msg.sample │ │ │ │ │ ├── update │ │ │ │ │ ├── update.d │ │ │ │ │ │ └── gitea │ │ │ │ │ └── update.sample │ │ │ │ │ ├── info │ │ │ │ │ ├── exclude │ │ │ │ │ └── refs │ │ │ │ │ ├── objects │ │ │ │ │ ├── 23 │ │ │ │ │ │ └── dac78c3317010b4851964fc0dff362fc40dd87 │ │ │ │ │ ├── 45 │ │ │ │ │ │ └── 9f7a9284ba653a382d73bd08dbff0ce48c04bd │ │ │ │ │ ├── 49 │ │ │ │ │ │ └── 4f47baeda0f20be99ceca28973a5b4e2639fac │ │ │ │ │ ├── 61 │ │ │ │ │ │ └── 2c0b44b5a2569f8392b391b571f5b0cf38d822 │ │ │ │ │ ├── 64 │ │ │ │ │ │ └── 4b14725c53c94d515e58e60cf55b45d2b0387d │ │ │ │ │ ├── 66 │ │ │ │ │ │ └── fe6594c1a643e6d9d3ac655948804543f361db │ │ │ │ │ ├── 75 │ │ │ │ │ │ └── 704c60b07c63ca3c23f7558669a86ee046b1b6 │ │ │ │ │ ├── 94 │ │ │ │ │ │ ├── 65c94d506140766fca573414c9819a8cd326bc │ │ │ │ │ │ └── dba4cd133625a3a9a8d8fe1fdc3e9fc116d79e │ │ │ │ │ ├── 06 │ │ │ │ │ │ └── 7e8657dcd509c2e63376eb64c17fbc218dcdf2 │ │ │ │ │ ├── 0e │ │ │ │ │ │ └── 117226e9611523c1bd75611a497294c34a89ee │ │ │ │ │ ├── 0f │ │ │ │ │ │ └── 449daa627f17a95f1feca1b6a2bdffe035a354 │ │ │ │ │ ├── 1d │ │ │ │ │ │ └── 9d875edb469786a9c6dbae5aaeef9a3bcb2c33 │ │ │ │ │ ├── 5e │ │ │ │ │ │ └── 331c4a57c0fbd6b3f3b0c44e23b969b815ab5c │ │ │ │ │ ├── 6e │ │ │ │ │ │ └── 0c2d4ca40cff19e81e7ccc540f83599ac46ba4 │ │ │ │ │ ├── 6f │ │ │ │ │ │ └── dd39e7e47bb01e92fdacd36aa510aa61dbe94a │ │ │ │ │ ├── 7e │ │ │ │ │ │ └── 02de72ffb166c8102057246b26b07f15fe0d3f │ │ │ │ │ ├── 8e │ │ │ │ │ │ └── 1c6452d41d7a45d0b16d5f711befdbbe2c0320 │ │ │ │ │ ├── 9b │ │ │ │ │ │ └── 160ccb0fe44106a5f535e4bf2ee8fade9c7457 │ │ │ │ │ ├── 9f │ │ │ │ │ │ └── ec0d70b748bd8292f43d32612948c0b134296e │ │ │ │ │ ├── a2 │ │ │ │ │ │ ├── 8f4dc019162842bd5b211ccab3938a4c869058 │ │ │ │ │ │ └── 9d30d933cc3b0f8ac921bb30912ae8d2eb0ac8 │ │ │ │ │ ├── a8 │ │ │ │ │ │ └── a375133818257773488e4d99a2423b5d87da0e │ │ │ │ │ ├── b2 │ │ │ │ │ │ └── 6adb425bcdc41d853a4a99d666f7e5922fc412 │ │ │ │ │ ├── b6 │ │ │ │ │ │ └── 640f6e51b9e54d757685915363dec6102c3c31 │ │ │ │ │ ├── b8 │ │ │ │ │ │ └── 3008725f2e4de6ed0eb82a3906c15a6bab36dc │ │ │ │ │ ├── ca │ │ │ │ │ │ └── 77fb843d6016f246237cf416116c7c692661ac │ │ │ │ │ ├── ce │ │ │ │ │ │ └── 382e7f0e87e08eed171b74218242a580548727 │ │ │ │ │ ├── d5 │ │ │ │ │ │ └── 186b0fd377a7c1598297bcdc7fea5025dd318b │ │ │ │ │ ├── da │ │ │ │ │ │ └── db4b56294c5feae8eb8cde4ac1bacd4218f6dc │ │ │ │ │ ├── df │ │ │ │ │ │ └── b770e6519e1e0606eb65dc09de0871078ab8ca │ │ │ │ │ ├── e0 │ │ │ │ │ │ └── 523379a7c09728f497fd99fb534fca7f740e62 │ │ │ │ │ ├── ea │ │ │ │ │ │ └── 78036835f061e9b31853d1649ac5f9bd522ff5 │ │ │ │ │ ├── eb │ │ │ │ │ │ └── 966e2602a8d73a9b2dd488c0ade54d84baa405 │ │ │ │ │ ├── f6 │ │ │ │ │ │ └── e575b38b60c0bee86677480861c4e474400d09 │ │ │ │ │ ├── fb │ │ │ │ │ │ └── 6a8a9e1aa5815c8eb7831eef10f0267d803b62 │ │ │ │ │ └── info │ │ │ │ │ │ └── packs │ │ │ │ │ └── refs │ │ │ │ │ └── heads │ │ │ │ │ └── master │ │ │ ├── gitea │ │ │ │ ├── avatars │ │ │ │ │ ├── afa79842299060b5ee62d1566448cd42 │ │ │ │ │ └── c3a8e0afa692c2437d775e44b59082aa │ │ │ │ ├── conf │ │ │ │ │ └── app.ini │ │ │ │ └── gitea.db │ │ │ └── ssh │ │ │ │ ├── ssh_host_dsa_key │ │ │ │ ├── ssh_host_dsa_key.pub │ │ │ │ ├── ssh_host_ecdsa_key │ │ │ │ ├── ssh_host_ecdsa_key.pub │ │ │ │ ├── ssh_host_ed25519_key │ │ │ │ ├── ssh_host_ed25519_key.pub │ │ │ │ ├── ssh_host_rsa_key │ │ │ │ └── ssh_host_rsa_key.pub │ │ └── gitea_credentials.txt │ └── docker-compose.yml │ └── e2e_postgres │ └── docker-compose.yml ├── docs ├── ABSTRUSE_YML.md ├── INTEGRATING_GIT_PROVIDERS.md └── QUICKSTART.md ├── go.mod ├── go.sum ├── internal ├── auth │ ├── auth.go │ ├── bcrypt.go │ ├── claims.go │ ├── grpc.go │ ├── htpasswd.go │ ├── jwt.go │ └── worker.go └── version │ └── version.go ├── pb └── api.proto ├── pkg ├── fs │ └── fs.go ├── gitscm │ ├── gitea.go │ ├── scm.go │ └── types.go ├── lib │ ├── collection.go │ ├── id.go │ ├── json.go │ ├── net.go │ ├── rand.go │ ├── tcp_wait.go │ └── time.go ├── stats │ ├── cpu.go │ ├── mem.go │ └── stats.go └── tlsutil │ └── certgen.go ├── server ├── api │ ├── api.go │ ├── badge │ │ └── badge.go │ ├── build │ │ ├── find.go │ │ ├── find_job.go │ │ ├── list.go │ │ ├── log.go │ │ ├── restart.go │ │ ├── restart_job.go │ │ ├── stop.go │ │ ├── stop_job.go │ │ └── trigger.go │ ├── middlewares │ │ └── auth.go │ ├── provider │ │ ├── create.go │ │ ├── delete.go │ │ ├── find.go │ │ ├── listuser.go │ │ ├── sync.go │ │ └── update.go │ ├── render │ │ ├── errors.go │ │ ├── render.go │ │ └── types.go │ ├── repo │ │ ├── active.go │ │ ├── config.go │ │ ├── create_env.go │ │ ├── create_hooks.go │ │ ├── create_mount.go │ │ ├── delete_env.go │ │ ├── delete_mount.go │ │ ├── find.go │ │ ├── list.go │ │ ├── list_env.go │ │ ├── list_hooks.go │ │ ├── list_mount.go │ │ ├── update_env.go │ │ ├── update_misc.go │ │ ├── update_mount.go │ │ └── update_sshkey.go │ ├── setup │ │ ├── ready.go │ │ └── user.go │ ├── stats │ │ ├── jobs.go │ │ ├── pause.go │ │ ├── resume.go │ │ └── stats.go │ ├── system │ │ └── version.go │ ├── team │ │ ├── create.go │ │ ├── find.go │ │ ├── list.go │ │ └── update.go │ ├── user │ │ ├── avatar.go │ │ ├── create.go │ │ ├── list.go │ │ ├── login.go │ │ ├── password.go │ │ ├── profile.go │ │ ├── update.go │ │ └── update_profile.go │ ├── webhook │ │ └── hook.go │ └── worker │ │ ├── auth.go │ │ ├── download_cache.go │ │ ├── list.go │ │ └── upload_cache.go ├── cmd │ ├── cmd.go │ └── wire.go ├── config │ └── config.go ├── core │ ├── build.go │ ├── env.go │ ├── githook.go │ ├── job.go │ ├── mount.go │ ├── permission.go │ ├── provider.go │ ├── registry.go │ ├── repo.go │ ├── scheduler.go │ ├── stats.go │ ├── team.go │ ├── timestamp.go │ ├── user.go │ └── worker.go ├── http │ └── http.go ├── logger │ └── logger.go ├── parser │ ├── env.go │ └── parser.go ├── scheduler │ └── scheduler.go ├── service │ ├── githook │ │ └── parser.go │ └── stats │ │ └── stats.go ├── store │ ├── build │ │ └── build.go │ ├── envvariable │ │ └── envvariable.go │ ├── job │ │ └── job.go │ ├── mounts │ │ └── mounts.go │ ├── permission │ │ └── permission.go │ ├── provider │ │ └── provider.go │ ├── repo │ │ └── repo.go │ ├── store.go │ ├── team │ │ └── team.go │ └── user │ │ └── user.go ├── worker │ └── registry.go └── ws │ ├── app.go │ ├── client.go │ ├── proxy.go │ ├── server.go │ └── types.go ├── tests ├── e2e │ ├── e2e.go │ └── tcp_wait.go └── webhooks │ ├── gitea │ ├── branch │ │ ├── headers.txt │ │ └── webhook.json │ ├── pull_request │ │ ├── headers.txt │ │ └── webhook.json │ ├── push │ │ ├── headers.txt │ │ └── webhook.json │ └── tag │ │ ├── headers.txt │ │ └── webhook.json │ ├── github │ ├── branch │ │ ├── headers.txt │ │ └── webhook.json │ ├── pull_request │ │ ├── headers.txt │ │ └── webhook.json │ ├── push │ │ ├── headers.txt │ │ ├── sha.js │ │ └── webhook.json │ └── tag │ │ ├── headers.txt │ │ └── webhook.json │ └── main.go ├── web └── abstruse │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── angular.json │ ├── karma.conf.js │ ├── ngsw-config.json │ ├── package-lock.json │ ├── package.json │ ├── proxy.conf.json │ ├── src │ ├── app │ │ ├── app-routing.module.ts │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── auth │ │ │ ├── auth.module.ts │ │ │ ├── login │ │ │ │ ├── login.component.html │ │ │ │ ├── login.component.sass │ │ │ │ └── login.component.ts │ │ │ └── shared │ │ │ │ ├── already-auth-guard.service.ts │ │ │ │ ├── auth-guard.service.ts │ │ │ │ ├── auth.model.ts │ │ │ │ └── auth.service.ts │ │ ├── builds │ │ │ ├── build │ │ │ │ ├── build.component.html │ │ │ │ ├── build.component.sass │ │ │ │ └── build.component.ts │ │ │ ├── builds-routing.module.ts │ │ │ ├── builds.module.ts │ │ │ ├── common │ │ │ │ ├── build-list-item │ │ │ │ │ ├── build-list-item.component.html │ │ │ │ │ ├── build-list-item.component.sass │ │ │ │ │ └── build-list-item.component.ts │ │ │ │ ├── builds-common.module.ts │ │ │ │ └── builds-items │ │ │ │ │ ├── builds-items-options.model.ts │ │ │ │ │ ├── builds-items.component.html │ │ │ │ │ ├── builds-items.component.sass │ │ │ │ │ └── builds-items.component.ts │ │ │ ├── index │ │ │ │ ├── index.component.html │ │ │ │ ├── index.component.sass │ │ │ │ └── index.component.ts │ │ │ ├── job-list-item │ │ │ │ ├── job-list-item.component.html │ │ │ │ ├── job-list-item.component.sass │ │ │ │ └── job-list-item.component.ts │ │ │ ├── job │ │ │ │ ├── job.component.html │ │ │ │ ├── job.component.sass │ │ │ │ └── job.component.ts │ │ │ └── shared │ │ │ │ ├── build.model.ts │ │ │ │ └── builds.service.ts │ │ ├── core │ │ │ ├── core.module.ts │ │ │ ├── gateway-timeout │ │ │ │ ├── gateway-timeout.component.html │ │ │ │ ├── gateway-timeout.component.sass │ │ │ │ └── gateway-timeout.component.ts │ │ │ ├── header │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.sass │ │ │ │ └── header.component.ts │ │ │ ├── index.ts │ │ │ ├── interceptors │ │ │ │ ├── api.interceptor.ts │ │ │ │ └── error.interceptor.ts │ │ │ └── not-found │ │ │ │ ├── not-found.component.html │ │ │ │ ├── not-found.component.sass │ │ │ │ └── not-found.component.ts │ │ ├── dashboard │ │ │ ├── dashboard-routing.module.ts │ │ │ ├── dashboard.module.ts │ │ │ ├── index │ │ │ │ ├── index.component.html │ │ │ │ ├── index.component.sass │ │ │ │ └── index.component.ts │ │ │ └── shared │ │ │ │ └── dashboard.service.ts │ │ ├── profile │ │ │ ├── profile-routing.module.ts │ │ │ ├── profile.module.ts │ │ │ ├── profile │ │ │ │ ├── profile.component.html │ │ │ │ ├── profile.component.sass │ │ │ │ └── profile.component.ts │ │ │ ├── security │ │ │ │ ├── security.component.html │ │ │ │ ├── security.component.sass │ │ │ │ └── security.component.ts │ │ │ ├── settings │ │ │ │ ├── settings.component.html │ │ │ │ ├── settings.component.sass │ │ │ │ └── settings.component.ts │ │ │ └── shared │ │ │ │ ├── password.model.ts │ │ │ │ └── profile.service.ts │ │ ├── providers │ │ │ ├── provider-item │ │ │ │ ├── provider-item.component.html │ │ │ │ ├── provider-item.component.sass │ │ │ │ └── provider-item.component.ts │ │ │ ├── providers-modal │ │ │ │ ├── providers-modal.component.html │ │ │ │ ├── providers-modal.component.sass │ │ │ │ └── providers-modal.component.ts │ │ │ ├── providers-routing.module.ts │ │ │ ├── providers.module.ts │ │ │ ├── providers │ │ │ │ ├── providers.component.html │ │ │ │ ├── providers.component.sass │ │ │ │ └── providers.component.ts │ │ │ └── shared │ │ │ │ ├── provider.class.ts │ │ │ │ └── providers.service.ts │ │ ├── repos │ │ │ ├── branches │ │ │ │ ├── branches.component.html │ │ │ │ ├── branches.component.sass │ │ │ │ └── branches.component.ts │ │ │ ├── builds │ │ │ │ ├── builds.component.html │ │ │ │ ├── builds.component.sass │ │ │ │ └── builds.component.ts │ │ │ ├── pull-requests │ │ │ │ ├── pull-requests.component.html │ │ │ │ ├── pull-requests.component.sass │ │ │ │ └── pull-requests.component.ts │ │ │ ├── repo-item │ │ │ │ ├── repo-item.component.html │ │ │ │ ├── repo-item.component.sass │ │ │ │ └── repo-item.component.ts │ │ │ ├── repo │ │ │ │ ├── repo.component.html │ │ │ │ ├── repo.component.sass │ │ │ │ └── repo.component.ts │ │ │ ├── repos-routing.module.ts │ │ │ ├── repos.module.ts │ │ │ ├── repos │ │ │ │ ├── repos.component.html │ │ │ │ ├── repos.component.sass │ │ │ │ └── repos.component.ts │ │ │ ├── settings-env-modal │ │ │ │ ├── settings-env-modal.component.html │ │ │ │ ├── settings-env-modal.component.sass │ │ │ │ └── settings-env-modal.component.ts │ │ │ ├── settings-envs │ │ │ │ ├── env-variable.model.ts │ │ │ │ ├── settings-envs.component.html │ │ │ │ ├── settings-envs.component.sass │ │ │ │ └── settings-envs.component.ts │ │ │ ├── settings-mount-modal │ │ │ │ ├── settings-mount-modal.component.html │ │ │ │ ├── settings-mount-modal.component.sass │ │ │ │ └── settings-mount-modal.component.ts │ │ │ ├── settings-mount │ │ │ │ ├── mount-variable.model.ts │ │ │ │ ├── settings-mount.component.html │ │ │ │ ├── settings-mount.component.sass │ │ │ │ └── settings-mount.component.ts │ │ │ ├── settings-ssh-modal │ │ │ │ ├── settings-ssh-modal.component.html │ │ │ │ ├── settings-ssh-modal.component.sass │ │ │ │ ├── settings-ssh-modal.component.spec.ts │ │ │ │ └── settings-ssh-modal.component.ts │ │ │ ├── settings-ssh │ │ │ │ ├── settings-ssh.component.html │ │ │ │ ├── settings-ssh.component.sass │ │ │ │ ├── settings-ssh.component.spec.ts │ │ │ │ └── settings-ssh.component.ts │ │ │ ├── settings │ │ │ │ ├── settings.component.html │ │ │ │ ├── settings.component.sass │ │ │ │ └── settings.component.ts │ │ │ └── shared │ │ │ │ ├── hook.model.ts │ │ │ │ ├── repo.model.ts │ │ │ │ └── repos.service.ts │ │ ├── setup │ │ │ ├── header │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.sass │ │ │ │ └── header.component.ts │ │ │ ├── setup-routing.module.ts │ │ │ ├── setup.component.html │ │ │ ├── setup.component.ts │ │ │ ├── setup.module.ts │ │ │ ├── shared │ │ │ │ ├── admin.model.ts │ │ │ │ ├── setup-done-guard.service.ts │ │ │ │ ├── setup.model.ts │ │ │ │ └── setup.service.ts │ │ │ └── user │ │ │ │ ├── user.component.html │ │ │ │ ├── user.component.sass │ │ │ │ └── user.component.ts │ │ ├── shared │ │ │ ├── common │ │ │ │ ├── bytes.ts │ │ │ │ ├── colors.ts │ │ │ │ ├── random-hash.ts │ │ │ │ └── random-int.ts │ │ │ ├── components │ │ │ │ ├── loader │ │ │ │ │ ├── loader.component.html │ │ │ │ │ ├── loader.component.sass │ │ │ │ │ └── loader.component.ts │ │ │ │ ├── modal │ │ │ │ │ ├── content-ref.class.ts │ │ │ │ │ ├── modal-config.service.ts │ │ │ │ │ ├── modal-ref.class.ts │ │ │ │ │ ├── modal-stack.class.ts │ │ │ │ │ ├── modal.component.html │ │ │ │ │ ├── modal.component.sass │ │ │ │ │ ├── modal.component.ts │ │ │ │ │ ├── modal.module.ts │ │ │ │ │ └── modal.service.ts │ │ │ │ ├── progress-wizard │ │ │ │ │ ├── progress-wizard.component.html │ │ │ │ │ ├── progress-wizard.component.sass │ │ │ │ │ └── progress-wizard.component.ts │ │ │ │ └── terminal │ │ │ │ │ ├── terminal.component.html │ │ │ │ │ ├── terminal.component.sass │ │ │ │ │ └── terminal.component.ts │ │ │ ├── directives │ │ │ │ ├── stop-propagation.directive.ts │ │ │ │ ├── tooltip.directive.spec.ts │ │ │ │ └── tooltip.directive.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── monaco.model.ts │ │ │ │ ├── socket.class.ts │ │ │ │ └── socket.model.ts │ │ │ ├── providers │ │ │ │ ├── data.service.ts │ │ │ │ ├── socket.service.ts │ │ │ │ └── time.service.ts │ │ │ ├── shared.module.ts │ │ │ ├── validators │ │ │ │ └── validators.ts │ │ │ └── widgets │ │ │ │ ├── avatar-picker │ │ │ │ ├── avatar-picker.component.html │ │ │ │ ├── avatar-picker.component.sass │ │ │ │ ├── avatar-picker.component.spec.ts │ │ │ │ └── avatar-picker.component.ts │ │ │ │ ├── checkbox │ │ │ │ ├── checkbox.component.html │ │ │ │ ├── checkbox.component.sass │ │ │ │ ├── checkbox.component.spec.ts │ │ │ │ └── checkbox.component.ts │ │ │ │ ├── color-picker │ │ │ │ ├── color-picker.component.html │ │ │ │ ├── color-picker.component.sass │ │ │ │ └── color-picker.component.ts │ │ │ │ ├── progress-bar │ │ │ │ ├── progress-bar.component.html │ │ │ │ ├── progress-bar.component.sass │ │ │ │ ├── progress-bar.component.spec.ts │ │ │ │ ├── progress-bar.component.ts │ │ │ │ └── progress-bar.interface.ts │ │ │ │ ├── selectbox │ │ │ │ ├── selectbox.component.html │ │ │ │ ├── selectbox.component.sass │ │ │ │ ├── selectbox.component.spec.ts │ │ │ │ └── selectbox.component.ts │ │ │ │ └── toggle │ │ │ │ ├── toggle.component.html │ │ │ │ ├── toggle.component.sass │ │ │ │ └── toggle.component.ts │ │ ├── system │ │ │ ├── shared │ │ │ │ ├── system.service.ts │ │ │ │ └── version.class.ts │ │ │ ├── system-routing.module.ts │ │ │ ├── system.module.ts │ │ │ └── version │ │ │ │ ├── version.component.html │ │ │ │ ├── version.component.sass │ │ │ │ └── version.component.ts │ │ ├── teams │ │ │ ├── shared │ │ │ │ ├── teams.service.ts │ │ │ │ ├── user.model.ts │ │ │ │ └── users.service.ts │ │ │ ├── team-item │ │ │ │ ├── team-item.component.html │ │ │ │ ├── team-item.component.sass │ │ │ │ └── team-item.component.ts │ │ │ ├── team-modal │ │ │ │ ├── team-modal.component.html │ │ │ │ ├── team-modal.component.sass │ │ │ │ └── team-modal.component.ts │ │ │ ├── teams-list │ │ │ │ ├── teams-list.component.html │ │ │ │ ├── teams-list.component.sass │ │ │ │ └── teams-list.component.ts │ │ │ ├── teams-routing.module.ts │ │ │ ├── teams.module.ts │ │ │ ├── user-list-item │ │ │ │ ├── user-list-item.component.html │ │ │ │ ├── user-list-item.component.sass │ │ │ │ └── user-list-item.component.ts │ │ │ ├── user-modal │ │ │ │ ├── user-modal.component.html │ │ │ │ ├── user-modal.component.sass │ │ │ │ └── user-modal.component.ts │ │ │ └── users │ │ │ │ ├── users.component.html │ │ │ │ ├── users.component.sass │ │ │ │ └── users.component.ts │ │ └── workers │ │ │ ├── shared │ │ │ ├── worker.model.ts │ │ │ └── workers.service.ts │ │ │ ├── worker-modal │ │ │ ├── worker-modal.component.html │ │ │ ├── worker-modal.component.sass │ │ │ └── worker-modal.component.ts │ │ │ ├── worker-table-item │ │ │ ├── worker-table-item.component.html │ │ │ ├── worker-table-item.component.sass │ │ │ └── worker-table-item.component.ts │ │ │ ├── workers-routing.module.ts │ │ │ ├── workers.module.ts │ │ │ └── workers │ │ │ ├── workers.component.html │ │ │ ├── workers.component.sass │ │ │ └── workers.component.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── fonts │ │ │ ├── Roboto │ │ │ │ ├── roboto-v20-latin-100.woff │ │ │ │ ├── roboto-v20-latin-100.woff2 │ │ │ │ ├── roboto-v20-latin-300.woff │ │ │ │ ├── roboto-v20-latin-300.woff2 │ │ │ │ ├── roboto-v20-latin-500.woff │ │ │ │ ├── roboto-v20-latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-700.woff │ │ │ │ ├── roboto-v20-latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-900.woff │ │ │ │ ├── roboto-v20-latin-900.woff2 │ │ │ │ ├── roboto-v20-latin-regular.woff │ │ │ │ └── roboto-v20-latin-regular.woff2 │ │ │ ├── Rubik │ │ │ │ ├── rubik-v9-latin-300.woff │ │ │ │ ├── rubik-v9-latin-300.woff2 │ │ │ │ ├── rubik-v9-latin-500.woff │ │ │ │ ├── rubik-v9-latin-500.woff2 │ │ │ │ ├── rubik-v9-latin-700.woff │ │ │ │ ├── rubik-v9-latin-700.woff2 │ │ │ │ ├── rubik-v9-latin-900.woff │ │ │ │ ├── rubik-v9-latin-900.woff2 │ │ │ │ ├── rubik-v9-latin-regular.woff │ │ │ │ └── rubik-v9-latin-regular.woff2 │ │ │ ├── SourceCodePro │ │ │ │ ├── SourceCodePro-Bold.woff │ │ │ │ ├── SourceCodePro-Bold.woff2 │ │ │ │ ├── SourceCodePro-Regular.woff │ │ │ │ └── SourceCodePro-Regular.woff2 │ │ │ └── octicons │ │ │ │ ├── octicons.svg │ │ │ │ ├── octicons.woff │ │ │ │ └── octicons.woff2 │ │ ├── icons │ │ │ ├── icon-192x192.png │ │ │ └── icon-512x512.png │ │ └── images │ │ │ ├── abstruse-square-dark.svg │ │ │ ├── abstruse-square.svg │ │ │ ├── abstruse-text-black.svg │ │ │ ├── abstruse.svg │ │ │ ├── avatars │ │ │ ├── avatar_1.svg │ │ │ ├── avatar_10.svg │ │ │ ├── avatar_11.svg │ │ │ ├── avatar_12.svg │ │ │ ├── avatar_13.svg │ │ │ ├── avatar_14.svg │ │ │ ├── avatar_15.svg │ │ │ ├── avatar_16.svg │ │ │ ├── avatar_17.svg │ │ │ ├── avatar_18.svg │ │ │ ├── avatar_19.svg │ │ │ ├── avatar_2.svg │ │ │ ├── avatar_20.svg │ │ │ ├── avatar_21.svg │ │ │ ├── avatar_22.svg │ │ │ ├── avatar_23.svg │ │ │ ├── avatar_24.svg │ │ │ ├── avatar_25.svg │ │ │ ├── avatar_26.svg │ │ │ ├── avatar_27.svg │ │ │ ├── avatar_28.svg │ │ │ ├── avatar_29.svg │ │ │ ├── avatar_3.svg │ │ │ ├── avatar_30.svg │ │ │ ├── avatar_4.svg │ │ │ ├── avatar_5.svg │ │ │ ├── avatar_6.svg │ │ │ ├── avatar_7.svg │ │ │ ├── avatar_8.svg │ │ │ └── avatar_9.svg │ │ │ └── icons │ │ │ ├── gitea-bg.svg │ │ │ ├── gitea-gray.svg │ │ │ └── gitea.svg │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── manifest.webmanifest │ ├── polyfills.ts │ ├── styles │ │ ├── _animations.sass │ │ ├── _colours.sass │ │ ├── _mixins.sass │ │ ├── _typography.sass │ │ ├── _variables.sass │ │ ├── app.sass │ │ ├── button.sass │ │ ├── common.sass │ │ ├── form.sass │ │ ├── header.sass │ │ ├── hero.sass │ │ ├── list.sass │ │ ├── main.sass │ │ ├── notification.sass │ │ ├── octicons.sass │ │ ├── pagination.sass │ │ ├── placeholder.sass │ │ ├── section.sass │ │ ├── status.sass │ │ ├── subheader.sass │ │ ├── table.sass │ │ ├── tabs.sass │ │ ├── tag.sass │ │ ├── terminal.sass │ │ └── tooltip.sass │ └── test.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── webpack.config.js └── worker ├── app ├── app.go ├── interceptor.go └── server.go ├── cache ├── cache.go ├── download.go └── upload.go ├── cmd ├── cmd.go └── wire.go ├── config └── config.go ├── docker ├── docker.go ├── image.go ├── init.go └── util.go ├── git ├── clone.go └── git.go ├── http ├── bearer.go └── client.go └── logger └── logger.go /.dockerignore: -------------------------------------------------------------------------------- 1 | build/ 2 | pb/api.pb.go 3 | pb/api_grpc.pb.go 4 | server/ui 5 | worker/data 6 | server/cmd/wire_gen.go 7 | worker/cmd/wire_gen.go 8 | .DS_Store 9 | tmp/ 10 | configs/ 11 | web/abstruse/node_modules 12 | web/abstruse/dist 13 | ./**/*/testdata/ 14 | .git/ 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.go] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | 18 | [Makefile] 19 | indent_style = tab 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /server/ui/ 3 | /worker/data 4 | /server/cmd/wire_gen.go 5 | /worker/cmd/wire_gen.go 6 | /pb/api.pb.go 7 | /pb/api_grpc.pb.go 8 | .DS_Store 9 | tmp/ 10 | configs/testing/**/*.pem 11 | configs/testing/**/*.log 12 | configs/testing/**/*/indexers/ 13 | configs/testing/**/*/log/ 14 | configs/testing/**/*/queues/ 15 | configs/testing/**/*/sessions/ 16 | testdata/ 17 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "useTabs": false, 5 | "tabWidth": 2, 6 | "semi": true, 7 | "bracketSpacing": true, 8 | "trailingComma": "none", 9 | "arrowParens": "avoid" 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Bleenco GmbH https://bleenco.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd/abstruse-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/bleenco/abstruse/server/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /cmd/abstruse-worker/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/bleenco/abstruse/worker/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/.gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Gitea 3 | email = gitea@fake.local 4 | [core] 5 | quotepath = false 6 | commitGraph = true 7 | [gc] 8 | writeCommitGraph = true 9 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/.ssh/environment: -------------------------------------------------------------------------------- 1 | GITEA_CUSTOM=/data/gitea 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/HEAD: -------------------------------------------------------------------------------- 1 | ref: refs/heads/master 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/config: -------------------------------------------------------------------------------- 1 | [core] 2 | repositoryformatversion = 0 3 | filemode = true 4 | bare = true 5 | ignorecase = true 6 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/description: -------------------------------------------------------------------------------- 1 | Unnamed repository; edit this file 'description' to name the repository. 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/applypatch-msg.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to check the commit log message taken by 4 | # applypatch from an e-mail message. 5 | # 6 | # The hook should exit with non-zero status after issuing an 7 | # appropriate message if it wants to stop the commit. The hook is 8 | # allowed to edit the commit message file. 9 | # 10 | # To enable this hook, rename this file to "applypatch-msg". 11 | 12 | . git-sh-setup 13 | commitmsg="$(git rev-parse --git-path hooks/commit-msg)" 14 | test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} 15 | : 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/commit-msg.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to check the commit log message. 4 | # Called by "git commit" with one argument, the name of the file 5 | # that has the commit message. The hook should exit with non-zero 6 | # status after issuing an appropriate message if it wants to stop the 7 | # commit. The hook is allowed to edit the commit message file. 8 | # 9 | # To enable this hook, rename this file to "commit-msg". 10 | 11 | # Uncomment the below to add a Signed-off-by line to the message. 12 | # Doing this in a hook is a bad idea in general, but the prepare-commit-msg 13 | # hook is more suited to it. 14 | # 15 | # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') 16 | # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" 17 | 18 | # This example catches duplicate Signed-off-by lines. 19 | 20 | test "" = "$(grep '^Signed-off-by: ' "$1" | 21 | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { 22 | echo >&2 Duplicate Signed-off-by lines. 23 | exit 1 24 | } 25 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/post-receive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | data=$(cat) 3 | exitcodes="" 4 | hookname=$(basename $0) 5 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 6 | 7 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 8 | test -x "${hook}" && test -f "${hook}" || continue 9 | echo "${data}" | "${hook}" 10 | exitcodes="${exitcodes} $?" 11 | done 12 | 13 | for i in ${exitcodes}; do 14 | [ ${i} -eq 0 ] || exit ${i} 15 | done 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/post-receive.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' post-receive 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/post-update.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to prepare a packed repository for use over 4 | # dumb transports. 5 | # 6 | # To enable this hook, rename this file to "post-update". 7 | 8 | exec git update-server-info 9 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/pre-applypatch.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to verify what is about to be committed 4 | # by applypatch from an e-mail message. 5 | # 6 | # The hook should exit with non-zero status after issuing an 7 | # appropriate message if it wants to stop the commit. 8 | # 9 | # To enable this hook, rename this file to "pre-applypatch". 10 | 11 | . git-sh-setup 12 | precommit="$(git rev-parse --git-path hooks/pre-commit)" 13 | test -x "$precommit" && exec "$precommit" ${1+"$@"} 14 | : 15 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/pre-merge-commit.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to verify what is about to be committed. 4 | # Called by "git merge" with no arguments. The hook should 5 | # exit with non-zero status after issuing an appropriate message to 6 | # stderr if it wants to stop the merge commit. 7 | # 8 | # To enable this hook, rename this file to "pre-merge-commit". 9 | 10 | . git-sh-setup 11 | test -x "$GIT_DIR/hooks/pre-commit" && 12 | exec "$GIT_DIR/hooks/pre-commit" 13 | : 14 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/pre-receive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | data=$(cat) 3 | exitcodes="" 4 | hookname=$(basename $0) 5 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 6 | 7 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 8 | test -x "${hook}" && test -f "${hook}" || continue 9 | echo "${data}" | "${hook}" 10 | exitcodes="${exitcodes} $?" 11 | done 12 | 13 | for i in ${exitcodes}; do 14 | [ ${i} -eq 0 ] || exit ${i} 15 | done 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/pre-receive.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' pre-receive 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/pre-receive.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to make use of push options. 4 | # The example simply echoes all push options that start with 'echoback=' 5 | # and rejects all pushes when the "reject" push option is used. 6 | # 7 | # To enable this hook, rename this file to "pre-receive". 8 | 9 | if test -n "$GIT_PUSH_OPTION_COUNT" 10 | then 11 | i=0 12 | while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" 13 | do 14 | eval "value=\$GIT_PUSH_OPTION_$i" 15 | case "$value" in 16 | echoback=*) 17 | echo "echo from the pre-receive-hook: ${value#*=}" >&2 18 | ;; 19 | reject) 20 | exit 1 21 | esac 22 | i=$((i + 1)) 23 | done 24 | fi 25 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exitcodes="" 3 | hookname=$(basename $0) 4 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 5 | 6 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 7 | test -x "${hook}" && test -f "${hook}" || continue 8 | "${hook}" $1 $2 $3 9 | exitcodes="${exitcodes} $?" 10 | done 11 | 12 | for i in ${exitcodes}; do 13 | [ ${i} -eq 0 ] || exit ${i} 14 | done 15 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/hooks/update.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' update $1 $2 $3 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/info/exclude: -------------------------------------------------------------------------------- 1 | # git ls-files --others --exclude-from=.git/info/exclude 2 | # Lines that start with '#' are comments. 3 | # For a project mostly in C, the following would be a good set of 4 | # exclude patterns (uncomment them if you want to use them): 5 | # *.[oa] 6 | # *~ 7 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/info/refs: -------------------------------------------------------------------------------- 1 | 872e99a0de70656cbac0638953458bbbbf016629 refs/heads/master 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/objects/info/packs: -------------------------------------------------------------------------------- 1 | P pack-240a97588b15c19566b570d8f679902d93b64069.pack 2 | 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/objects/pack/pack-240a97588b15c19566b570d8f679902d93b64069.idx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/objects/pack/pack-240a97588b15c19566b570d8f679902d93b64069.idx -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/objects/pack/pack-240a97588b15c19566b570d8f679902d93b64069.pack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/objects/pack/pack-240a97588b15c19566b570d8f679902d93b64069.pack -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/chisel.git/refs/heads/master: -------------------------------------------------------------------------------- 1 | 872e99a0de70656cbac0638953458bbbbf016629 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/HEAD: -------------------------------------------------------------------------------- 1 | ref: refs/heads/master 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/config: -------------------------------------------------------------------------------- 1 | [core] 2 | repositoryformatversion = 0 3 | filemode = true 4 | bare = true 5 | ignorecase = true 6 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/description: -------------------------------------------------------------------------------- 1 | Unnamed repository; edit this file 'description' to name the repository. 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/applypatch-msg.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to check the commit log message taken by 4 | # applypatch from an e-mail message. 5 | # 6 | # The hook should exit with non-zero status after issuing an 7 | # appropriate message if it wants to stop the commit. The hook is 8 | # allowed to edit the commit message file. 9 | # 10 | # To enable this hook, rename this file to "applypatch-msg". 11 | 12 | . git-sh-setup 13 | commitmsg="$(git rev-parse --git-path hooks/commit-msg)" 14 | test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} 15 | : 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/commit-msg.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to check the commit log message. 4 | # Called by "git commit" with one argument, the name of the file 5 | # that has the commit message. The hook should exit with non-zero 6 | # status after issuing an appropriate message if it wants to stop the 7 | # commit. The hook is allowed to edit the commit message file. 8 | # 9 | # To enable this hook, rename this file to "commit-msg". 10 | 11 | # Uncomment the below to add a Signed-off-by line to the message. 12 | # Doing this in a hook is a bad idea in general, but the prepare-commit-msg 13 | # hook is more suited to it. 14 | # 15 | # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') 16 | # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" 17 | 18 | # This example catches duplicate Signed-off-by lines. 19 | 20 | test "" = "$(grep '^Signed-off-by: ' "$1" | 21 | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { 22 | echo >&2 Duplicate Signed-off-by lines. 23 | exit 1 24 | } 25 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/post-receive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | data=$(cat) 3 | exitcodes="" 4 | hookname=$(basename $0) 5 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 6 | 7 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 8 | test -x "${hook}" && test -f "${hook}" || continue 9 | echo "${data}" | "${hook}" 10 | exitcodes="${exitcodes} $?" 11 | done 12 | 13 | for i in ${exitcodes}; do 14 | [ ${i} -eq 0 ] || exit ${i} 15 | done 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/post-receive.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' post-receive 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/post-update.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to prepare a packed repository for use over 4 | # dumb transports. 5 | # 6 | # To enable this hook, rename this file to "post-update". 7 | 8 | exec git update-server-info 9 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/pre-applypatch.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to verify what is about to be committed 4 | # by applypatch from an e-mail message. 5 | # 6 | # The hook should exit with non-zero status after issuing an 7 | # appropriate message if it wants to stop the commit. 8 | # 9 | # To enable this hook, rename this file to "pre-applypatch". 10 | 11 | . git-sh-setup 12 | precommit="$(git rev-parse --git-path hooks/pre-commit)" 13 | test -x "$precommit" && exec "$precommit" ${1+"$@"} 14 | : 15 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/pre-merge-commit.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to verify what is about to be committed. 4 | # Called by "git merge" with no arguments. The hook should 5 | # exit with non-zero status after issuing an appropriate message to 6 | # stderr if it wants to stop the merge commit. 7 | # 8 | # To enable this hook, rename this file to "pre-merge-commit". 9 | 10 | . git-sh-setup 11 | test -x "$GIT_DIR/hooks/pre-commit" && 12 | exec "$GIT_DIR/hooks/pre-commit" 13 | : 14 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/pre-receive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | data=$(cat) 3 | exitcodes="" 4 | hookname=$(basename $0) 5 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 6 | 7 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 8 | test -x "${hook}" && test -f "${hook}" || continue 9 | echo "${data}" | "${hook}" 10 | exitcodes="${exitcodes} $?" 11 | done 12 | 13 | for i in ${exitcodes}; do 14 | [ ${i} -eq 0 ] || exit ${i} 15 | done 16 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/pre-receive.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' pre-receive 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/pre-receive.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to make use of push options. 4 | # The example simply echoes all push options that start with 'echoback=' 5 | # and rejects all pushes when the "reject" push option is used. 6 | # 7 | # To enable this hook, rename this file to "pre-receive". 8 | 9 | if test -n "$GIT_PUSH_OPTION_COUNT" 10 | then 11 | i=0 12 | while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" 13 | do 14 | eval "value=\$GIT_PUSH_OPTION_$i" 15 | case "$value" in 16 | echoback=*) 17 | echo "echo from the pre-receive-hook: ${value#*=}" >&2 18 | ;; 19 | reject) 20 | exit 1 21 | esac 22 | i=$((i + 1)) 23 | done 24 | fi 25 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exitcodes="" 3 | hookname=$(basename $0) 4 | GIT_DIR=${GIT_DIR:-$(dirname $0)} 5 | 6 | for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do 7 | test -x "${hook}" && test -f "${hook}" || continue 8 | "${hook}" $1 $2 $3 9 | exitcodes="${exitcodes} $?" 10 | done 11 | 12 | for i in ${exitcodes}; do 13 | [ ${i} -eq 0 ] || exit ${i} 14 | done 15 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/hooks/update.d/gitea: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | "/app/gitea/gitea" hook --config='/data/gitea/conf/app.ini' update $1 $2 $3 3 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/info/exclude: -------------------------------------------------------------------------------- 1 | # git ls-files --others --exclude-from=.git/info/exclude 2 | # Lines that start with '#' are comments. 3 | # For a project mostly in C, the following would be a good set of 4 | # exclude patterns (uncomment them if you want to use them): 5 | # *.[oa] 6 | # *~ 7 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/info/refs: -------------------------------------------------------------------------------- 1 | ce382e7f0e87e08eed171b74218242a580548727 refs/heads/master 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/06/7e8657dcd509c2e63376eb64c17fbc218dcdf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/06/7e8657dcd509c2e63376eb64c17fbc218dcdf2 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/0e/117226e9611523c1bd75611a497294c34a89ee: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/0e/117226e9611523c1bd75611a497294c34a89ee -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/0f/449daa627f17a95f1feca1b6a2bdffe035a354: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/0f/449daa627f17a95f1feca1b6a2bdffe035a354 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/1d/9d875edb469786a9c6dbae5aaeef9a3bcb2c33: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/1d/9d875edb469786a9c6dbae5aaeef9a3bcb2c33 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/23/dac78c3317010b4851964fc0dff362fc40dd87: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/23/dac78c3317010b4851964fc0dff362fc40dd87 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/45/9f7a9284ba653a382d73bd08dbff0ce48c04bd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/45/9f7a9284ba653a382d73bd08dbff0ce48c04bd -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/49/4f47baeda0f20be99ceca28973a5b4e2639fac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/49/4f47baeda0f20be99ceca28973a5b4e2639fac -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/5e/331c4a57c0fbd6b3f3b0c44e23b969b815ab5c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/5e/331c4a57c0fbd6b3f3b0c44e23b969b815ab5c -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/61/2c0b44b5a2569f8392b391b571f5b0cf38d822: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/61/2c0b44b5a2569f8392b391b571f5b0cf38d822 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/64/4b14725c53c94d515e58e60cf55b45d2b0387d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/64/4b14725c53c94d515e58e60cf55b45d2b0387d -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/66/fe6594c1a643e6d9d3ac655948804543f361db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/66/fe6594c1a643e6d9d3ac655948804543f361db -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/6e/0c2d4ca40cff19e81e7ccc540f83599ac46ba4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/6e/0c2d4ca40cff19e81e7ccc540f83599ac46ba4 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/6f/dd39e7e47bb01e92fdacd36aa510aa61dbe94a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/6f/dd39e7e47bb01e92fdacd36aa510aa61dbe94a -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/75/704c60b07c63ca3c23f7558669a86ee046b1b6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/75/704c60b07c63ca3c23f7558669a86ee046b1b6 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/7e/02de72ffb166c8102057246b26b07f15fe0d3f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/7e/02de72ffb166c8102057246b26b07f15fe0d3f -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/8e/1c6452d41d7a45d0b16d5f711befdbbe2c0320: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/8e/1c6452d41d7a45d0b16d5f711befdbbe2c0320 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/94/65c94d506140766fca573414c9819a8cd326bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/94/65c94d506140766fca573414c9819a8cd326bc -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/94/dba4cd133625a3a9a8d8fe1fdc3e9fc116d79e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/94/dba4cd133625a3a9a8d8fe1fdc3e9fc116d79e -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/9b/160ccb0fe44106a5f535e4bf2ee8fade9c7457: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/9b/160ccb0fe44106a5f535e4bf2ee8fade9c7457 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/9f/ec0d70b748bd8292f43d32612948c0b134296e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/9f/ec0d70b748bd8292f43d32612948c0b134296e -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a2/8f4dc019162842bd5b211ccab3938a4c869058: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a2/8f4dc019162842bd5b211ccab3938a4c869058 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a2/9d30d933cc3b0f8ac921bb30912ae8d2eb0ac8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a2/9d30d933cc3b0f8ac921bb30912ae8d2eb0ac8 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a8/a375133818257773488e4d99a2423b5d87da0e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/a8/a375133818257773488e4d99a2423b5d87da0e -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b2/6adb425bcdc41d853a4a99d666f7e5922fc412: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b2/6adb425bcdc41d853a4a99d666f7e5922fc412 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b6/640f6e51b9e54d757685915363dec6102c3c31: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b6/640f6e51b9e54d757685915363dec6102c3c31 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b8/3008725f2e4de6ed0eb82a3906c15a6bab36dc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/b8/3008725f2e4de6ed0eb82a3906c15a6bab36dc -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ca/77fb843d6016f246237cf416116c7c692661ac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ca/77fb843d6016f246237cf416116c7c692661ac -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ce/382e7f0e87e08eed171b74218242a580548727: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ce/382e7f0e87e08eed171b74218242a580548727 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/d5/186b0fd377a7c1598297bcdc7fea5025dd318b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/d5/186b0fd377a7c1598297bcdc7fea5025dd318b -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/da/db4b56294c5feae8eb8cde4ac1bacd4218f6dc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/da/db4b56294c5feae8eb8cde4ac1bacd4218f6dc -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/df/b770e6519e1e0606eb65dc09de0871078ab8ca: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/df/b770e6519e1e0606eb65dc09de0871078ab8ca -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/e0/523379a7c09728f497fd99fb534fca7f740e62: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/e0/523379a7c09728f497fd99fb534fca7f740e62 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ea/78036835f061e9b31853d1649ac5f9bd522ff5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/ea/78036835f061e9b31853d1649ac5f9bd522ff5 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/eb/966e2602a8d73a9b2dd488c0ade54d84baa405: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/eb/966e2602a8d73a9b2dd488c0ade54d84baa405 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/f6/e575b38b60c0bee86677480861c4e474400d09: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/f6/e575b38b60c0bee86677480861c4e474400d09 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/fb/6a8a9e1aa5815c8eb7831eef10f0267d803b62: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/fb/6a8a9e1aa5815c8eb7831eef10f0267d803b62 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/objects/info/packs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/git/repositories/gitea/d3-bundle.git/refs/heads/master: -------------------------------------------------------------------------------- 1 | ce382e7f0e87e08eed171b74218242a580548727 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/gitea/avatars/afa79842299060b5ee62d1566448cd42: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/gitea/avatars/afa79842299060b5ee62d1566448cd42 -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/gitea/avatars/c3a8e0afa692c2437d775e44b59082aa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/gitea/avatars/c3a8e0afa692c2437d775e44b59082aa -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/gitea/gitea.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bleenco/abstruse/b28dd99d7f1b8e163a1dce0b55cf02a36f0cf30a/configs/testing/e2e/data/gitea/gitea/gitea.db -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_dsa_key.pub: -------------------------------------------------------------------------------- 1 | ssh-dss AAAAB3NzaC1kc3MAAACBAOGfq8V8IU07Nc4zQC6MtUyLx5wdhGWedm3qlWHT7UUovP+e+xt0Rf8Z/V8uoTB4nBDKA7juby7gifEvWfrzd/y6BqbIP9poD5l+jNAzQIPB2r0W4Grfw6ZLFnC1LB+PQEGaMm2Y5y8u6HVQzxV9BdUCeaoN5UhXTDr4pt0IYyeJAAAAFQDep7rcUupZTfuwikZDR1TmYai2DQAAAIBpw6aPEUdiQ2qvarl604KGEQ9f+mCPQT+6IA97T6/znayerwzCaUhZJ8Kkup7ztjzqw7evUdQntwNp9MY59J98oLSxpK4msX15vX4wec9Z/NI43HoYsctAQgukBWs9IP4XUqPTWdt3Ka5KfkEV6MYka8Zty31q1HvABrIXexU6fAAAAIAcBOfCaUkH9XP4uxLAdUIS51k8/7b7TGr/RyTJiBvBPyyNnn8Vxd8gm1X1KAZ53mwYapSl+mYED31Srgb3EOd3S0JedOJY/e0RTJwiKuv41G9pQ7XW2gVHiLUkKVyuxfSuJf/x/EGeJk0fgMRhaC9Ud0dCmEc6fLcI3BPwpu+TUA== root@4a37bd2d0f91 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_ecdsa_key: -------------------------------------------------------------------------------- 1 | -----BEGIN OPENSSH PRIVATE KEY----- 2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS 3 | 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQoSEMVoE2wrze0aUdqN5qhPY9UDKp6 4 | 2tQEbVswbtzV3D5BygdfmI7Cu6KKGqvRdvLM9RLasV2yt2n4xAvVMz8EAAAAsFad3fhWnd 5 | 34AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBChIQxWgTbCvN7Rp 6 | R2o3mqE9j1QMqnra1ARtWzBu3NXcPkHKB1+YjsK7oooaq9F28sz1EtqxXbK3afjEC9UzPw 7 | QAAAAhAJfBv477skQzc+dtwN0T3ioA2aZGQtmJ9B8SiPxiBEKNAAAAEXJvb3RANGEzN2Jk 8 | MmQwZjkxAQIDBAUG 9 | -----END OPENSSH PRIVATE KEY----- 10 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_ecdsa_key.pub: -------------------------------------------------------------------------------- 1 | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBChIQxWgTbCvN7RpR2o3mqE9j1QMqnra1ARtWzBu3NXcPkHKB1+YjsK7oooaq9F28sz1EtqxXbK3afjEC9UzPwQ= root@4a37bd2d0f91 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_ed25519_key: -------------------------------------------------------------------------------- 1 | -----BEGIN OPENSSH PRIVATE KEY----- 2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW 3 | QyNTUxOQAAACCF/Qjua5JUTB73iFM0AWKablT3xxJvkMxklt6BqQVNrgAAAJigZegtoGXo 4 | LQAAAAtzc2gtZWQyNTUxOQAAACCF/Qjua5JUTB73iFM0AWKablT3xxJvkMxklt6BqQVNrg 5 | AAAECdEkCeskyuZ8tSYtklnQfxPd9sAOEeWUDQX4LB4spxXIX9CO5rklRMHveIUzQBYppu 6 | VPfHEm+QzGSW3oGpBU2uAAAAEXJvb3RANGEzN2JkMmQwZjkxAQIDBA== 7 | -----END OPENSSH PRIVATE KEY----- 8 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_ed25519_key.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIX9CO5rklRMHveIUzQBYppuVPfHEm+QzGSW3oGpBU2u root@4a37bd2d0f91 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea/ssh/ssh_host_rsa_key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMseyFuyMAVteCMHdn8wydeXnAhzKiFKWbn4zpaCJo7E4REYm5ERuTNFLJ1VId8T7+w9JyMwDtgy/jsEs5HxBfa7NXoWYZJvlUnSGHLozyOKeTJGIXmGk49+B8DiZ588U05QP6YmZlTlb2++TOdt6TuIfx/72pUbFajMLAgZdTcBqBvabhC7hWe0PTf5ptbmA4IugN2Uir0dNevmIj133sOVSHvOdigzsfzk0EPxxNgjenepYW8LfJh59m2rDF6EhkDYZ7xjh4gRX4tTaMzbFHgOKz+TCTr1BT4AOVu97x6YVgcgJUL2k75jpTukLVCFpUeKJBwn8aBuYwZuYhs3CX root@4a37bd2d0f91 2 | -------------------------------------------------------------------------------- /configs/testing/e2e/data/gitea_credentials.txt: -------------------------------------------------------------------------------- 1 | url: http://10.20.20.50:3200/ 2 | username: gitea 3 | password: Gitea321! 4 | access_token: 868615bbceac2bbcf02037709a82eae9e32fc519 5 | secret: 6256a5206ef 6 | 7 | // misc commands 8 | git update-index --assume-unchanged configs/testing/e2e/data/gitea/gitea/gitea.db 9 | -------------------------------------------------------------------------------- /internal/auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | // JWT is exposed JWT authenticator with middlewares 9 | // to verify access tokens. 10 | var JWT *JWTAuth 11 | 12 | var ( 13 | // JWTSecret secred from config for signing tokens. 14 | JWTSecret []byte 15 | ) 16 | 17 | // Init authentication constants from config. 18 | func Init(secret string) { 19 | JWTSecret = []byte(secret) 20 | JWT = NewJWTAuth("HS256") 21 | } 22 | 23 | func fatal(msg interface{}) { 24 | fmt.Println(msg) 25 | os.Exit(1) 26 | } 27 | -------------------------------------------------------------------------------- /internal/auth/bcrypt.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "golang.org/x/crypto/bcrypt" 5 | ) 6 | 7 | // Password defines password to be hashed. 8 | type Password struct { 9 | Password string 10 | Cost int 11 | } 12 | 13 | // HashPassword generates encrypted password from password string 14 | func HashPassword(passwd Password) (string, error) { 15 | if passwd.Cost == 0 { 16 | passwd.Cost = bcrypt.DefaultCost 17 | } 18 | bytes, err := bcrypt.GenerateFromPassword([]byte(passwd.Password), passwd.Cost) 19 | return string(bytes), err 20 | } 21 | 22 | // CheckPasswordHash compares password string with encrypted hash. 23 | func CheckPasswordHash(password, hash string) bool { 24 | err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) 25 | return err == nil 26 | } 27 | -------------------------------------------------------------------------------- /internal/auth/grpc.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "context" 4 | 5 | // Authentication holds the identifier/jwt token credentials. 6 | type Authentication struct { 7 | Identifier string 8 | JWT string 9 | } 10 | 11 | // GetRequestMetadata gets the current request metadata. 12 | func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { 13 | return map[string]string{ 14 | "identifier": a.Identifier, 15 | "jwt": a.JWT, 16 | }, nil 17 | } 18 | 19 | // RequireTransportSecurity indicates whether the credentials requires transport security. 20 | func (a *Authentication) RequireTransportSecurity() bool { 21 | return true 22 | } 23 | -------------------------------------------------------------------------------- /internal/auth/htpasswd.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/bleenco/abstruse/pkg/fs" 7 | ) 8 | 9 | func generateHtpasswdFile(filePath, user, password string) error { 10 | passwd, err := HashPassword(Password{Password: password, Cost: 1}) 11 | if err != nil { 12 | return err 13 | } 14 | creds := fmt.Sprintf("%s:%s\n", user, passwd) 15 | return fs.WriteFile(filePath, creds) 16 | } 17 | -------------------------------------------------------------------------------- /internal/auth/worker.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "fmt" 5 | 6 | jwt "github.com/dgrijalva/jwt-go" 7 | ) 8 | 9 | // GenerateWorkerJWT generates workers json web token. 10 | func GenerateWorkerJWT(id string) (string, error) { 11 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ 12 | "identifier": id, 13 | }) 14 | 15 | return token.SignedString(JWTSecret) 16 | } 17 | 18 | // GetWorkerIdentifierByJWT return workers id by token string. 19 | func GetWorkerIdentifierByJWT(token string) (string, error) { 20 | var id string 21 | 22 | if token == "" { 23 | return id, fmt.Errorf("invalid token") 24 | } 25 | 26 | t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { 27 | if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { 28 | return nil, fmt.Errorf("Unexpected signing method: %v", t.Header["alg"]) 29 | } 30 | 31 | return JWTSecret, nil 32 | }) 33 | if err != nil { 34 | return id, err 35 | } 36 | 37 | if claims, ok := t.Claims.(jwt.MapClaims); ok && t.Valid { 38 | id = claims["identifier"].(string) 39 | } 40 | 41 | return id, nil 42 | } 43 | -------------------------------------------------------------------------------- /pkg/gitscm/types.go: -------------------------------------------------------------------------------- 1 | package gitscm 2 | 3 | // HookForm struct for saving webhooks. 4 | type HookForm struct { 5 | Branch bool `json:"branch" valid:"required"` 6 | Push bool `json:"push" valid:"required"` 7 | PullRequest bool `json:"pullRequest" valid:"required"` 8 | Tag bool `json:"tag" valid:"required"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/lib/id.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | // ID returns new uuid in string format. 8 | func ID() string { 9 | return uuid.New().String() 10 | } 11 | -------------------------------------------------------------------------------- /pkg/lib/json.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io" 7 | ) 8 | 9 | // DecodeJSON is a convenience function to create a JSON decoder 10 | // set it up to disallow unknown fields and then decode into the 11 | // given value. 12 | func DecodeJSON(data io.Reader, out interface{}) error { 13 | if data == nil { 14 | return io.EOF 15 | } 16 | 17 | decoder := json.NewDecoder(data) 18 | decoder.DisallowUnknownFields() 19 | return decoder.Decode(&out) 20 | } 21 | 22 | // UnmarshalJSON is a convenience function around calling DecodeJSON. 23 | func UnmarshalJSON(data []byte, out interface{}) error { 24 | return DecodeJSON(bytes.NewReader(data), out) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/lib/rand.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // RandomString returns random string. 9 | func RandomString() string { 10 | b := make([]byte, 4) 11 | rand.Read(b) 12 | return fmt.Sprintf("%x", b) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/lib/tcp_wait.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | ) 8 | 9 | // WaitTCP is used to wait for external service is available on specific host and port. 10 | func WaitTCP(duration time.Duration, host string, port int) error { 11 | timeout := time.After(duration) 12 | tick := time.Tick(1 * time.Second) 13 | host = fmt.Sprintf("%s:%d", host, port) 14 | for { 15 | select { 16 | case <-timeout: 17 | return fmt.Errorf("timed out") 18 | case <-tick: 19 | conn, err := net.DialTimeout("tcp", host, 500*time.Millisecond) 20 | if err == nil { 21 | conn.Close() 22 | return nil 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pkg/lib/time.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // FormatTime returns DB compatible datetime string. 8 | func FormatTime(t time.Time) string { 9 | if t.IsZero() { 10 | return "0000-00-00 00:00:00" 11 | } 12 | 13 | return t.Format("2006-01-02 15:04:05") 14 | } 15 | 16 | // ParseTime returns time.Time from string. 17 | func ParseTime(str string) time.Time { 18 | t, err := time.Parse("2006-01-02 15:04:05", str) 19 | if err != nil { 20 | return time.Now() 21 | } 22 | return t 23 | } 24 | 25 | // TimeNow returns current datetime. 26 | func TimeNow() *time.Time { 27 | return func(t time.Time) *time.Time { return &t }(time.Now()) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/stats/cpu.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import "github.com/shirou/gopsutil/cpu" 4 | 5 | func getCPUPercent() int32 { 6 | percent, err := cpu.Percent(0, true) 7 | if err != nil { 8 | return 0 9 | } 10 | total := func() int { 11 | var t float64 12 | for _, p := range percent { 13 | t += p 14 | } 15 | return int(int(t) / len(percent)) 16 | }() 17 | 18 | return int32(total) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/stats/mem.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import "github.com/shirou/gopsutil/mem" 4 | 5 | func getMemoryPercent() int32 { 6 | stat, err := mem.VirtualMemory() 7 | if err != nil { 8 | return 0 9 | } 10 | return int32(stat.UsedPercent) 11 | } 12 | -------------------------------------------------------------------------------- /pkg/stats/stats.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import "github.com/shirou/gopsutil/host" 4 | 5 | // GetUsageStats returns system utilization stats. 6 | func GetUsageStats() (int32, int32) { 7 | return getCPUPercent(), getMemoryPercent() 8 | } 9 | 10 | // GetHostStats returns system information. 11 | func GetHostStats() (*host.InfoStat, error) { 12 | return host.Info() 13 | } 14 | -------------------------------------------------------------------------------- /server/api/badge/badge.go: -------------------------------------------------------------------------------- 1 | package badge 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | "github.com/go-chi/chi" 9 | "github.com/narqo/go-badge" 10 | ) 11 | 12 | // HandleBadge returns an http.HandlerFunc that writes SVG status build 13 | // icon to the http response body. 14 | func HandleBadge(builds core.BuildStore) http.HandlerFunc { 15 | return func(w http.ResponseWriter, r *http.Request) { 16 | token := chi.URLParam(r, "token") 17 | branch := r.URL.Query().Get("branch") 18 | 19 | status, err := builds.FindStatus(token, branch) 20 | if err != nil { 21 | status = core.BuildStatusUnknown 22 | } 23 | color := "#555555" 24 | if status == core.BuildStatusPassing { 25 | color = "#48bb78" 26 | } else if status == core.BuildStatusFailing { 27 | color = "#e74c3c" 28 | } else if status == core.BuildStatusRunning { 29 | color = "#ecc94b" 30 | } 31 | 32 | svg, err := badge.RenderBytes("build", status, badge.Color(color)) 33 | if err != nil { 34 | render.InternalServerError(w, err.Error()) 35 | return 36 | } 37 | 38 | w.Header().Set("Content-Type", "image/svg+xml") 39 | w.Write(svg) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/api/build/find.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleFind returns an http.HandlerFunc that writes JSON encoded 14 | // result of build to the http response. 15 | func HandleFind(builds core.BuildStore) http.HandlerFunc { 16 | return func(w http.ResponseWriter, r *http.Request) { 17 | claims := middlewares.ClaimsFromCtx(r.Context()) 18 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 19 | if err != nil { 20 | render.BadRequestError(w, err.Error()) 21 | return 22 | } 23 | 24 | build, err := builds.FindUser(uint(id), claims.ID) 25 | if err != nil { 26 | render.NotFoundError(w, err.Error()) 27 | return 28 | } 29 | 30 | render.JSON(w, http.StatusOK, build) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/api/build/find_job.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleFindJob returns http.handlerFunc that writes JSON encoded 14 | // job result to the http response body. 15 | func HandleFindJob(jobs core.JobStore, scheduler core.Scheduler) http.HandlerFunc { 16 | type resp struct { 17 | *core.Job 18 | Log string `json:"log"` 19 | } 20 | 21 | return func(w http.ResponseWriter, r *http.Request) { 22 | claims := middlewares.ClaimsFromCtx(r.Context()) 23 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 24 | if err != nil { 25 | render.BadRequestError(w, err.Error()) 26 | return 27 | } 28 | 29 | job, err := jobs.FindUser(uint(id), claims.ID) 30 | if err != nil { 31 | render.NotFoundError(w, err.Error()) 32 | return 33 | } 34 | 35 | if currentLog, err := scheduler.JobLog(uint(id)); err == nil { 36 | job.Log = currentLog 37 | } 38 | 39 | render.JSON(w, http.StatusOK, resp{job, job.Log}) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/api/provider/find.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleFind writes JSON encoded provider data to the http response body. 14 | func HandleFind(providers core.ProviderStore, users core.UserStore) http.HandlerFunc { 15 | return func(w http.ResponseWriter, r *http.Request) { 16 | claims := middlewares.ClaimsFromCtx(r.Context()) 17 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 18 | if err != nil { 19 | render.InternalServerError(w, err.Error()) 20 | return 21 | } 22 | 23 | user, err := users.Find(claims.ID) 24 | if err != nil { 25 | render.UnathorizedError(w, err.Error()) 26 | return 27 | } 28 | 29 | provider, err := providers.Find(uint(id)) 30 | if err != nil { 31 | render.InternalServerError(w, err.Error()) 32 | return 33 | } 34 | 35 | if provider.UserID == claims.ID || user.Role == "admin" { 36 | render.JSON(w, http.StatusOK, provider) 37 | } 38 | 39 | render.UnathorizedError(w, err.Error()) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/api/provider/listuser.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/middlewares" 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | ) 10 | 11 | // HandleListUser returns http.HandlerFunc that writes JSON encoded 12 | // list of providers based on user id to http response body. 13 | func HandleListUser(providers core.ProviderStore) http.HandlerFunc { 14 | return func(w http.ResponseWriter, r *http.Request) { 15 | claims := middlewares.ClaimsFromCtx(r.Context()) 16 | 17 | providers, err := providers.ListUser(claims.ID) 18 | if err != nil { 19 | render.InternalServerError(w, err.Error()) 20 | return 21 | } 22 | 23 | render.JSON(w, http.StatusOK, providers) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /server/api/render/errors.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // InternalServerError helper. 8 | func InternalServerError(w http.ResponseWriter, msg string) { 9 | JSON(w, http.StatusInternalServerError, Error{Message: msg}) 10 | } 11 | 12 | // UnathorizedError helper. 13 | func UnathorizedError(w http.ResponseWriter, msg string) { 14 | JSON(w, http.StatusUnauthorized, Error{Message: msg}) 15 | } 16 | 17 | // NotFoundError helper. 18 | func NotFoundError(w http.ResponseWriter, msg string) { 19 | JSON(w, http.StatusNotFound, Error{Message: msg}) 20 | } 21 | 22 | // ForbiddenError helper. 23 | func ForbiddenError(w http.ResponseWriter, msg string) { 24 | JSON(w, http.StatusForbidden, Error{Message: msg}) 25 | } 26 | 27 | // BadRequestError helper. 28 | func BadRequestError(w http.ResponseWriter, msg string) { 29 | JSON(w, http.StatusBadRequest, Error{Message: msg}) 30 | } 31 | -------------------------------------------------------------------------------- /server/api/render/render.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "net/http" 7 | ) 8 | 9 | // JSON render encodes given data to JSON and writes it to response. 10 | func JSON(w http.ResponseWriter, status int, v interface{}) { 11 | buf := &bytes.Buffer{} 12 | enc := json.NewEncoder(buf) 13 | enc.SetEscapeHTML(true) 14 | if err := enc.Encode(v); err != nil { 15 | http.Error(w, err.Error(), http.StatusInternalServerError) 16 | return 17 | } 18 | 19 | w.Header().Set("Content-Type", "application/json; charset=utf-8") 20 | w.WriteHeader(status) 21 | w.Write(buf.Bytes()) 22 | } 23 | -------------------------------------------------------------------------------- /server/api/render/types.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | // Empty represents an empty response. 4 | type Empty struct{} 5 | 6 | // Error represents a JSON encoded API error. 7 | type Error struct { 8 | Message string `json:"message"` 9 | } 10 | 11 | type BoolResponse struct { 12 | Status bool `json:"status"` 13 | } 14 | -------------------------------------------------------------------------------- /server/api/repo/find.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleFind returns an http.HandlerFunc that writes JSON encoded 14 | // repository result to the http response body. 15 | func HandleFind(repos core.RepositoryStore) http.HandlerFunc { 16 | return func(w http.ResponseWriter, r *http.Request) { 17 | claims := middlewares.ClaimsFromCtx(r.Context()) 18 | 19 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 20 | if err != nil { 21 | render.InternalServerError(w, err.Error()) 22 | return 23 | } 24 | 25 | repo, err := repos.Find(uint(id), claims.ID) 26 | if err != nil { 27 | render.NotFoundError(w, err.Error()) 28 | return 29 | } 30 | 31 | render.JSON(w, http.StatusOK, repo) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server/api/repo/list_hooks.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleListHooks returns an http.HandlerFunc that writes JSON encoded 14 | // list of hooks to the http response body. 15 | func HandleListHooks(repos core.RepositoryStore) http.HandlerFunc { 16 | return func(w http.ResponseWriter, r *http.Request) { 17 | claims := middlewares.ClaimsFromCtx(r.Context()) 18 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 19 | if err != nil { 20 | render.InternalServerError(w, err.Error()) 21 | return 22 | } 23 | 24 | hooks, err := repos.ListHooks(uint(id), claims.ID) 25 | if err != nil { 26 | render.NotFoundError(w, err.Error()) 27 | return 28 | } 29 | 30 | render.JSON(w, http.StatusOK, hooks) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/api/repo/list_mount.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/middlewares" 8 | "github.com/bleenco/abstruse/server/api/render" 9 | "github.com/bleenco/abstruse/server/core" 10 | "github.com/go-chi/chi" 11 | ) 12 | 13 | // HandleListMount returns http.HandlerFunc that writes JSON encoded 14 | // list of env variables for repository to the http response body. 15 | func HandleListMount(mounts core.MountsStore, repos core.RepositoryStore) http.HandlerFunc { 16 | return func(w http.ResponseWriter, r *http.Request) { 17 | claims := middlewares.ClaimsFromCtx(r.Context()) 18 | 19 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 20 | if err != nil { 21 | render.InternalServerError(w, err.Error()) 22 | return 23 | } 24 | 25 | if perm := repos.GetPermissions(uint(id), claims.ID); !perm.Read { 26 | render.UnathorizedError(w, "permission denied") 27 | return 28 | } 29 | 30 | mts, err := mounts.List(uint(id)) 31 | if err != nil { 32 | render.InternalServerError(w, err.Error()) 33 | return 34 | } 35 | 36 | render.JSON(w, http.StatusOK, mts) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /server/api/setup/ready.go: -------------------------------------------------------------------------------- 1 | package setup 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // HandleReady returns an http.HandlerFunc that writes JSON encoded 11 | // status to the http response body. 12 | func HandleReady(users core.UserStore) http.HandlerFunc { 13 | type resp struct { 14 | User bool `json:"user"` 15 | } 16 | 17 | return func(w http.ResponseWriter, r *http.Request) { 18 | res, err := users.List() 19 | if err != nil { 20 | render.InternalServerError(w, err.Error()) 21 | return 22 | } 23 | user := false 24 | if len(res) > 0 { 25 | user = true 26 | } 27 | 28 | render.JSON(w, http.StatusOK, resp{User: user}) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/api/stats/jobs.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | ) 10 | 11 | // HandleJobs returns an http.HandlerFunc that writes JSON encoded 12 | // result about jobs statistics to the http response body. 13 | func HandleJobs(jobs core.JobStore) http.HandlerFunc { 14 | return func(w http.ResponseWriter, r *http.Request) { 15 | layout := "2006-01-02" 16 | from := r.URL.Query().Get("from") 17 | to := r.URL.Query().Get("to") 18 | 19 | tfrom, err := time.Parse(layout, from) 20 | if err != nil { 21 | tfrom = time.Now().AddDate(0, 0, -7) 22 | } 23 | tto, err := time.Parse(layout, to) 24 | if err != nil { 25 | tto = time.Now() 26 | } 27 | 28 | tfrom = time.Date(tfrom.Year(), tfrom.Month(), tfrom.Day(), 0, 0, 0, 0, time.UTC) 29 | tto = time.Date(tto.Year(), tto.Month(), tto.Day(), 23, 59, 59, 0, time.UTC) 30 | 31 | jobs, err := jobs.List(tfrom, tto) 32 | if err != nil { 33 | render.InternalServerError(w, err.Error()) 34 | return 35 | } 36 | 37 | render.JSON(w, http.StatusOK, jobs) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /server/api/stats/pause.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/middlewares" 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | ) 10 | 11 | // HandlePause returns an http.HandlerFunc which writes JSON encoded 12 | // result about pausing scheduler to the http response body 13 | func HandlePause(users core.UserStore, scheduler core.Scheduler) http.HandlerFunc { 14 | return func(w http.ResponseWriter, r *http.Request) { 15 | claims := middlewares.ClaimsFromCtx(r.Context()) 16 | 17 | if user, err := users.Find(claims.ID); err != nil || user.Role != "admin" { 18 | render.UnathorizedError(w, err.Error()) 19 | return 20 | } 21 | 22 | if err := scheduler.Pause(); err != nil { 23 | render.InternalServerError(w, err.Error()) 24 | return 25 | } 26 | 27 | render.JSON(w, http.StatusOK, render.Empty{}) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /server/api/stats/resume.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/middlewares" 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | ) 10 | 11 | // HandleResume returns an http.HandlerFunc which writes JSON encoded 12 | // result about resuming scheduler to the http response body 13 | func HandleResume(users core.UserStore, scheduler core.Scheduler) http.HandlerFunc { 14 | return func(w http.ResponseWriter, r *http.Request) { 15 | claims := middlewares.ClaimsFromCtx(r.Context()) 16 | 17 | if user, err := users.Find(claims.ID); err != nil || user.Role != "admin" { 18 | render.UnathorizedError(w, err.Error()) 19 | return 20 | } 21 | 22 | if err := scheduler.Resume(); err != nil { 23 | render.InternalServerError(w, err.Error()) 24 | return 25 | } 26 | 27 | render.JSON(w, http.StatusOK, render.Empty{}) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /server/api/stats/stats.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // HandleStats returns an http.HandlerFunc that writes JSON encoded 11 | // server stats to the http response body. 12 | func HandleStats(stats core.StatsService) http.HandlerFunc { 13 | type resp struct { 14 | Usage []core.Usage `json:"usage"` 15 | Stats []core.SchedulerStats `json:"stats"` 16 | Status bool `json:"status"` 17 | } 18 | 19 | return func(w http.ResponseWriter, r *http.Request) { 20 | usage, statistics := stats.GetHistory() 21 | status := stats.SchedulerStatus() 22 | render.JSON(w, http.StatusOK, resp{usage, statistics, status}) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /server/api/system/version.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/internal/version" 7 | "github.com/bleenco/abstruse/server/api/render" 8 | ) 9 | 10 | // HandleVersion returns an http.HandlerFunc that writes JSON 11 | // encoded version data to the http response body. 12 | func HandleVersion() http.HandlerFunc { 13 | return func(w http.ResponseWriter, r *http.Request) { 14 | render.JSON(w, http.StatusOK, version.GetBuildInfo()) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /server/api/team/find.go: -------------------------------------------------------------------------------- 1 | package team 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | "github.com/go-chi/chi" 10 | ) 11 | 12 | // HandleFind returns an http.HandlerFunc that writes JSON encoded 13 | // team result to the http response body. 14 | func HandleFind(teams core.TeamStore) http.HandlerFunc { 15 | return func(w http.ResponseWriter, r *http.Request) { 16 | id, err := strconv.Atoi(chi.URLParam(r, "id")) 17 | if err != nil { 18 | render.InternalServerError(w, err.Error()) 19 | return 20 | } 21 | 22 | team, err := teams.Find(uint(id)) 23 | if err != nil { 24 | render.NotFoundError(w, err.Error()) 25 | return 26 | } 27 | 28 | render.JSON(w, http.StatusOK, team) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/api/team/list.go: -------------------------------------------------------------------------------- 1 | package team 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // HandleList returns an http.HandlerFunc that writes JSON encoded 11 | // teams result to the http response body. 12 | func HandleList(teams core.TeamStore) http.HandlerFunc { 13 | return func(w http.ResponseWriter, r *http.Request) { 14 | teams, err := teams.List() 15 | if err != nil { 16 | render.InternalServerError(w, err.Error()) 17 | return 18 | } 19 | 20 | render.JSON(w, http.StatusOK, teams) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /server/api/user/list.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // HandleList returns an http.HandlerFunc that writes JSON encoded 11 | // list of users to the http response body. 12 | func HandleList(users core.UserStore) http.HandlerFunc { 13 | return func(w http.ResponseWriter, r *http.Request) { 14 | data, err := users.List() 15 | if err != nil { 16 | render.InternalServerError(w, err.Error()) 17 | return 18 | } 19 | render.JSON(w, http.StatusOK, data) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/api/user/profile.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/middlewares" 7 | "github.com/bleenco/abstruse/server/api/render" 8 | "github.com/bleenco/abstruse/server/core" 9 | ) 10 | 11 | // HandleProfile returns an http.HandlerFunc that writes JSON encoded 12 | // user data to the http response body. 13 | func HandleProfile(users core.UserStore) http.HandlerFunc { 14 | return func(w http.ResponseWriter, r *http.Request) { 15 | claims := middlewares.ClaimsFromCtx(r.Context()) 16 | 17 | user, err := users.Find(claims.ID) 18 | if err != nil { 19 | render.NotFoundError(w, err.Error()) 20 | return 21 | } 22 | 23 | render.JSON(w, http.StatusOK, user) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /server/api/worker/list.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/bleenco/abstruse/server/api/render" 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // HandleList returns an http.HandlerFunc that writes JSON encoded 11 | // list of workers in registry to http response body. 12 | func HandleList(workers core.WorkerRegistry) http.HandlerFunc { 13 | type resp struct { 14 | ID string `json:"id"` 15 | Addr string `json:"addr"` 16 | Host core.HostInfo `json:"host"` 17 | Usage []core.WorkerUsage `json:"usage"` 18 | } 19 | 20 | return func(w http.ResponseWriter, r *http.Request) { 21 | workers, err := workers.List() 22 | if err != nil { 23 | render.InternalServerError(w, err.Error()) 24 | return 25 | } 26 | 27 | var response []resp 28 | for _, worker := range workers { 29 | response = append(response, resp{worker.ID, worker.Addr, worker.Host, worker.Usage}) 30 | } 31 | 32 | render.JSON(w, http.StatusOK, response) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /server/api/worker/upload_cache.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/bleenco/abstruse/server/api/render" 10 | "github.com/bleenco/abstruse/server/config" 11 | ) 12 | 13 | // HandleUploadCache returns http.handlerFunc that writes JSON encoded 14 | // result about uploading cache to the http response body. 15 | func HandleUploadCache(config *config.Config) http.HandlerFunc { 16 | return func(w http.ResponseWriter, r *http.Request) { 17 | r.ParseMultipartForm(1000 << 20) 18 | 19 | src, handler, err := r.FormFile("file") 20 | if err != nil { 21 | render.InternalServerError(w, err.Error()) 22 | return 23 | } 24 | defer src.Close() 25 | 26 | filePath := filepath.Join(config.DataDir, "cache", handler.Filename) 27 | dst, err := os.Create(filePath) 28 | if err != nil { 29 | render.InternalServerError(w, err.Error()) 30 | return 31 | } 32 | defer dst.Close() 33 | 34 | if _, err := io.Copy(dst, src); err != nil { 35 | render.InternalServerError(w, err.Error()) 36 | return 37 | } 38 | 39 | render.JSON(w, http.StatusOK, render.BoolResponse{Status: true}) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/core/env.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ( 4 | // EnvVariable defines `env_variables` db table. 5 | EnvVariable struct { 6 | ID uint `gorm:"primary_key;auto_increment;not null" json:"id"` 7 | Key string `gorm:"not null" json:"key"` 8 | Value string `gorm:"not null" sql:"type:text" json:"value"` 9 | Secret bool `gorm:"not null,default:false" json:"secret"` 10 | RepositoryID uint `gorm:"not null" json:"repositoryID"` 11 | Repository Repository `json:"repository"` 12 | Timestamp 13 | } 14 | 15 | // EnvVariableStore defines operations on environment variables 16 | // in datastore. 17 | EnvVariableStore interface { 18 | // Find returns env variable from datastore. 19 | Find(uint) (*EnvVariable, error) 20 | 21 | // List returns list of environment variables from the datastore. 22 | List(uint) ([]*EnvVariable, error) 23 | 24 | // Create persists a new env variable to the datastore. 25 | Create(*EnvVariable) error 26 | 27 | // Update persists updated env variable to the datastore. 28 | Update(*EnvVariable) error 29 | 30 | // Delete deletes env variable from the datastore. 31 | Delete(*EnvVariable) error 32 | } 33 | ) 34 | -------------------------------------------------------------------------------- /server/core/mount.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ( 4 | // Mount defines `mounts` db table. 5 | Mount struct { 6 | ID uint `gorm:"primary_key;auto_increment;not null" json:"id"` 7 | Host string `gorm:"not null" json:"host"` 8 | Container string `gorm:"not null" json:"container"` 9 | RepositoryID uint `gorm:"not null" json:"repositoryID"` 10 | Repository Repository `json:"repository"` 11 | Timestamp 12 | } 13 | 14 | // MountsStore defines operations on mounts in datastore 15 | MountsStore interface { 16 | // Find returns mounts from datastore. 17 | Find(uint) (*Mount, error) 18 | 19 | // List returns list of mounts from the datastore. 20 | List(uint) ([]*Mount, error) 21 | 22 | // Create persists a new mount to the datastore. 23 | Create(*Mount) error 24 | 25 | // Update persists updated mounts to the datastore. 26 | Update(*Mount) error 27 | 28 | // Delete deletes mounts from the datastore. 29 | Delete(*Mount) error 30 | } 31 | ) 32 | -------------------------------------------------------------------------------- /server/core/registry.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ( 4 | // Registry represents worker nodes registry. 5 | Registry interface{} 6 | ) 7 | -------------------------------------------------------------------------------- /server/core/stats.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "time" 4 | 5 | // StatsHistoryCount history units 6 | const StatsHistoryCount = 120 7 | 8 | type ( 9 | // Usage defines server usage stats. 10 | Usage struct { 11 | CPU int32 `json:"cpu"` 12 | Mem int32 `json:"mem"` 13 | Timestamp time.Time `json:"timestamp"` 14 | } 15 | 16 | // StatsService defines operations on server statistics. 17 | StatsService interface { 18 | GetHistory() ([]Usage, []SchedulerStats) 19 | 20 | SchedulerStatus() bool 21 | } 22 | ) 23 | -------------------------------------------------------------------------------- /server/core/timestamp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "time" 4 | 5 | // Timestamp defines timestamp fields. 6 | type Timestamp struct { 7 | CreatedAt time.Time `json:"createdAt"` 8 | UpdatedAt time.Time `json:"updatedAt"` 9 | DeletedAt *time.Time `json:"deletedAt"` 10 | } 11 | -------------------------------------------------------------------------------- /server/parser/env.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/bleenco/abstruse/server/core" 8 | ) 9 | 10 | // GenerateGlobalEnv generates global env variables. 11 | func GenerateGlobalEnv(build *core.Build) []string { 12 | envs := make(map[string]string) 13 | 14 | envs["ABSTRUSE_REF"] = build.Ref 15 | envs["ABSTRUSE_BRANCH"] = build.Branch 16 | envs["ABSTRUSE_COMMIT"] = build.Commit 17 | 18 | if build.PR == 0 { 19 | envs["ABSTRUSE_PULL_REQUEST"] = "false" 20 | } else { 21 | envs["ABSTRUSE_PULL_REQUEST"] = fmt.Sprintf("%d", build.PR) 22 | } 23 | 24 | if strings.HasPrefix(build.Ref, "refs/tags/") { 25 | envs["ABSTRUSE_TAG"] = strings.TrimPrefix(build.Ref, "refs/tags/") 26 | } else { 27 | envs["ABSTRUSE_TAG"] = "false" 28 | } 29 | 30 | return toSlice(envs) 31 | } 32 | 33 | func toSlice(envs map[string]string) []string { 34 | var result []string 35 | for key, val := range envs { 36 | result = append(result, fmt.Sprintf("%s=%s", key, val)) 37 | } 38 | return result 39 | } 40 | -------------------------------------------------------------------------------- /server/store/envvariable/envvariable.go: -------------------------------------------------------------------------------- 1 | package envvariable 2 | 3 | import ( 4 | "github.com/bleenco/abstruse/server/core" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | // New returns a new EnvVariableStore. 9 | func New(db *gorm.DB) core.EnvVariableStore { 10 | return envVariableStore{db} 11 | } 12 | 13 | type envVariableStore struct { 14 | db *gorm.DB 15 | } 16 | 17 | func (s envVariableStore) Find(id uint) (*core.EnvVariable, error) { 18 | env := &core.EnvVariable{} 19 | err := s.db.Where("id = ?", id).First(&env).Error 20 | return env, err 21 | } 22 | 23 | func (s envVariableStore) List(id uint) ([]*core.EnvVariable, error) { 24 | var envs []*core.EnvVariable 25 | err := s.db.Where("repository_id = ?", id).Find(&envs).Error 26 | return envs, err 27 | } 28 | 29 | func (s envVariableStore) Create(env *core.EnvVariable) error { 30 | return s.db.Create(&env).Error 31 | } 32 | 33 | func (s envVariableStore) Update(env *core.EnvVariable) error { 34 | return s.db.Model(env).Updates(&env).Error 35 | } 36 | 37 | func (s envVariableStore) Delete(env *core.EnvVariable) error { 38 | return s.db.Delete(&env).Error 39 | } 40 | -------------------------------------------------------------------------------- /server/store/mounts/mounts.go: -------------------------------------------------------------------------------- 1 | package mount 2 | 3 | import ( 4 | "github.com/bleenco/abstruse/server/core" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | // New returns a new MountsStore. 9 | func New(db *gorm.DB) core.MountsStore { 10 | return mountsStore{db} 11 | } 12 | 13 | type mountsStore struct { 14 | db *gorm.DB 15 | } 16 | 17 | func (s mountsStore) Find(id uint) (*core.Mount, error) { 18 | mnt := &core.Mount{} 19 | err := s.db.Where("id = ?", id).First(&mnt).Error 20 | return mnt, err 21 | } 22 | 23 | func (s mountsStore) List(id uint) ([]*core.Mount, error) { 24 | var mnts []*core.Mount 25 | err := s.db.Where("repository_id = ?", id).Find(&mnts).Error 26 | return mnts, err 27 | } 28 | 29 | func (s mountsStore) Create(mnt *core.Mount) error { 30 | return s.db.Create(&mnt).Error 31 | } 32 | 33 | func (s mountsStore) Update(mnt *core.Mount) error { 34 | return s.db.Model(mnt).Updates(&mnt).Error 35 | } 36 | 37 | func (s mountsStore) Delete(mnt *core.Mount) error { 38 | return s.db.Delete(&mnt).Error 39 | } 40 | -------------------------------------------------------------------------------- /server/ws/proxy.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "net/http" 7 | ) 8 | 9 | // UpstreamHandler proxies HTTP requests to running 10 | // WebSocket server or application. 11 | func UpstreamHandler(addr string) http.HandlerFunc { 12 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 13 | peer, err := net.Dial("tcp", addr) 14 | if err != nil { 15 | w.WriteHeader(http.StatusBadGateway) 16 | return 17 | } 18 | if err := r.Write(peer); err != nil { 19 | w.WriteHeader(http.StatusBadGateway) 20 | return 21 | } 22 | hj, ok := w.(http.Hijacker) 23 | if !ok { 24 | w.WriteHeader(http.StatusInternalServerError) 25 | return 26 | } 27 | conn, _, err := hj.Hijack() 28 | if err != nil { 29 | w.WriteHeader(http.StatusInternalServerError) 30 | return 31 | } 32 | 33 | go pipe(peer, conn) 34 | go pipe(conn, peer) 35 | }) 36 | } 37 | 38 | func pipe(c1 net.Conn, c2 net.Conn) { 39 | defer c1.Close() 40 | defer c2.Close() 41 | io.Copy(c1, c2) 42 | } 43 | -------------------------------------------------------------------------------- /server/ws/types.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | // Object represents generic message parameters. 4 | type Object map[string]interface{} 5 | 6 | // Message represents websocket message. 7 | type Message struct { 8 | Type string `json:"type"` 9 | Data Object `json:"data"` 10 | } 11 | -------------------------------------------------------------------------------- /tests/e2e/tcp_wait.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | ) 8 | 9 | func waitTCP(duration time.Duration, port int) error { 10 | timeout := time.After(duration) 11 | tick := time.Tick(1 * time.Second) 12 | host := fmt.Sprintf("%s:%d", "localhost", port) 13 | for { 14 | select { 15 | case <-timeout: 16 | return fmt.Errorf("timed out") 17 | case <-tick: 18 | conn, err := net.DialTimeout("tcp", host, 500*time.Millisecond) 19 | if err == nil { 20 | conn.Close() 21 | return nil 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/webhooks/gitea/branch/headers.txt: -------------------------------------------------------------------------------- 1 | X-Github-Delivery 730e6b14-9fe5-47b6-a354-b96dd096e835 2 | X-Gogs-Delivery 730e6b14-9fe5-47b6-a354-b96dd096e835 3 | X-Gogs-Signature 3c8086439c3ccfcba3dc0d1c685a307aaf7bc91a5c5f2a70f5c18752f2e8e6c5 4 | Content-Length 2611 5 | X-Gitea-Signature 3c8086439c3ccfcba3dc0d1c685a307aaf7bc91a5c5f2a70f5c18752f2e8e6c5 6 | Content-Type application/json 7 | X-Gitea-Event push 8 | User-Agent Go-http-client/1.1 9 | X-Github-Event push 10 | X-Gitea-Delivery 730e6b14-9fe5-47b6-a354-b96dd096e835 11 | X-Gogs-Event push 12 | Accept-Encoding gzip 13 | -------------------------------------------------------------------------------- /tests/webhooks/gitea/pull_request/headers.txt: -------------------------------------------------------------------------------- 1 | User-Agent Go-http-client/1.1 2 | X-Gogs-Signature 094c646dde5b76ec96d5a4ae633c6159d40ff1b36043cc6c484a452d11840fe1 3 | X-Github-Event pull_request 4 | X-Gogs-Delivery 11484fa2-29f7-4a54-8b9c-d66559f7f402 5 | X-Gitea-Signature 094c646dde5b76ec96d5a4ae633c6159d40ff1b36043cc6c484a452d11840fe1 6 | X-Gogs-Event pull_request 7 | Content-Length 7499 8 | Content-Type application/json 9 | X-Github-Delivery 11484fa2-29f7-4a54-8b9c-d66559f7f402 10 | X-Gitea-Delivery 11484fa2-29f7-4a54-8b9c-d66559f7f402 11 | X-Gitea-Event pull_request 12 | Accept-Encoding gzip 13 | -------------------------------------------------------------------------------- /tests/webhooks/gitea/push/headers.txt: -------------------------------------------------------------------------------- 1 | X-Gogs-Signature 7fd629115274f61e2d5ee74dd6e3e73a93a9bc39451a9566436d0a541ab3cd07 2 | Accept-Encoding gzip 3 | Content-Length 3207 4 | X-Github-Event push 5 | X-Gitea-Delivery 2dbe459a-8a38-4c95-b8a9-6830dd2d24f4 6 | X-Gitea-Event push 7 | X-Gitea-Signature 7fd629115274f61e2d5ee74dd6e3e73a93a9bc39451a9566436d0a541ab3cd07 8 | X-Gogs-Delivery 2dbe459a-8a38-4c95-b8a9-6830dd2d24f4 9 | X-Github-Delivery 2dbe459a-8a38-4c95-b8a9-6830dd2d24f4 10 | X-Gogs-Event push 11 | User-Agent Go-http-client/1.1 12 | Content-Type application/json 13 | -------------------------------------------------------------------------------- /tests/webhooks/gitea/tag/headers.txt: -------------------------------------------------------------------------------- 1 | X-Gogs-Delivery 6e691c45-ffba-4893-a79f-dbd6957d4f4d 2 | Accept-Encoding gzip 3 | X-Gitea-Event create 4 | X-Github-Delivery 6e691c45-ffba-4893-a79f-dbd6957d4f4d 5 | X-Github-Event create 6 | X-Gitea-Delivery 6e691c45-ffba-4893-a79f-dbd6957d4f4d 7 | X-Gogs-Event create 8 | X-Gogs-Signature d9eacbfb9a3d90bf91cf643dfc0075cac83f22fa73d8b240440c5657ac068994 9 | Content-Length 2142 10 | Content-Type application/json 11 | X-Gitea-Signature d9eacbfb9a3d90bf91cf643dfc0075cac83f22fa73d8b240440c5657ac068994 12 | User-Agent Go-http-client/1.1 13 | -------------------------------------------------------------------------------- /tests/webhooks/github/branch/headers.txt: -------------------------------------------------------------------------------- 1 | User-Agent GitHub-Hookshot/bf33810 2 | Accept */* 3 | X-Github-Delivery 5caf9f78-d227-11ea-809c-e9a7311b8abc 4 | X-Github-Event push 5 | X-Hub-Signature sha1=1b4679ed18978d26b2262725e7bb6a352959f547 6 | X-Forwarded-For 140.82.115.146, 10.100.10.1 7 | Content-Length 7435 8 | X-Forwarded-Proto https 9 | Accept-Encoding gzip 10 | X-Real-Ip 140.82.115.146 11 | Content-Type application/json 12 | -------------------------------------------------------------------------------- /tests/webhooks/github/pull_request/headers.txt: -------------------------------------------------------------------------------- 1 | Accept */* 2 | Content-Type application/json 3 | X-Github-Delivery 18833c00-d228-11ea-9d45-18711679016d 4 | X-Github-Event pull_request 5 | X-Forwarded-For 140.82.115.248, 10.100.10.1 6 | X-Forwarded-Proto https 7 | X-Real-Ip 140.82.115.248 8 | Accept-Encoding gzip 9 | X-Hub-Signature sha1=e325b9168763ce61576f05f8fac01b977b92358b 10 | User-Agent GitHub-Hookshot/bf33810 11 | Content-Length 21578 12 | -------------------------------------------------------------------------------- /tests/webhooks/github/push/headers.txt: -------------------------------------------------------------------------------- 1 | X-Hub-Signature sha1=2fe41c5e4351d0622da9a09a1d37f49728d48664 2 | User-Agent GitHub-Hookshot/bf33810 3 | Content-Length 7444 4 | X-Real-Ip 140.82.115.244 5 | Accept-Encoding gzip 6 | X-Forwarded-For 140.82.115.244, 10.100.10.1 7 | Content-Type application/json 8 | X-Forwarded-Proto https 9 | X-Github-Delivery 68c158c8-d228-11ea-9b9f-827201ccb51d 10 | X-Github-Event push 11 | Accept */* 12 | -------------------------------------------------------------------------------- /tests/webhooks/github/push/sha.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | const payload = require("./webhook.json"); 3 | const secret = "73f5195de6"; 4 | 5 | const sig = crypto 6 | .createHmac("sha1", secret) 7 | .update(JSON.stringify(payload)) 8 | .digest("hex"); 9 | console.log(sig); 10 | -------------------------------------------------------------------------------- /tests/webhooks/github/tag/headers.txt: -------------------------------------------------------------------------------- 1 | X-Forwarded-For 140.82.115.248, 10.100.10.1 2 | X-Real-Ip 140.82.115.248 3 | User-Agent GitHub-Hookshot/bf33810 4 | Accept */* 5 | X-Forwarded-Proto https 6 | X-Github-Event push 7 | X-Hub-Signature sha1=07be3d99714674dbe09e00fe624e81a8904a90f4 8 | Content-Type application/json 9 | Content-Length 7164 10 | X-Github-Delivery 78024492-d227-11ea-8439-2a65180843e5 11 | Accept-Encoding gzip 12 | -------------------------------------------------------------------------------- /web/abstruse/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /web/abstruse/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.angular/cache 36 | /.sass-cache 37 | /connect.lock 38 | /coverage 39 | /libpeerconnection.log 40 | npm-debug.log 41 | yarn-error.log 42 | testem.log 43 | /typings 44 | 45 | # System Files 46 | .DS_Store 47 | Thumbs.db 48 | -------------------------------------------------------------------------------- /web/abstruse/README.md: -------------------------------------------------------------------------------- 1 | # Abstruse 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.0.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /web/abstruse/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | jasmineHtmlReporter: { 19 | suppressAll: true // removes the duplicated traces 20 | }, 21 | coverageReporter: { 22 | dir: require('path').join(__dirname, './coverage/abstruse'), 23 | subdir: '.', 24 | reporters: [{ type: 'html' }, { type: 'text-summary' }] 25 | }, 26 | reporters: ['progress', 'kjhtml'], 27 | port: 9876, 28 | colors: true, 29 | logLevel: config.LOG_INFO, 30 | autoWatch: true, 31 | browsers: ['Chrome'], 32 | singleRun: false, 33 | restartOnFileChange: true 34 | }); 35 | }; 36 | -------------------------------------------------------------------------------- /web/abstruse/ngsw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/service-worker/config/schema.json", 3 | "index": "/index.html", 4 | "dataGroups": [ 5 | { 6 | "name": "api", 7 | "urls": ["/api", "/badge", "/uploads"], 8 | "cacheConfig": { 9 | "maxSize": 0, 10 | "maxAge": "0u", 11 | "strategy": "freshness" 12 | } 13 | } 14 | ], 15 | "assetGroups": [ 16 | { 17 | "name": "app", 18 | "installMode": "prefetch", 19 | "resources": { 20 | "files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"] 21 | } 22 | }, 23 | { 24 | "name": "assets", 25 | "installMode": "lazy", 26 | "updateMode": "prefetch", 27 | "resources": { 28 | "files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"] 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /web/abstruse/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost", 4 | "secure": false 5 | }, 6 | "/ws": { 7 | "target": "ws://localhost", 8 | "secure": false, 9 | "ws": true 10 | }, 11 | "/badge": { 12 | "target": "http://localhost", 13 | "secure": false 14 | }, 15 | "/uploads": { 16 | "target": "http://localhost", 17 | "secure": false 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/abstruse/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
{{ error }}.
16 |