2023-10-09 19:29:22 +00:00
{ system ? builtins . currentSystem
, config ? { }
, pkgs ? import ../.. { inherit system config ; }
2024-09-19 14:19:46 +00:00
, forgejoPackage ? pkgs . forgejo
2023-10-09 19:29:22 +00:00
} :
with import ../lib/testing-python.nix { inherit system pkgs ; } ;
with pkgs . lib ;
let
## gpg --faked-system-time='20230301T010000!' --quick-generate-key snakeoil ed25519 sign
signingPrivateKey = ''
- - - - - BEGIN PGP PRIVATE KEY BLOCK-----
lFgEY/6jkBYJKwYBBAHaRw8BAQdADXiZRV8RJUyC9g0LH04wLMaJL9WTc+szbMi7
5fw4yP8AAQCl8EwGfzSLm/P6fCBfA3I9znFb3MEHGCCJhJ6VtKYyRw7ktAhzbmFr
ZW9pbIiUBBMWCgA8FiEE+wUM6VW/NLtAdSixTWQt6LZ4x50FAmP+o5ACGwMFCQPC
ZwAECwkIBwQVCgkIBRYCAwEAAh4FAheAAAoJEE1kLei2eMedFTgBAKQs1oGFZrCI
TZP42hmBTKxGAI1wg7VSdDEWTZxut/2JAQDGgo2sa4VHMfj0aqYGxrIwfP2B7JHO
GCqGCRf9O/hzBA ==
= 9 Uy3
- - - - - END PGP PRIVATE KEY BLOCK-----
'' ;
signingPrivateKeyId = " 4 D 6 4 2 D E 8 B 6 7 8 C 7 9 D " ;
2024-04-21 15:54:59 +00:00
actionsWorkflowYaml = ''
run-name : dummy workflow
on :
push :
jobs :
cat :
runs-on : native
steps :
- uses : http://localhost:3000/test/checkout@main
- run : cat testfile
'' ;
# https://github.com/actions/checkout/releases
checkoutActionSource = pkgs . fetchFromGitHub {
owner = " a c t i o n s " ;
repo = " c h e c k o u t " ;
rev = " v 4 . 1 . 1 " ;
hash = " s h a 2 5 6 - h 2 / U I p 8 I j P o 3 e E 4 G z x 5 2 F b 7 p c g G / W w 7 u 3 1 w 5 f d K V M o s = " ;
} ;
2024-06-05 15:53:02 +00:00
metricSecret = " f a k e s e c r e t " ;
2023-10-09 19:29:22 +00:00
supportedDbTypes = [ " m y s q l " " p o s t g r e s " " s q l i t e 3 " ] ;
2024-04-21 15:54:59 +00:00
makeForgejoTest = type : nameValuePair type ( makeTest {
2023-10-09 19:29:22 +00:00
name = " f o r g e j o - ${ type } " ;
meta . maintainers = with maintainers ; [ bendlas emilylange ] ;
nodes = {
server = { config , pkgs , . . . }: {
virtualisation . memorySize = 2047 ;
services . forgejo = {
enable = true ;
2024-09-19 14:19:46 +00:00
package = forgejoPackage ;
2023-10-09 19:29:22 +00:00
database = { inherit type ; } ;
settings . service . DISABLE_REGISTRATION = true ;
settings . " r e p o s i t o r y . s i g n i n g " . SIGNING_KEY = signingPrivateKeyId ;
settings . actions . ENABLED = true ;
2024-04-21 15:54:59 +00:00
settings . repository = {
ENABLE_PUSH_CREATE_USER = true ;
DEFAULT_PUSH_CREATE_PRIVATE = false ;
} ;
2024-06-05 15:53:02 +00:00
settings . metrics . ENABLED = true ;
secrets . metrics . TOKEN = pkgs . writeText " m e t r i c s _ s e c r e t " metricSecret ;
2023-10-09 19:29:22 +00:00
} ;
2024-04-21 15:54:59 +00:00
environment . systemPackages = [ config . services . forgejo . package pkgs . gnupg pkgs . jq pkgs . file pkgs . htmlq ] ;
2023-10-09 19:29:22 +00:00
services . openssh . enable = true ;
specialisation . runner = {
inheritParentConfig = true ;
2024-04-21 15:54:59 +00:00
configuration . services . gitea-actions-runner = {
package = pkgs . forgejo-runner ;
instances . " t e s t " = {
enable = true ;
name = " c i " ;
url = " h t t p : / / l o c a l h o s t : 3 0 0 0 " ;
labels = [
# type ":host" does not depend on docker/podman/lxc
" n a t i v e : h o s t "
] ;
tokenFile = " / v a r / l i b / f o r g e j o / r u n n e r _ t o k e n " ;
} ;
2023-10-09 19:29:22 +00:00
} ;
} ;
2023-11-16 04:20:00 +00:00
specialisation . dump = {
inheritParentConfig = true ;
configuration . services . forgejo . dump = {
enable = true ;
type = " t a r . z s t " ;
file = " d u m p . t a r . z s t " ;
} ;
} ;
2023-10-09 19:29:22 +00:00
} ;
2024-04-21 15:54:59 +00:00
client = { . . . }: {
programs . git = {
enable = true ;
config = {
user . email = " t e s t @ l o c a l h o s t " ;
user . name = " t e s t " ;
init . defaultBranch = " m a i n " ;
} ;
} ;
programs . ssh . extraConfig = ''
Host *
StrictHostKeyChecking no
IdentityFile ~/.ssh/privk
'' ;
2023-10-09 19:29:22 +00:00
} ;
} ;
testScript = { nodes , . . . }:
let
inherit ( import ./ssh-keys.nix pkgs ) snakeOilPrivateKey snakeOilPublicKey ;
serverSystem = nodes . server . system . build . toplevel ;
2023-11-16 04:20:00 +00:00
dumpFile = with nodes . server . specialisation . dump . configuration . services . forgejo . dump ; " ${ backupDir } / ${ file } " ;
2024-04-21 15:54:59 +00:00
remoteUri = " f o r g e j o @ s e r v e r : t e s t / r e p o " ;
remoteUriCheckoutAction = " f o r g e j o @ s e r v e r : t e s t / c h e c k o u t " ;
2023-10-09 19:29:22 +00:00
in
''
2023-11-16 04:20:00 +00:00
import json
2023-10-09 19:29:22 +00:00
start_all ( )
2024-04-21 15:54:59 +00:00
client . succeed ( " m k d i r - p ~ / . s s h " )
client . succeed ( " ( u m a s k 0 0 7 7 ; c a t ${ snakeOilPrivateKey } > ~ / . s s h / p r i v k ) " )
client . succeed ( " m k d i r / t m p / r e p o " )
client . succeed ( " g i t - C / t m p / r e p o i n i t " )
client . succeed ( " e c h o ' h e l l o w o r l d ' > / t m p / r e p o / t e s t f i l e " )
client . succeed ( " g i t - C / t m p / r e p o a d d . " )
client . succeed ( " g i t - C / t m p / r e p o c o m m i t - m ' I n i t i a l i m p o r t ' " )
client . succeed ( " g i t - C / t m p / r e p o r e m o t e a d d o r i g i n ${ remoteUri } " )
2023-10-09 19:29:22 +00:00
server . wait_for_unit ( " f o r g e j o . s e r v i c e " )
server . wait_for_open_port ( 3000 )
server . wait_for_open_port ( 22 )
server . succeed ( " c u r l - - f a i l h t t p : / / l o c a l h o s t : 3 0 0 0 / " )
server . succeed (
" s u - l f o r g e j o - c ' g p g - - h o m e d i r / v a r / l i b / f o r g e j o / d a t a / h o m e / . g n u p g "
+ " - - i m p o r t ${ toString ( pkgs . writeText " f o r g e j o . k e y " signingPrivateKey ) } ' "
)
assert " B E G I N P G P P U B L I C K E Y B L O C K " in server . succeed ( " c u r l h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / v 1 / s i g n i n g - k e y . g p g " )
2024-04-21 15:54:59 +00:00
api_version = json . loads ( server . succeed ( " c u r l h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / f o r g e j o / v 1 / v e r s i o n " ) ) . get ( " v e r s i o n " )
2024-09-19 14:19:46 +00:00
assert " d e v e l o p m e n t " != api_version and " ${ forgejoPackage . version } + g i t e a - " in api_version , (
2024-04-21 15:54:59 +00:00
" / a p i / f o r g e j o / v 1 / v e r s i o n s h o u l d n o t r e t u r n ' d e v e l o p m e n t ' "
2024-05-15 15:35:15 +00:00
+ f " b u t s h o u l d c o n t a i n a f o r g e j o + g i t e a c o m p a t i b i l i t y v e r s i o n s t r i n g . G o t ' { a p i _ v e r s i o n } ' i n s t e a d . "
2024-04-21 15:54:59 +00:00
)
2023-10-09 19:29:22 +00:00
server . succeed (
" c u r l - - f a i l h t t p : / / l o c a l h o s t : 3 0 0 0 / u s e r / s i g n _ u p | g r e p ' R e g i s t r a t i o n i s d i s a b l e d . "
+ " P l e a s e c o n t a c t y o u r s i t e a d m i n i s t r a t o r . ' "
)
server . succeed (
" s u - l f o r g e j o - c ' G I T E A _ W O R K _ D I R = / v a r / l i b / f o r g e j o g i t e a a d m i n u s e r c r e a t e "
2024-05-15 15:35:15 +00:00
+ " - - u s e r n a m e t e s t - - p a s s w o r d t o t a l l y s a f e - - e m a i l t e s t @ l o c a l h o s t - - m u s t - c h a n g e - p a s s w o r d = f a l s e ' "
2023-10-09 19:29:22 +00:00
)
api_token = server . succeed (
" c u r l - - f a i l - X P O S T h t t p : / / t e s t : t o t a l l y s a f e @ l o c a l h o s t : 3 0 0 0 / a p i / v 1 / u s e r s / t e s t / t o k e n s "
+ " - H ' A c c e p t : a p p l i c a t i o n / j s o n ' - H ' C o n t e n t - T y p e : a p p l i c a t i o n / j s o n ' - d "
+ " ' { \" n a m e \" : \" t o k e n \" , \" s c o p e s \" : [ \" a l l \" ] } ' | j q ' . s h a 1 ' | x a r g s e c h o - n "
)
server . succeed (
" c u r l - - f a i l - X P O S T h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / v 1 / u s e r / r e p o s "
+ " - H ' A c c e p t : a p p l i c a t i o n / j s o n ' - H ' C o n t e n t - T y p e : a p p l i c a t i o n / j s o n ' "
+ f " - H ' A u t h o r i z a t i o n : t o k e n { a p i _ t o k e n } ' "
+ ' - d \ ' { " a u t o _ i n i t " : false , " d e s c r i p t i o n " : " s t r i n g " , " l i c e n s e " : " m i t " , " n a m e " : " r e p o " , " p r i v a t e " : false } \ '' '
)
server . succeed (
" c u r l - - f a i l - X P O S T h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / v 1 / u s e r / k e y s "
+ " - H ' A c c e p t : a p p l i c a t i o n / j s o n ' - H ' C o n t e n t - T y p e : a p p l i c a t i o n / j s o n ' "
+ f " - H ' A u t h o r i z a t i o n : t o k e n { a p i _ t o k e n } ' "
+ ' - d \ ' { " k e y " : " ${ snakeOilPublicKey } " , " r e a d _ o n l y " : true , " t i t l e " : " S S H " } \ '' '
)
2024-04-21 15:54:59 +00:00
client . succeed ( " g i t - C / t m p / r e p o p u s h o r i g i n m a i n " )
2023-10-09 19:29:22 +00:00
2024-04-21 15:54:59 +00:00
client . succeed ( " g i t c l o n e ${ remoteUri } / t m p / r e p o - c l o n e " )
print ( client . succeed ( " l s - l a s h / t m p / r e p o - c l o n e " ) )
assert " h e l l o w o r l d " == client . succeed ( " c a t / t m p / r e p o - c l o n e / t e s t f i l e " ) . strip ( )
2023-10-09 19:29:22 +00:00
2023-11-16 04:20:00 +00:00
with subtest ( " T e s t i n g g i t p r o t o c o l v e r s i o n = 2 o v e r s s h " ) :
2024-04-21 15:54:59 +00:00
git_protocol = client . succeed ( " G I T _ T R A C E 2 _ E V E N T = t r u e g i t - C / t m p / r e p o - c l o n e f e t c h | & g r e p n e g o t i a t e d - v e r s i o n " )
2023-11-16 04:20:00 +00:00
version = json . loads ( git_protocol ) . get ( " v a l u e " )
assert version == " 2 " , f " g i t d i d n o t n e g o t i a t e p r o t o c o l v e r s i o n 2 , b u t v e r s i o n { v e r s i o n } i n s t e a d . "
2023-10-09 19:29:22 +00:00
server . wait_until_succeeds (
' test " $ ( c u r l h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / v 1 / r e p o s / t e s t / r e p o / c o m m i t s '
+ ' - H " A c c e p t : a p p l i c a t i o n / j s o n " | jq length ) " = " 1 " ' ,
timeout = 10
)
2024-06-05 15:53:02 +00:00
with subtest ( " T e s t i n g / m e t r i c s e n d p o i n t w i t h t o k e n f r o m c f g . s e c r e t s " ) :
server . fail ( " c u r l - - f a i l h t t p : / / l o c a l h o s t : 3 0 0 0 / m e t r i c s " )
server . succeed ( ' curl - - fail http://localhost:3000/metrics - H " A u t h o r i z a t i o n : B e a r e r ${ metricSecret } " ' )
2024-04-21 15:54:59 +00:00
with subtest ( " T e s t i n g r u n n e r r e g i s t r a t i o n a n d a c t i o n w o r k f l o w " ) :
2023-10-09 19:29:22 +00:00
server . succeed (
" s u - l f o r g e j o - c ' G I T E A _ W O R K _ D I R = / v a r / l i b / f o r g e j o g i t e a a c t i o n s g e n e r a t e - r u n n e r - t o k e n ' | s e d ' s / ^ / T O K E N = / ' | t e e / v a r / l i b / f o r g e j o / r u n n e r _ t o k e n "
)
server . succeed ( " ${ serverSystem } / s p e c i a l i s a t i o n / r u n n e r / b i n / s w i t c h - t o - c o n f i g u r a t i o n t e s t " )
server . wait_for_unit ( " g i t e a - r u n n e r - t e s t . s e r v i c e " )
server . succeed ( " j o u r n a l c t l - o c a t - u g i t e a - r u n n e r - t e s t . s e r v i c e | g r e p - q ' R u n n e r r e g i s t e r e d s u c c e s s f u l l y ' " )
2023-11-16 04:20:00 +00:00
2024-04-21 15:54:59 +00:00
# enable actions feature for this repository, defaults to disabled
server . succeed (
" c u r l - - f a i l - X P A T C H h t t p : / / l o c a l h o s t : 3 0 0 0 / a p i / v 1 / r e p o s / t e s t / r e p o "
+ " - H ' A c c e p t : a p p l i c a t i o n / j s o n ' - H ' C o n t e n t - T y p e : a p p l i c a t i o n / j s o n ' "
+ f " - H ' A u t h o r i z a t i o n : t o k e n { a p i _ t o k e n } ' "
+ ' - d \ ' { " h a s _ a c t i o n s " : true } \ '' '
)
# mirror "actions/checkout" action
client . succeed ( " c p - R ${ checkoutActionSource } / / t m p / c h e c k o u t " )
client . succeed ( " g i t - C / t m p / c h e c k o u t i n i t " )
client . succeed ( " g i t - C / t m p / c h e c k o u t a d d . " )
client . succeed ( " g i t - C / t m p / c h e c k o u t c o m m i t - m ' I n i t i a l i m p o r t ' " )
client . succeed ( " g i t - C / t m p / c h e c k o u t r e m o t e a d d o r i g i n ${ remoteUriCheckoutAction } " )
client . succeed ( " g i t - C / t m p / c h e c k o u t p u s h o r i g i n m a i n " )
# push workflow to initial repo
client . succeed ( " m k d i r - p / t m p / r e p o / . f o r g e j o / w o r k f l o w s " )
client . succeed ( " c p ${ pkgs . writeText " d u m m y - w o r k f l o w . y m l " actionsWorkflowYaml } / t m p / r e p o / . f o r g e j o / w o r k f l o w s / " )
client . succeed ( " g i t - C / t m p / r e p o a d d . " )
client . succeed ( " g i t - C / t m p / r e p o c o m m i t - m ' A d d d u m m y w o r k f l o w ' " )
client . succeed ( " g i t - C / t m p / r e p o p u s h o r i g i n m a i n " )
def poll_workflow_action_status ( _ ) -> bool :
output = server . succeed (
" c u r l - - f a i l h t t p : / / l o c a l h o s t : 3 0 0 0 / t e s t / r e p o / a c t i o n s | "
+ ' htmlq " . f l e x - i t e m - l e a d i n g s p a n " - - attribute " d a t a - t o o l t i p - c o n t e n t " '
) . strip ( )
# values taken from https://codeberg.org/forgejo/forgejo/src/commit/af47c583b4fb3190fa4c4c414500f9941cc02389/options/locale/locale_en-US.ini#L3649-L3661
if output in [ " F a i l u r e " , " C a n c e l e d " , " S k i p p e d " , " B l o c k e d " ] :
raise Exception ( f " W o r k f l o w s t a t u s i s ' { o u t p u t } ' , w h i c h w e c o n s i d e r f a i l e d . " )
server . log ( f " C o m m a n d r e t u r n e d ' { o u t p u t } ' , w h i c h w e c o n s i d e r f a i l e d . " )
elif output in [ " U n k n o w n " , " W a i t i n g " , " R u n n i n g " , " " ] :
server . log ( f " W o r k f l o w s t a t u s i s ' { o u t p u t } ' . W a i t i n g s o m e m o r e . . . " )
return False
elif output in [ " S u c c e s s " ] :
return True
raise Exception ( f " W o r k f l o w s t a t u s i s ' { o u t p u t } ' , w h i c h w e d o n ' t k n o w . V a l u e m a p p i n g s l i k e l y n e e d u p d a t i n g . " )
with server . nested ( " W a i t i n g f o r t h e w o r k f l o w r u n t o b e s u c c e s s f u l " ) :
retry ( poll_workflow_action_status )
2023-11-16 04:20:00 +00:00
with subtest ( " T e s t i n g b a c k u p s e r v i c e " ) :
server . succeed ( " ${ serverSystem } / s p e c i a l i s a t i o n / d u m p / b i n / s w i t c h - t o - c o n f i g u r a t i o n t e s t " )
server . systemctl ( " s t a r t f o r g e j o - d u m p " )
assert " Z s t a n d a r d c o m p r e s s e d d a t a " in server . succeed ( " f i l e ${ dumpFile } " )
server . copy_from_vm ( " ${ dumpFile } " )
2023-10-09 19:29:22 +00:00
'' ;
} ) ;
in
2024-04-21 15:54:59 +00:00
listToAttrs ( map makeForgejoTest supportedDbTypes )