mirror of
				https://git.lapiole.org/dani/ansible-roles.git
				synced 2025-10-31 02:41:36 +01:00 
			
		
		
		
	Update to 2021-12-31 14:05
This commit is contained in:
		
							
								
								
									
										14
									
								
								roles/rpm_build_server/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								roles/rpm_build_server/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| # RPM Build Server | ||||
|  | ||||
| # Description | ||||
| This role will configure an rpm build server | ||||
|  | ||||
| # Compatibility | ||||
| The role is testing on the following distributions | ||||
| * AlmaLinux 8 | ||||
|  | ||||
| # Settings | ||||
|  | ||||
| # Installation | ||||
|  | ||||
| # Upgrades | ||||
							
								
								
									
										47
									
								
								roles/rpm_build_server/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								roles/rpm_build_server/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| --- | ||||
|  | ||||
| rpm_root_dir: /opt/rpm-build | ||||
| rpm_packager: RPM Builder <rpms@{{ ansible_domain }}> | ||||
| # User account under which the buildsys will run | ||||
| # will be created | ||||
| rpm_user: rpmbuilder | ||||
| # Unix group allowed to submit builds | ||||
| rpm_build_group: rpmbuilders | ||||
| # Admin email where notifications will be sent | ||||
| rpm_admin_email: "{{ system_admin_email | default('root@' ~ ansible_domain) }}" | ||||
| # name of the GPG key used to sign the packages | ||||
| rpm_gpg_name: RPM Signing Key | ||||
| rpm_gpg_email: rpms@{{ ansible_domain }} | ||||
| # optional passphrase for the GPG Key | ||||
| # rpm_gpg_pass: S3cr3tP@ssPhr4z | ||||
|  | ||||
| # You can configure remote mirrors to which the local repo will be synced with rsync | ||||
| # rpm_mirrors: | ||||
| #   - dest: repo@repo.example.org:/opt/repo/rpms/ | ||||
| #     rsync_opts: | ||||
| #       - '--times' | ||||
| #       - '--recursive' | ||||
| #       - '--partial' | ||||
| #       - '--delete-after' | ||||
| #       - '--exclude=archives' | ||||
|  | ||||
| # A list of rsync options which will be used to sync repo to mirrors | ||||
| # This is a fallback if rsync_opts is not defined for a mirror | ||||
| rpm_mirror_rsync_opts: | ||||
|   - '--times' | ||||
|   - '--recursive' | ||||
|   - '--partial' | ||||
|   - '--delete-after' | ||||
|  | ||||
| # You can use an LDAP server to lookup email address of build | ||||
| # submitters. The buildsys will first get the username of the uploaded SRPM | ||||
| # and then lookup into LDAP as configured here for the corresponding email address | ||||
| # If an email if found, notifications will be sent to the submitter's address | ||||
| rpm_ldap_servers: "{{ ad_ldap_servers is defined | ternary(ad_ldap_servers | map('regex_replace', '^(.*)', 'ldap://\\1') | list, []) }}" | ||||
| rpm_ldap_start_tls: True | ||||
| # rpm_ldap_bind_dn: CN=Build System,OU=Apps,DC=foo,DC=bar | ||||
| # rpm_ldap_bind_pass: S3cr3t. | ||||
| rpm_ldap_search_base: "{{ ad_ldap_user_search_base is defined | ternary(ad_ldap_user_search_base, ansible_domain | regex_replace('\\.', ',DC=')) }}" | ||||
| # The {user} string will be replaced with the username of the submiter of the build | ||||
| rpm_ldap_search_filter: (&(objectClass=user)(userPrincipalName={user})(mail=*)) | ||||
| rpm_ldap_email_attr: mail | ||||
							
								
								
									
										357
									
								
								roles/rpm_build_server/files/watcher.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								roles/rpm_build_server/files/watcher.pl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,357 @@ | ||||
| #!/usr/bin/perl | ||||
|  | ||||
| use strict; | ||||
| use warnings; | ||||
| use Linux::Inotify2; | ||||
| use YAML::Tiny; | ||||
| use Getopt::Long; | ||||
| use File::stat; | ||||
| use File::Find; | ||||
| use File::Basename; | ||||
| use File::Path qw(make_path); | ||||
| use File::Copy qw(move); | ||||
| use AnyEvent; | ||||
| use RPM2; | ||||
| use Time::HiRes 'time'; | ||||
| use Email::MIME; | ||||
| use Email::Sender::Simple qw(sendmail); | ||||
| use Email::Sender::Transport::Sendmail; | ||||
| use Net::LDAP; | ||||
|  | ||||
| # Init an empty conf | ||||
| my $conf = {}; | ||||
|  | ||||
| # Disable output buffering | ||||
| $| = 1; | ||||
|  | ||||
| # Defaults for command line flags | ||||
| my $opt = { | ||||
|   config  => '../etc/config.yml', | ||||
|   verbose => 0, | ||||
|   quiet   => 0 | ||||
| }; | ||||
|  | ||||
| # Read some options from the command line | ||||
| GetOptions ( | ||||
|   'config=s' => \$opt->{config}, | ||||
|   'quiet'    => \$opt->{quiet}, | ||||
|   'verbose'  => \$opt->{verbose} | ||||
| ); | ||||
|  | ||||
| # Check if the config file exists, and if so, parse it | ||||
| # and load it in $conf | ||||
| if ( -e $opt->{config} ) { | ||||
|   log_verbose( "Reading config file " . $opt->{config} ); | ||||
|   my $yaml = YAML::Tiny->read( $opt->{config} ); | ||||
|  | ||||
|   if ( not $yaml or not $yaml->[0] ) { | ||||
|     die "Config file " . $opt->{config} . " is invalid\n"; | ||||
|   } | ||||
|   $conf = $yaml->[0]; | ||||
| } else { | ||||
|   # If the config file doesn't exist, just die | ||||
|   die "Config file " . $opt->{config} . " doesn't exist\n"; | ||||
| } | ||||
|  | ||||
| # If ldap is configured, we'll use it to lookup email | ||||
| # addresses of submitters to send them notifications | ||||
| my $ldap; | ||||
| my $ldap_msg; | ||||
| if (defined $conf->{ldap} and defined $conf->{ldap}->{servers}){ | ||||
|   log_verbose("Connecting to " . join(', ', @{$conf->{ldap}->{servers}})); | ||||
|   $ldap = new Net::LDAP($conf->{ldap}->{servers}, | ||||
|     timeout => 10, | ||||
|   ); | ||||
|   if (not defined $ldap){ | ||||
|     log_info("Couldn't connect to any LDAP servers (" . join(',', @{$conf->{ldap}->{servers}}) . ")"); | ||||
|   } else { | ||||
|     if (defined $conf->{ldap}->{start_tls} and $conf->{ldap}->{start_tls}){ | ||||
|       log_verbose("Upgrade LDAP connection using StartTLS"); | ||||
|       $ldap_msg = $ldap->start_tls( | ||||
|         verify => 'require' | ||||
|       ); | ||||
|       if ($ldap_msg->code){ | ||||
|         log_verbose("StartTLS failed : " . $ldap_msg->error); | ||||
|         log_verbose("LDAP support will be disabled"); | ||||
|         $ldap = undef; | ||||
|       } | ||||
|     } | ||||
|     if (defined $conf->{ldap}->{bind_dn} and defined $conf->{ldap}->{bind_pass}){ | ||||
|       log_verbose("Binding as $conf->{ldap}->{bind_dn}"); | ||||
|       $ldap_msg = $ldap->bind( | ||||
|         $conf->{ldap}->{bind_dn}, | ||||
|         password => $conf->{ldap}->{bind_pass} | ||||
|       ); | ||||
|       if ($ldap_msg->code){ | ||||
|         log_verbose("LDAP bind failed : " . $ldap_msg->error); | ||||
|         log_verbose("LDAP support will be disabled"); | ||||
|         $ldap = undef; | ||||
|       } | ||||
|     } else { | ||||
|       log_verbose("Using anonymous bind"); | ||||
|       $ldap_msg = $ldap->bind; | ||||
|     } | ||||
|   } | ||||
| } else { | ||||
|   log_verbose("No LDAP servers configured"); | ||||
| } | ||||
|  | ||||
| my $inotify = new Linux::Inotify2 | ||||
|    or die "Unable to create new inotify object: $!"; | ||||
|  | ||||
| log_verbose("Searching for folders in $conf->{paths}->{uploads}"); | ||||
| find({ | ||||
|   wanted => sub { -d and create_watcher($inotify, $File::Find::name); } | ||||
| }, $conf->{paths}->{uploads}); | ||||
|  | ||||
| my $cv = AnyEvent->condvar; | ||||
|  | ||||
| my $poller = AnyEvent->io( | ||||
|   fh   => $inotify->fileno, | ||||
|   poll => 'r', | ||||
|   cb   => sub { $inotify->poll } | ||||
| ); | ||||
|  | ||||
| # Receive event signals (inotify signals) | ||||
| $cv->recv; | ||||
|  | ||||
| # Print messages only if the verbose flag was given | ||||
| sub log_verbose { | ||||
|   my $msg = shift; | ||||
|   print $msg . "\n" if ( $opt->{verbose} ); | ||||
| } | ||||
|  | ||||
| # Print normal messages | ||||
| sub log_info { | ||||
|   my $msg = shift; | ||||
|   print $msg . "\n" if ( not $opt->{quiet} ); | ||||
| } | ||||
|  | ||||
| # Print error messages | ||||
| sub log_error { | ||||
|   my $msg = shift; | ||||
|   print $msg . "\n"; | ||||
| } | ||||
|  | ||||
| # Create a watcher for a specific directory | ||||
| sub create_watcher { | ||||
|   my ($inotify, $dir) = @_; | ||||
|   log_verbose("Start watching folder $dir"); | ||||
|   $inotify->watch ($dir, IN_CLOSE_WRITE | IN_MOVED_TO, sub { | ||||
|     my $event = shift; | ||||
|     my $candidate = $event->fullname; | ||||
|     handle_submit($candidate); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| # takes the path of an SRPM to rebuild, | ||||
| # build it with mock, sign the result, update the repo | ||||
| # and sync to remote mirrors if defined | ||||
| sub handle_submit { | ||||
|   my $srpm = shift; | ||||
|   if (not -f $srpm){ | ||||
|     log_verbose("$srpm isn't a file, ignoring"); | ||||
|     return; | ||||
|   } | ||||
|   if ($srpm !~ m/src\.rpm$/i){ | ||||
|     log_verbose("New file $srpm isn't an src.rpm file, ignoring"); | ||||
|     return; | ||||
|   } | ||||
|   log_info("New file to process $srpm"); | ||||
|   my $submiter = getpwuid(stat($srpm)->uid); | ||||
|   my $email; | ||||
|   log_info("File submited by $submiter"); | ||||
|   if (defined $ldap){ | ||||
|     $email = user2email($submiter); | ||||
|     if (not defined $email){ | ||||
|       log_verbose("LDAP returned no result"); | ||||
|     } | ||||
|   } | ||||
|   if (defined $email){ | ||||
|     log_verbose("Notifications will be sent to $email"); | ||||
|   } else { | ||||
|     log_verbose("No email address for $submiter, no notification will be sent"); | ||||
|   } | ||||
|   my $src_pkg = RPM2->open_package($srpm); | ||||
|   if (not $src_pkg->is_source_package){ | ||||
|     log_verbose("Couldn't parse $srpm as a valid srpm"); | ||||
|     return; | ||||
|   } | ||||
|   my $target = basename(dirname($srpm)); | ||||
|   if (not defined $conf->{targets}->{$target}){ | ||||
|     log_info("$srpm submited for target $target, but it's not defined in the configuration"); | ||||
|   } | ||||
|   foreach my $arch (@{$conf->{targets}->{$target}}){ | ||||
|     my $job_id = $src_pkg->as_nvre() . '-' . time(); | ||||
|     my $result = $conf->{paths}->{builds} . '/' . $submiter . '/' . $target . '-' . $arch . '/' . $job_id; | ||||
|     log_info("Rebuilding $srpm for $target/$arch in $result (job ID $job_id)"); | ||||
|     make_path($result); | ||||
|     my $mock_msg; | ||||
|     foreach my $out (qx(mock -r $target-$arch --resultdir=$result $srpm 2>&1)){ | ||||
|       chomp $out; | ||||
|       $mock_msg .= $out; | ||||
|       log_info("[$job_id] $out"); | ||||
|     } | ||||
|     if ($? != 0) { | ||||
|       log_info("[$job_id] Build submited by $submiter failed"); | ||||
|       handle_error($job_id, 'Mock build', $mock_msg); | ||||
|       return; | ||||
|     } | ||||
|     my $repo_dir = $conf->{paths}->{repo}; | ||||
|     my $repo_cache_dir = $conf->{paths}->{repo_cache}; | ||||
|     if ($src_pkg->release =~ m/\.(beta|git\.)/){ | ||||
|       $repo_dir .= '/testing'; | ||||
|       $repo_cache_dir .= '/testing'; | ||||
|     } | ||||
|     $repo_dir .= '/' . $target; | ||||
|     $repo_cache_dir .= '/' . $target; | ||||
|     find({ | ||||
|       wanted => sub { | ||||
|         return if (not -f); | ||||
|         return if (not $_ =~ m/\.rpm$/); | ||||
|         my $built_pkg = $_; | ||||
|         log_info("[$job_id] Signing package $built_pkg"); | ||||
|         # Note : the optional passphrase for the gpg key is in rpmmacros | ||||
|         qx(rpm --addsign $built_pkg); | ||||
|         if ($? != 0) { | ||||
|           log_info("[$job_id] Signing failed"); | ||||
|           handle_error($job_id, 'Package signature error', "Command rpm --addsign $built_pkg failed"); | ||||
|           return; | ||||
|         } | ||||
|         # Open the package without checking the signature, as the key might not be present in the | ||||
|         # rpm trusted store | ||||
|         my $pkg = RPM2->open_package($built_pkg, RPM2->_rpmvsf_nosignatures); | ||||
|         my $dest = $repo_dir; | ||||
|         if ($pkg->is_source_package){ | ||||
|           $dest .= '/SRPMS'; | ||||
|         } else { | ||||
|           # the resulting RPM can be noarch, so use this instead of $arch | ||||
|           $dest .= '/' . $pkg->arch; | ||||
|         } | ||||
|         log_info("[$job_id] Moving $built_pkg to the repo $dest"); | ||||
|         make_path($dest); | ||||
|         make_path($repo_cache_dir); | ||||
|         move $built_pkg, $dest . '/' . basename($built_pkg); | ||||
|       } | ||||
|     }, $result); | ||||
|     log_info("[$job_id] Updating repo metadata for $target"); | ||||
|     qx(createrepo --checksum sha -x "*debuginfo*" --update -c $repo_cache_dir $repo_dir); | ||||
|     if ($? != 0) { | ||||
|       log_info("[$job_id] Createrepo failed"); | ||||
|       handle_error( | ||||
|         $job_id, | ||||
|         'Createrepo error', | ||||
|         "Command createrepo --checksum sha -x \"*debuginfo*\" --update -c $repo_cache_dir $repo_dir" | ||||
|       ); | ||||
|       return; | ||||
|     } | ||||
|     log_info("[$job_id] Building package finished"); | ||||
|     # Now push to mirrors if defined | ||||
|     if (defined $conf->{mirror} and defined $conf->{mirror}->{push}){ | ||||
|       foreach my $mirror (@{$conf->{mirror}->{push}}){ | ||||
|         log_info("[$job_id] syncing repo to $mirror->{dest}"); | ||||
|         my $rsync_cmd = 'rsync '; | ||||
|         if (defined $mirror->{rsync_opts}){ | ||||
|           $rsync_cmd .= join(' ', @{$mirror->{rsync_opts}}); | ||||
|         } else { | ||||
|           $rsync_cmd .= join(' ', @{$conf->{mirror}->{rsync_opts}}); | ||||
|         } | ||||
|         $rsync_cmd .= ' ' . $conf->{paths}->{repo} . '/ ' . $mirror->{dest} . '/'; | ||||
|         log_verbose("[$job_id] Running command $rsync_cmd"); | ||||
|         foreach my $out (qx($rsync_cmd 2>&1)){ | ||||
|           chomp $out; | ||||
|           log_verbose("[$job_id] $out"); | ||||
|         } | ||||
|         if ($? != 0) { | ||||
|           log_info("[$job_id] Syncing to $mirror->{dest} failed"); | ||||
|           handle_error($job_id, 'Mirror update error', "Command $rsync_cmd failed"); | ||||
|           return; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     if (defined $email){ | ||||
|       my $body = "Resulting RPM are available in $conf->{paths}->{repo}/$target"; | ||||
|       if (defined $conf->{mirror} and defined $conf->{mirror}->{push}){ | ||||
|         $body .= "\nand have been synced to the following mirror:\n"; | ||||
|         foreach my $mirror (@{$conf->{mirror}->{push}}){ | ||||
|           $body .= "$mirror->{dest}\n"; | ||||
|         } | ||||
|       } | ||||
|       send_notification( | ||||
|         $email, | ||||
|         "Rebuilding " . $src_pkg->as_nvre() . " for $target/$arch succeded", | ||||
|         $body | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| # Handle errors. Log it, and notify the admin | ||||
| sub handle_error { | ||||
|   my $job_id = shift; | ||||
|   my $step   = shift; | ||||
|   my $err    = shift; | ||||
|   my $dest   = shift; | ||||
|  | ||||
|   log_error( $err ); | ||||
|   if ( defined $conf->{notify}->{to} ) { | ||||
|     send_notification( | ||||
|       $conf->{notify}->{to}, | ||||
|       "Error while building $job_id", | ||||
|       "Building $job_id failed at step '$step'. The error was\n$err\n" | ||||
|     ); | ||||
|   } | ||||
|   if ( defined $dest ) { | ||||
|     send_notification( | ||||
|       $dest, | ||||
|       "Error while building $job_id", | ||||
|       "Building $job_id failed at step '$step'. The error was\n$err\n" | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| # Send an email message | ||||
| sub send_notification { | ||||
|   my $to = shift; | ||||
|   my $subject = shift; | ||||
|   my $body = shift; | ||||
|   my $mail   = Email::MIME->create(   | ||||
|     header_str => [ | ||||
|       From    => $conf->{notify}->{from}, | ||||
|       To      => $to, | ||||
|       Subject => $subject | ||||
|     ], | ||||
|     attributes => { | ||||
|       charset  => 'utf-8', | ||||
|       encoding => 'base64' | ||||
|     }, | ||||
|     body_str => $body | ||||
|   ); | ||||
|   my $transport = Email::Sender::Transport::Sendmail->new(); | ||||
|   sendmail( $mail, { transport => $transport } ); | ||||
| } | ||||
|  | ||||
| # Lookup in LDAP if we can get the email address of a user | ||||
| sub user2email { | ||||
|   my $user = shift; | ||||
|   if (not defined $ldap or not defined $conf->{ldap}->{search_base} or not defined $conf->{ldap}->{search_filter}){ | ||||
|     return; | ||||
|   } | ||||
|   my $filter = $conf->{ldap}->{search_filter}; | ||||
|   $filter =~ s/\{user\}/$user/g; | ||||
|   log_verbose("Searching in $conf->{ldap}->{search_base} with filter $filter"); | ||||
|   my $results = $ldap->search( | ||||
|     base   => $conf->{ldap}->{search_base}, | ||||
|     filter => $filter, | ||||
|     attrs  => [ $conf->{ldap}->{email_attr} ] | ||||
|   ); | ||||
|   if ($results->code){ | ||||
|     log_verbose("Error occured while searching in LDAP : " . $results->error); | ||||
|     return; | ||||
|   } | ||||
|   if ($results->count != 1){ | ||||
|     log_verbose("Searching returned " . $results->count . "result(s), while it should have returned 1"); | ||||
|     return; | ||||
|   } | ||||
|   return $results->entry(0)->get_value( $conf->{ldap}->{email_attr} ); | ||||
| } | ||||
							
								
								
									
										8
									
								
								roles/rpm_build_server/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								roles/rpm_build_server/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| --- | ||||
|  | ||||
| - name: reset permissions | ||||
|   command: "{{ rpm_root_dir }}/bin/perms.sh" | ||||
|  | ||||
| - name: restart build-watcher | ||||
|   service: name=build-watcher state=restarted | ||||
|  | ||||
							
								
								
									
										58
									
								
								roles/rpm_build_server/tasks/conf.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								roles/rpm_build_server/tasks/conf.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| --- | ||||
|  | ||||
| - name: Deploy mock config | ||||
|   template: src=mock/{{ item }}.j2 dest=/etc/mock/{{ item }} | ||||
|   loop: | ||||
|     - site-defaults.cfg | ||||
|     - el7-x86_64.cfg | ||||
|     - el8-x86_64.cfg | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Deploy rpmmacros | ||||
|   template: src=rpmmacros.j2 dest={{ rpm_root_dir }}/.rpmmacros owner={{ rpm_user }} mode=600 | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Deploy main configuration | ||||
|   template: src=config.yml.j2 dest={{ rpm_root_dir }}/etc/config.yml | ||||
|   notify: restart build-watcher | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Check if gpg key exists | ||||
|   shell: gpg --list-options show-only-fpr-mbox --list-secret-keys | grep -q "{{ rpm_gpg_email }}" | ||||
|   failed_when: False | ||||
|   changed_when: False | ||||
|   register: rpm_gpg_key_exists | ||||
|   become_user: "{{ rpm_user }}" | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Flush handlers to set permissions on directories | ||||
|   meta: flush_handlers | ||||
|   tags: rpm | ||||
|  | ||||
| - when: rpm_gpg_key_exists.rc != 0 | ||||
|   block: | ||||
|     - name: Generate main key | ||||
|       shell: | | ||||
|         gpg --batch \ | ||||
|           --passphrase '{{ rpm_gpg_pass is defined | ternary(rpm_gpg_pass, '') }}' \ | ||||
|           --pinentry-mode loopback \ | ||||
|           --quick-gen-key "{{ rpm_gpg_name }} <{{ rpm_gpg_email }}>" rsa3072 default never | ||||
|  | ||||
|     - name: Get key ID | ||||
|       shell: gpg --list-options show-only-fpr-mbox --list-secret-keys | grep {{ rpm_gpg_email }} | awk '{ print $1 }' | ||||
|       register: rpm_gpg_key_id | ||||
|       changed_when: False | ||||
|  | ||||
|     - name: Add sub key | ||||
|       shell: | | ||||
|         gpg --batch \ | ||||
|           --passphrase '{{ rpm_gpg_pass is defined | ternary(rpm_gpg_pass, '') }}' \ | ||||
|           --pinentry-mode loopback \ | ||||
|           --quick-add-key {{ rpm_gpg_key_id.stdout }} rsa3072 default never \ | ||||
|  | ||||
|     - name: Export public key | ||||
|       shell: gpg --export -a "rpms@lapiole.org" > {{ rpm_root_dir }}/repo/RPM-GPG-KEY | ||||
|  | ||||
|   become_user: "{{ rpm_user }}" | ||||
|   tags: rpm | ||||
|  | ||||
							
								
								
									
										18
									
								
								roles/rpm_build_server/tasks/directories.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								roles/rpm_build_server/tasks/directories.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| --- | ||||
|  | ||||
| - name: Create directories | ||||
|   file: path={{ item.dir }} state=directory owner={{ item.owner | default(omit) }} group={{ item.group | default(omit) }} mode={{ item.mode | default(omit) }} | ||||
|   loop: | ||||
|     - dir: "{{ rpm_root_dir }}" | ||||
|     - dir: "{{ rpm_root_dir }}/mock" | ||||
|     - dir: "{{ rpm_root_dir }}/cache" | ||||
|     - dir: "{{ rpm_root_dir }}/cache/mock" | ||||
|     - dir: "{{ rpm_root_dir }}/cache/repo" | ||||
|     - dir: "{{ rpm_root_dir }}/repo" | ||||
|     - dir: "{{ rpm_root_dir }}/bin" | ||||
|     - dir: "{{ rpm_root_dir }}/uploads/el7" | ||||
|     - dir: "{{ rpm_root_dir }}/uploads/el8" | ||||
|     - dir: "{{ rpm_root_dir }}/errors" | ||||
|     - dir: "{{ rpm_root_dir }}/builds" | ||||
|     - dir: "{{ rpm_root_dir }}/etc" | ||||
|   tags: rpm | ||||
							
								
								
									
										9
									
								
								roles/rpm_build_server/tasks/facts.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								roles/rpm_build_server/tasks/facts.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| --- | ||||
|  | ||||
| - include_vars: "{{ item }}" | ||||
|   with_first_found: | ||||
|     - vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml | ||||
|     - vars/{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml | ||||
|     - vars/{{ ansible_distribution }}.yml | ||||
|     - vars/{{ ansible_os_family }}.yml | ||||
|   tags: rpm | ||||
							
								
								
									
										22
									
								
								roles/rpm_build_server/tasks/install.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								roles/rpm_build_server/tasks/install.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| --- | ||||
|  | ||||
| - name: Deploy permission script | ||||
|   template: src=perms.sh.j2 dest={{ rpm_root_dir }}/bin/perms.sh mode=755 | ||||
|   notify: reset permissions | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Install watcher daemon | ||||
|   copy: src=watcher.pl dest={{ rpm_root_dir }}/bin/watcher.pl mode=755 | ||||
|   notify: restart build-watcher | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Deploy systemd unit | ||||
|   template: src=build-watcher.service.j2 dest=/etc/systemd/system/build-watcher.service | ||||
|   notify: restart build-watcher | ||||
|   register: rpm_unit | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Reload systemd | ||||
|   systemd: daemon_reload=True | ||||
|   when: rpm_unit.changed | ||||
|   tags: rpm | ||||
							
								
								
									
										9
									
								
								roles/rpm_build_server/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								roles/rpm_build_server/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| --- | ||||
|  | ||||
| - include: facts.yml | ||||
| - include: requirements.yml | ||||
| - include: user.yml | ||||
| - include: directories.yml | ||||
| - include: install.yml | ||||
| - include: conf.yml | ||||
| - include: services.yml | ||||
							
								
								
									
										5
									
								
								roles/rpm_build_server/tasks/requirements.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								roles/rpm_build_server/tasks/requirements.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| --- | ||||
|  | ||||
| - name: Install required packages | ||||
|   package: name={{ rpm_packages }} | ||||
|   tags: rpm | ||||
							
								
								
									
										5
									
								
								roles/rpm_build_server/tasks/services.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								roles/rpm_build_server/tasks/services.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| --- | ||||
|  | ||||
| - name: Start and enable the build watcher | ||||
|   service: name=build-watcher state=started enabled=True | ||||
|   tags: rpm | ||||
							
								
								
									
										23
									
								
								roles/rpm_build_server/tasks/user.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								roles/rpm_build_server/tasks/user.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| --- | ||||
|  | ||||
| - name: Create build user | ||||
|   user: | ||||
|     name: "{{ rpm_user }}" | ||||
|     system: True | ||||
|     home: "{{ rpm_root_dir }}" | ||||
|     generate_ssh_key: True | ||||
|     ssh_key_file: .ssh/id_rsa | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Create builder group | ||||
|   group: | ||||
|     name: "{{ rpm_build_group }}" | ||||
|   tags: rpm | ||||
|  | ||||
| - name: Add build user to the mock group | ||||
|   user: | ||||
|     name: "{{ rpm_user }}" | ||||
|     append: True | ||||
|     groups: | ||||
|       - mock | ||||
|   tags: rpm | ||||
							
								
								
									
										16
									
								
								roles/rpm_build_server/templates/build-watcher.service.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								roles/rpm_build_server/templates/build-watcher.service.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| [Unit] | ||||
| Description=RPM Build watcher service | ||||
|  | ||||
| [Service] | ||||
| Type=simple | ||||
| User={{ rpm_user }} | ||||
| Group={{ rpm_user }} | ||||
| ExecStart=/usr/bin/perl {{ rpm_root_dir }}/bin/watcher.pl --config {{ rpm_root_dir }}/etc/config.yml --verbose | ||||
| WorkingDirectory={{ rpm_root_dir }}/ | ||||
| Restart=always | ||||
| ReadWritePaths=/run {{ rpm_root_dir }}/repo {{ rpm_root_dir }}/cache {{ rpm_root_dir }}/builds | ||||
| PrivateTmp=true | ||||
|  | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
|  | ||||
							
								
								
									
										52
									
								
								roles/rpm_build_server/templates/config.yml.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								roles/rpm_build_server/templates/config.yml.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| --- | ||||
|  | ||||
| targets: | ||||
|   el7: | ||||
|     - x86_64 | ||||
|   el8: | ||||
|     - x86_64 | ||||
|  | ||||
| paths: | ||||
|   repo: {{ rpm_root_dir }}/repo | ||||
|   repo_cache: {{ rpm_root_dir }}/cache/repo | ||||
|   builds: {{ rpm_root_dir }}/builds | ||||
|   uploads: {{ rpm_root_dir }}/uploads | ||||
|  | ||||
| notify: | ||||
|   from: buildsys@{{ ansible_domain }} | ||||
|   to: {{ rpm_admin_email }} | ||||
|  | ||||
| {% if rpm_mirrors is defined and rpm_mirrors | length > 0 %} | ||||
| mirror: | ||||
|   push: | ||||
| {% for mirror in rpm_mirrors %} | ||||
|     - dest: {{ mirror.dest }} | ||||
| {% if mirror.rsync_opts is defined %} | ||||
|       rsync_opts: | ||||
| {% for opt in mirror.rsync_opts %} | ||||
|         - '{{ opt }}' | ||||
| {% endfor %} | ||||
| {% endif %} | ||||
| {% endfor %} | ||||
|   rsync_opts: | ||||
| {% for opt in rpm_mirror_rsync_opts %} | ||||
|     - '{{ opt }}' | ||||
| {% endfor %} | ||||
| {% endif %} | ||||
|  | ||||
| ldap: | ||||
| {% if rpm_ldap_servers is defined and rpm_ldap_servers | length > 0 %} | ||||
|   servers: | ||||
| {% for server in rpm_ldap_servers %} | ||||
|     - {{ server }} | ||||
| {% endfor %} | ||||
| {% else %} | ||||
|   servers: [] | ||||
| {% endif %} | ||||
|   start_tls: {{ rpm_ldap_start_tls | ternary('True', 'False') }} | ||||
|   bind_dn: {{ rpm_ldap_bind_dn }} | ||||
|   bind_pass: {{ rpm_ldap_bind_pass | quote }} | ||||
|   search_base: {{ rpm_ldap_search_base }} | ||||
|   search_filter: {{ rpm_ldap_search_filter }} | ||||
|   email_attr: {{ rpm_ldap_email_attr }} | ||||
|  | ||||
							
								
								
									
										1
									
								
								roles/rpm_build_server/templates/gpg-agent.conf.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								roles/rpm_build_server/templates/gpg-agent.conf.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| allow-loopback-pinentry | ||||
							
								
								
									
										2
									
								
								roles/rpm_build_server/templates/gpg.conf.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								roles/rpm_build_server/templates/gpg.conf.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| use-agent | ||||
| pinentry-mode loopback | ||||
							
								
								
									
										25
									
								
								roles/rpm_build_server/templates/mock/el7-x86_64.cfg.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								roles/rpm_build_server/templates/mock/el7-x86_64.cfg.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| include('templates/centos-7.tpl') | ||||
| include('templates/epel-7.tpl') | ||||
|  | ||||
| config_opts['root'] = 'el7-x86_64' | ||||
| config_opts['target_arch'] = 'x86_64' | ||||
| config_opts['legal_host_arches'] = ('x86_64',) | ||||
| config_opts['macros']['%rhel'] = '7' | ||||
| config_opts['macros']['%dist'] = '.el7.dbd' | ||||
|  | ||||
| config_opts['dnf.conf'] += """ | ||||
|  | ||||
| [rpmfusion-free-updates] | ||||
| baseurl = http://download1.rpmfusion.org/free/el/updates/7/x86_64/ | ||||
| gpgcheck = 1 | ||||
| gpgkey = https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-free-el-7 | ||||
| name = RPM Fusion for EL - Free - Updates | ||||
|  | ||||
| [dbd] | ||||
| name=dbd | ||||
| baseurl=http://rpms.lapiole.org/el7/ | ||||
| enabled=1 | ||||
| gpgcheck=1 | ||||
| gpgkey=https://rpms.lapiole.org/RPM-GPG-KEY | ||||
|  | ||||
| """ | ||||
							
								
								
									
										28
									
								
								roles/rpm_build_server/templates/mock/el8-x86_64.cfg.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								roles/rpm_build_server/templates/mock/el8-x86_64.cfg.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| include('templates/almalinux-8.tpl') | ||||
| include('templates/epel-8.tpl') | ||||
|  | ||||
| # Disable use_bootstrap_image until new release | ||||
| # See https://github.com/rpm-software-management/mock/issues/831 | ||||
| config_opts['use_bootstrap_image'] = False | ||||
| config_opts['root'] = 'el8-x86_64' | ||||
| config_opts['target_arch'] = 'x86_64' | ||||
| config_opts['legal_host_arches'] = ('x86_64',) | ||||
| config_opts['macros']['%rhel'] = '8' | ||||
| config_opts['macros']['%dist'] = '.el8.dbd' | ||||
|  | ||||
| config_opts['dnf.conf'] += """ | ||||
|  | ||||
| [rpmfusion-free-updates] | ||||
| baseurl = http://download1.rpmfusion.org/free/el/updates/8/x86_64/ | ||||
| gpgcheck = 1 | ||||
| gpgkey = https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-free-el-8 | ||||
| name = RPM Fusion for EL - Free - Updates | ||||
|  | ||||
| [dbd] | ||||
| name=dbd | ||||
| baseurl=http://rpms.lapiole.org/el8/ | ||||
| enabled=1 | ||||
| gpgcheck=1 | ||||
| gpgkey=https://rpms.lapiole.org/RPM-GPG-KEY | ||||
|  | ||||
| """ | ||||
							
								
								
									
										17
									
								
								roles/rpm_build_server/templates/mock/site-defaults.cfg.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								roles/rpm_build_server/templates/mock/site-defaults.cfg.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| {% if system_proxy is defined and system_proxy != '' %} | ||||
| config_opts['environment']['http_proxy'] = '{{ system_proxy }}' | ||||
| config_opts['environment']['https_proxy'] = '{{ system_proxy }}' | ||||
| {% endif %} | ||||
| config_opts['createrepo_on_rpms'] = False | ||||
| config_opts['cleanup_on_failure'] = 1 | ||||
| config_opts['cleanup_on_success'] = 1 | ||||
| config_opts['use_bootstrap_image'] = True | ||||
| config_opts['plugin_conf']['root_cache_opts']['compress_program'] = "zstd" | ||||
| config_opts['plugin_conf']['root_cache_opts']['extension'] = ".zst" | ||||
| config_opts['rpmbuild_networking'] = True | ||||
| config_opts['macros']['%distribution'] = "{{ rpm_packager }}" | ||||
| config_opts['macros']['%packager'] = "{{ rpm_packager }}" | ||||
| config_opts['macros']['%vendor'] = "{{ rpm_packager }}" | ||||
| config_opts['basedir'] = '{{ rpm_root_dir }}/mock' | ||||
| config_opts['cache_topdir'] = '{{ rpm_root_dir }}/cache/mock' | ||||
|  | ||||
							
								
								
									
										9
									
								
								roles/rpm_build_server/templates/perms.sh.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								roles/rpm_build_server/templates/perms.sh.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| set -eo pipefail | ||||
|  | ||||
| chown -R {{ rpm_user }} {{ rpm_root_dir }} | ||||
| chmod 770 {{ rpm_root_dir }} | ||||
| setfacl -b -k -R {{ rpm_root_dir }} | ||||
| setfacl -m g:{{ rpm_build_group }}:rX {{ rpm_root_dir }} | ||||
| setfacl -R -m g:{{ rpm_build_group }}:rwX,d:g:{{ rpm_build_group }}:rwX {{ rpm_root_dir }}/uploads {{ rpm_root_dir }}/builds {{ rpm_root_dir }}/repo | ||||
							
								
								
									
										3
									
								
								roles/rpm_build_server/templates/rpmmacros.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								roles/rpm_build_server/templates/rpmmacros.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| %_signature gpg | ||||
| %_gpg_name {{ rpm_gpg_name }} | ||||
| %__gpg_sign_cmd %{__gpg} gpg --no-verbose --no-armor --batch --pinentry-mode loopback --passphrase '{{ (rpm_gpg_pass is defined) | ternary(rpm_gpg_pass, '') }}' --no-secmem-warning -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename} | ||||
							
								
								
									
										18
									
								
								roles/rpm_build_server/vars/RedHat-8.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								roles/rpm_build_server/vars/RedHat-8.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| --- | ||||
|  | ||||
| rpm_packages: | ||||
|   - podman | ||||
|   - mock | ||||
|   - inotify-tools | ||||
|   - zstd | ||||
|   - rsync | ||||
|   - yum-utils | ||||
|   - rpm-sign | ||||
|   - perl-Linux-Inotify2 | ||||
|   - perl-YAML-Tiny | ||||
|   - perl-AnyEvent | ||||
|   - perl-RPM2 | ||||
|   - perl-Time-HiRes | ||||
|   - perl-Email-MIME | ||||
|   - perl-Email-Sender | ||||
|   - perl-LDAP | ||||
		Reference in New Issue
	
	Block a user
	 Daniel Berteaud
					Daniel Berteaud