Compare commits
2 Commits
main
...
add-woodpe
Author | SHA1 | Date |
---|---|---|
|
7821618722 | 8 months ago |
|
ca59097b35 | 8 months ago |
@ -0,0 +1 @@
|
||||
use WOODPECKER_GITEA_CLIENT_FILE, WOODPECKER_GITEA_SECRET_FILE
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,45 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.my.services.woodpecker;
|
||||
hasRunner = (name: builtins.elem name cfg.runners);
|
||||
agentPkg = pkgs.ambroisie.woodpecker-agent;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (cfg.enable && hasRunner "docker") {
|
||||
systemd.services.woodpecker-agent-docker = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "docker.socket" ]; # Needs the socket to be available
|
||||
# might break deployment
|
||||
restartIfChanged = false;
|
||||
confinement.enable = true;
|
||||
serviceConfig = {
|
||||
Environment = [
|
||||
"WOODPECKER_SERVER=localhost:${toString cfg.grpcPort}"
|
||||
"WOODPECKER_GRPC_SECURE=true"
|
||||
"WOODPECKER_MAX_PROCS=10"
|
||||
"WOODPECKER_BACKEND=docker"
|
||||
# FIXME: docker settings
|
||||
];
|
||||
BindPaths = [
|
||||
"/var/run/docker.sock"
|
||||
];
|
||||
EnvironmentFile = [
|
||||
cfg.sharedSecretFile
|
||||
];
|
||||
ExecStart = "${agentPkg}/bin/woodpecker-agent";
|
||||
User = "woodpecker-agent-docker";
|
||||
Group = "woodpecker-agent-docker";
|
||||
};
|
||||
};
|
||||
|
||||
# Make sure it is activated in that case
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
users.users.woodpecker-agent-docker = {
|
||||
isSystemUser = true;
|
||||
group = "woodpecker-agent-docker";
|
||||
extraGroups = [ "docker" ]; # Give access to the daemon
|
||||
};
|
||||
users.groups.woodpecker-agent-docker = { };
|
||||
};
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.my.services.woodpecker;
|
||||
hasRunner = (name: builtins.elem name cfg.runners);
|
||||
agentPkg = pkgs.ambroisie.woodpecker-agent;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (cfg.enable && hasRunner "local") {
|
||||
systemd.services.woodpecker-agent-local = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# might break deployment
|
||||
restartIfChanged = false;
|
||||
confinement.enable = true;
|
||||
confinement.packages = with pkgs; [
|
||||
git
|
||||
gnutar
|
||||
bash
|
||||
nixUnstable
|
||||
gzip
|
||||
];
|
||||
path = with pkgs; [
|
||||
git
|
||||
gnutar
|
||||
bash
|
||||
nixUnstable
|
||||
gzip
|
||||
];
|
||||
serviceConfig = {
|
||||
Environment = [
|
||||
"WOODPECKER_SERVER=localhost:${toString cfg.grpcPort}"
|
||||
"WOODPECKER_GRPC_SECURE=true"
|
||||
"WOODPECKER_MAX_PROCS=10"
|
||||
"WOODPECKER_BACKEND=local"
|
||||
"NIX_REMOTE=daemon"
|
||||
"PAGER=cat"
|
||||
];
|
||||
BindPaths = [
|
||||
"/nix/var/nix/daemon-socket/socket"
|
||||
"/run/nscd/socket"
|
||||
];
|
||||
BindReadOnlyPaths = [
|
||||
"/etc/resolv.conf:/etc/resolv.conf"
|
||||
"/etc/resolvconf.conf:/etc/resolvconf.conf"
|
||||
"/etc/passwd:/etc/passwd"
|
||||
"/etc/group:/etc/group"
|
||||
"/nix/var/nix/profiles/system/etc/nix:/etc/nix"
|
||||
"${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
|
||||
"${config.environment.etc."ssh/ssh_known_hosts".source}:/etc/ssh/ssh_known_hosts"
|
||||
"/etc/machine-id"
|
||||
# channels are dynamic paths in the nix store, therefore we need to bind mount the whole thing
|
||||
"/nix/"
|
||||
];
|
||||
EnvironmentFile = [
|
||||
cfg.sharedSecretFile
|
||||
];
|
||||
ExecStart = "${agentPkg}/bin/woodpecker-agent";
|
||||
User = "woodpecker-agent-local";
|
||||
Group = "woodpecker-agent-local";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.woodpecker-agent-local = {
|
||||
isSystemUser = true;
|
||||
group = "woodpecker-agent-local";
|
||||
};
|
||||
users.groups.woodpecker-agent-local = { };
|
||||
};
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
# A docker-based CI/CD system
|
||||
#
|
||||
# Inspired by [1]
|
||||
# [1]: https://github.com/Mic92/dotfiles/blob/master/nixos/eve/modules/drone.nix
|
||||
{ lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./agent-docker
|
||||
./agent-local
|
||||
./server
|
||||
];
|
||||
|
||||
options.my.services.woodpecker = with lib; {
|
||||
enable = mkEnableOption "Woodpecker CI";
|
||||
runners = mkOption {
|
||||
type = with types; listOf (enum [ "local" "docker" ]);
|
||||
default = [ ];
|
||||
example = [ "local" "docker" ];
|
||||
description = "Types of runners to enable";
|
||||
};
|
||||
admin = mkOption {
|
||||
type = types.str;
|
||||
default = "ambroisie";
|
||||
example = "admin";
|
||||
description = "Name of the admin user";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3031;
|
||||
example = 8080;
|
||||
description = "Internal port of the Woodpecker UI";
|
||||
};
|
||||
grpcPort = mkOption {
|
||||
type = types.port;
|
||||
default = 9001;
|
||||
example = 8080;
|
||||
description = "Internal port of the Woodpecker gRPC";
|
||||
};
|
||||
secretFile = mkOption {
|
||||
type = types.str;
|
||||
example = "/run/secrets/woodpecker-gitea.env";
|
||||
description = "Secrets to inject into Woodpecker server";
|
||||
};
|
||||
sharedSecretFile = mkOption {
|
||||
type = types.str;
|
||||
example = "/run/secrets/woodpecker-rpc.env";
|
||||
description = "Shared RPC secret to inject into server and runners";
|
||||
};
|
||||
};
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.my.services.woodpecker;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.woodpecker-server = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "postgresql.service" ];
|
||||
serviceConfig = {
|
||||
EnvironmentFile = [
|
||||
cfg.secretFile
|
||||
cfg.sharedSecretFile
|
||||
];
|
||||
Environment = [
|
||||
"WOODPECKER_SERVER_ADDR=:${toString cfg.port}"
|
||||
"WOODPECKER_GRPC_ADDR=:${toString cfg.grpcPort}"
|
||||
"WOODPECKER_HOST=https://woodpecker.${config.networking.domain}"
|
||||
"WOODPECKER_DATABASE_DRIVER=postgres"
|
||||
"WOODPECKER_DATABASE_DATASOURCE=postgres:///woodpecker?host=/run/postgresql"
|
||||
"WOODPECKER_ADMIN=${cfg.admin}"
|
||||
# FIXME: not supported?
|
||||
"WOODPECKER_JSONNET_ENABLED=true"
|
||||
"WOODPECKER_STARLARK_ENABLED=true"
|
||||
];
|
||||
ExecStart = "${pkgs.ambroisie.woodpecker-server}/bin/woodpecker-server";
|
||||
User = "woodpecker";
|
||||
Group = "woodpecker";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.woodpecker = {
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
group = "woodpecker";
|
||||
};
|
||||
users.groups.woodpecker = { };
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "woodpecker" ];
|
||||
ensureUsers = [{
|
||||
name = "woodpecker";
|
||||
ensurePermissions = {
|
||||
"DATABASE woodpecker" = "ALL PRIVILEGES";
|
||||
};
|
||||
}];
|
||||
};
|
||||
|
||||
my.services.nginx.virtualHosts = [
|
||||
{
|
||||
subdomain = "woodpecker";
|
||||
inherit (cfg) port;
|
||||
}
|
||||
{
|
||||
subdomain = "woodpecker-grpc";
|
||||
port = cfg.grpcPort;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
{ lib, buildGoModule, fetchFromGitHub }:
|
||||
let
|
||||
inherit (import ./common.nix { inherit lib fetchFromGitHub; })
|
||||
meta
|
||||
version
|
||||
src
|
||||
ldflags
|
||||
postBuild
|
||||
;
|
||||
in
|
||||
buildGoModule {
|
||||
pname = "woodpecker-agent";
|
||||
inherit version src ldflags postBuild;
|
||||
vendorSha256 = null;
|
||||
|
||||
subPackages = "cmd/agent";
|
||||
|
||||
CGO_ENABLED = 0;
|
||||
|
||||
meta = meta // {
|
||||
description = "Woodpecker Continuous Integration agent";
|
||||
};
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
{ lib, buildGoModule, fetchFromGitHub }:
|
||||
let
|
||||
inherit (import ./common.nix { inherit lib fetchFromGitHub; })
|
||||
meta
|
||||
version
|
||||
src
|
||||
ldflags
|
||||
postBuild
|
||||
;
|
||||
in
|
||||
buildGoModule {
|
||||
pname = "woodpecker-cli";
|
||||
inherit version src ldflags postBuild;
|
||||
vendorSha256 = null;
|
||||
|
||||
subPackages = "cmd/cli";
|
||||
|
||||
CGO_ENABLED = 0;
|
||||
|
||||
meta = meta // {
|
||||
description = "Command line client for the Woodpecker Continuous Integration server";
|
||||
};
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{ lib, fetchFromGitHub }:
|
||||
let
|
||||
version = "0.15.3";
|
||||
srcSha256 = "sha256-HOOH3H2SXLcT2oW/xL80TO+ZSI+Haulnznpb4hlCQow=";
|
||||
yarnSha256 = "sha256-x9g0vSoexfknqLejgcNIigmkFnqYsmhcQNTOStcj68o=";
|
||||
in
|
||||
{
|
||||
inherit version yarnSha256;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "woodpecker-ci";
|
||||
repo = "woodpecker";
|
||||
rev = "v${version}";
|
||||
sha256 = srcSha256;
|
||||
};
|
||||
|
||||
postBuild = ''
|
||||
cd $GOPATH/bin
|
||||
for f in *; do
|
||||
mv -- "$f" "woodpecker-$f"
|
||||
done
|
||||
cd -
|
||||
'';
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
"-X github.com/woodpecker-ci/woodpecker/version.Version=${version}"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://woodpecker-ci.org/";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ ambroisie ];
|
||||
};
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
{ lib, fetchFromGitHub, fetchYarnDeps, mkYarnPackage }:
|
||||
let
|
||||
inherit (import ./common.nix { inherit lib fetchFromGitHub; })
|
||||
meta
|
||||
version
|
||||
src
|
||||
yarnSha256
|
||||
;
|
||||
in
|
||||
mkYarnPackage {
|
||||
pname = "woodpecker-frontend";
|
||||
inherit version;
|
||||
|
||||
src = "${src}/web";
|
||||
|
||||
packageJSON = ./woodpecker-package.json;
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${src}/web/yarn.lock";
|
||||
sha256 = yarnSha256;
|
||||
};
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
yarn build
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
cp -R deps/woodpecker-ci/dist $out
|
||||
echo "${version}" > "$out/version"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
# Do not attempt generating a tarball for woodpecker-frontend again.
|
||||
doDist = false;
|
||||
|
||||
meta = meta // {
|
||||
description = "Woodpecker Continuous Integration server frontend";
|
||||
};
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
{ lib, buildGoModule, fetchFromGitHub, woodpecker-frontend }:
|
||||
let
|
||||
inherit (import ./common.nix { inherit lib fetchFromGitHub; })
|
||||
meta
|
||||
version
|
||||
src
|
||||
ldflags
|
||||
postBuild
|
||||
;
|
||||
in
|
||||
buildGoModule {
|
||||
pname = "woodpecker-server";
|
||||
inherit version src ldflags postBuild;
|
||||
vendorSha256 = null;
|
||||
|
||||
postPatch = ''
|
||||
cp -r ${woodpecker-frontend} web/dist
|
||||
'';
|
||||
|
||||
subPackages = "cmd/server";
|
||||
|
||||
CGO_ENABLED = 1;
|
||||
|
||||
passthru = {
|
||||
inherit woodpecker-frontend;
|
||||
|
||||
updateScript = ./update.sh;
|
||||
};
|
||||
|
||||
meta = meta // {
|
||||
description = "Woodpecker Continuous Integration server";
|
||||
};
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p nix wget prefetch-yarn-deps nix-prefetch-github jq
|
||||
|
||||
if [ "$#" -gt 1 ] || [[ "$1" == -* ]]; then
|
||||
echo "Regenerates packaging data for the woodpecker packages."
|
||||
echo "Usage: $0 [git release tag]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
version="$1"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
version="$(wget -O- "https://api.github.com/repos/woodpecker-ci/woodpecker/releases?per_page=1" | jq -r '.[0].tag_name')"
|
||||
fi
|
||||
|
||||
# strip leading "v"
|
||||
version="${version#v}"
|
||||
|
||||
# Woodpecker repository
|
||||
src_hash=$(nix-prefetch-github woodpecker-ci woodpecker --rev "v${version}" | jq -r .sha256)
|
||||
|
||||
# Front-end dependencies
|
||||
woodpecker_src="https://raw.githubusercontent.com/woodpecker-ci/woodpecker/v$version"
|
||||
wget "$woodpecker_src/web/package.json" -O woodpecker-package.json
|
||||
|
||||
web_tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$web_tmpdir"' EXIT
|
||||
pushd "$web_tmpdir"
|
||||
wget "$woodpecker_src/web/yarn.lock"
|
||||
yarn_hash=$(prefetch-yarn-deps yarn.lock)
|
||||
popd
|
||||
|
||||
# Use friendlier hashes
|
||||
src_hash=$(nix hash to-sri --type sha256 "$src_hash")
|
||||
yarn_hash=$(nix hash to-sri --type sha256 "$yarn_hash")
|
||||
|
||||
sed -i -E -e "s#version = \".*\"#version = \"$version\"#" common.nix
|
||||
sed -i -E -e "s#srcSha256 = \".*\"#srcSha256 = \"$src_hash\"#" common.nix
|
||||
sed -i -E -e "s#yarnSha256 = \".*\"#yarnSha256 = \"$yarn_hash\"#" common.nix
|
@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "woodpecker-ci",
|
||||
"author": "Woodpecker CI",
|
||||
"version": "0.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --max-warnings 0 --ext .js,.ts,.vue,.json .",
|
||||
"formatcheck": "prettier -c .",
|
||||
"format:fix": "prettier --write .",
|
||||
"typecheck": "vue-tsc --noEmit",
|
||||
"test": "echo 'No tests configured' && exit 0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kyvg/vue3-notification": "2.3.4",
|
||||
"@meforma/vue-toaster": "1.2.2",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"dayjs": "1.10.7",
|
||||
"floating-vue": "2.0.0-beta.5",
|
||||
"fuse.js": "6.4.6",
|
||||
"humanize-duration": "3.27.0",
|
||||
"javascript-time-ago": "2.3.10",
|
||||
"node-emoji": "1.11.0",
|
||||
"pinia": "2.0.0",
|
||||
"vue": "v3.2.20",
|
||||
"vue-router": "4.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "1.1.421",
|
||||
"@types/humanize-duration": "3.27.0",
|
||||
"@types/javascript-time-ago": "2.0.3",
|
||||
"@types/node": "16.11.6",
|
||||
"@types/node-emoji": "1.8.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.6.0",
|
||||
"@typescript-eslint/parser": "5.6.0",
|
||||
"@vitejs/plugin-vue": "1.9.4",
|
||||
"@vue/compiler-sfc": "3.2.20",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-airbnb-typescript": "16.1.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-plugin-import": "2.25.3",
|
||||
"eslint-plugin-prettier": "4.0.0",
|
||||
"eslint-plugin-promise": "5.1.1",
|
||||
"eslint-plugin-simple-import-sort": "7.0.0",
|
||||
"eslint-plugin-vue": "7.18.0",
|
||||
"eslint-plugin-vue-scoped-css": "1.3.0",
|
||||
"prettier": "2.4.1",
|
||||
"typescript": "4.4.4",
|
||||
"unplugin-icons": "0.12.17",
|
||||
"unplugin-vue-components": "0.17.0",
|
||||
"vite": "2.6.13",
|
||||
"vite-plugin-windicss": "1.4.12",
|
||||
"vite-svg-loader": "3.0.0",
|
||||
"vue-tsc": "0.28.10",
|
||||
"windicss": "3.2.0"
|
||||
}
|
||||
}
|
Loading…
Reference in new issue