def send_upstream(self, downstream, upstream): """ Sends the change indicated by the comment upstream. @param downstream - gerrit.Remote downstream object @param upstream - gerrit.Remote upstream object """ # Check if upstream project before doing anything. if not self.is_upstream_project(): return ssh = downstream.SSH() # Check to see if comment indicates a change is upstream ready if not self.is_upstream_indicated(): logger.debug("Change %s: Upstream not indicated" % self.change_id) return # Grab all of the approvals approvals = self.get_approvals(downstream.SSH()) # Check to see if comment has necessary approvals. if self.is_forced(): if not self.is_release_approved(approvals): msg = "Could not send to upstream: Release not approved." logger.debug("Change %s: %s" % (self.change_id, msg)) ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) return msg = ("***WARNING***\n%s (%s) has requested a forced upstream " "push. Bypassing all votes except for Release...\n\n" "Current votes are:\n\n%s" % (self._data['author']['name'], self._data['author']['email'], self.stringify_approvals(approvals))) logger.debug("Change %s: %s" % (self.change_id, msg)) ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) else: if not self.is_upstream_approved(approvals): msg = ("Could not send to upstream: One or more labels" " not approved.") logger.debug("Change %s: %s" % (self.change_id, msg)) ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) return # Do some git stuffs to push upstream logger.debug("Change %s: Sending to upstream" % self.change_id) repo_dir = '~/tmp' repo_dir = os.path.expanduser(repo_dir) repo_dir = os.path.abspath(repo_dir) # Add uuid, want a unique directory here uuid_dir = str(uuid4()) repo_dir = os.path.join(repo_dir, uuid_dir) # Make Empty directory - We want this to stop and fail on OSError if not os.path.isdir(repo_dir): os.makedirs(repo_dir) logger.debug( "Change %s: Created directory %s" % (self.change_id, repo_dir) ) # Save the current working directory old_cwd = os.getcwd() try: # Change to newly created directory. os.chdir(repo_dir) # Init the cwd git.init() # Add the remotes for upstream and downstream remote_url = "ssh://%[email protected]%s:%s/%s" git.add_remote('downstream', remote_url % (downstream.username, downstream.host, downstream.port, self.project)) # Figure out what user we will pose as # This every upstream user sharing the same key is kinda shady. # Default back to the configured user if username doesnt exist. # should fail in this case username = self.patchset_uploader_username name = self.patchSet_uploader_name email = self.patchset_uploader_email if not username: logger.debug("Change %s: Unable to use author credentials." " Defaulting to configured credentials." % self.change_id) username = upstream.username name = self._conf['git-config']['name'] email = self._conf['git-config']['email'] git.add_remote('upstream', remote_url % (username, upstream.host, upstream.port, self.project)) logger.debug('Change %s: Sending upstream as ' 'username %s, email %s, name %s' % (self.change_id, username, email, name)) try: env = get_review_env() # Set committer info git.set_config('user.email', email) git.set_config('user.name', name) # Download specific change to local args = ['git-review', '-r', 'downstream', '-d', '%s,%s' % (self.change_id, self.patchset_id)] logger.debug('Change %s: running: %s' % (self.change_id, ' '.join(args))) out = subprocess.check_output(args, stderr=subprocess.STDOUT, env=env) logger.debug("Change %s: %s" % (self.change_id, out)) # Send downloaded change to upstream args = ['git-review', '-R', '-y', '-r', 'upstream', self.branch, '-t', self.topic] logger.debug('Change %s: running: %s' % (self.change_id, ' '.join(args))) out = subprocess.check_output(args, stderr=subprocess.STDOUT, env=env) logger.debug("Change %s: %s" % (self.change_id, out)) upstream_url = self.get_upstream_url(upstream) msg = 'Sent to upstream: %s' % (upstream_url) # Send comment to downstream gerrit with link to change in # upstream gerrit ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) except subprocess.CalledProcessError as e: msg = "Could not send to upstream:\n%s" % e.output ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) logger.error("Change %s: Unable to send to upstream" % self.change_id) logger.error("Change %s: %s" % (self.change_id, out)) except Exception: msg = 'Could not send to upstream: Error running git-review' ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) logger.exception("Change %s: Unable to send to upstream" % self.change_id) finally: # Change to old current working directory os.chdir(old_cwd) # Attempt to clean up created directory shutil.rmtree(repo_dir)
def send_upstream(self, downstream, upstream): """ Sends the change indicated by the comment upstream. @param downstream - gerrit.Remote downstream object @param upstream - gerrit.Remote upstream object """ # Check if upstream project before doing anything. if not self.is_upstream_project(): return ssh = downstream.SSH() # Check to see if comment indicates a change is upstream ready if not self.is_upstream_indicated(): logger.debug("Change %s: Upstream not indicated" % self.change_id) return # Grab all of the approvals approvals = self.get_approvals(downstream.SSH()) # Check to see if comment has necessary approvals. if not self.is_upstream_approved(approvals): msg = ("Could not send to upstream: One or more labels" " not approved.") logger.debug("Change %s: %s" % (self.change_id, msg)) ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) return # Do some git stuffs to push upstream logger.debug("Change %s: Sending to upstream" % self.change_id) repo_dir = '~/tmp' repo_dir = os.path.expanduser(repo_dir) repo_dir = os.path.abspath(repo_dir) # Add uuid, want a unique directory here uuid_dir = str(uuid4()) repo_dir = os.path.join(repo_dir, uuid_dir) # Make Empty directory - We want this to stop and fail on OSError if not os.path.isdir(repo_dir): os.makedirs(repo_dir) logger.debug("Change %s: Created directory %s" % (self.change_id, repo_dir)) # Save the current working directory old_cwd = os.getcwd() try: # Change to newly created directory. os.chdir(repo_dir) # Init the cwd git.init() # Add the remotes for upstream and downstream remote_url = "ssh://%[email protected]%s:%s/%s" git.add_remote( 'downstream', remote_url % (downstream.username, downstream.host, downstream.port, self.project)) # Figure out what user we will pose as # This every upstream user sharing the same key is kinda shady. # Default back to the configured user if username doesnt exist. # should fail in this case username = self.change_owner_username name = self.change_owner_name email = self.change_owner_email if not username: logger.debug("Change %s: Unable to use author credentials." " Defaulting to configured credentials." % self.change_id) username = upstream.username name = self._conf['git-config']['name'] email = self._conf['git-config']['email'] git.add_remote( 'upstream', remote_url % (username, upstream.host, upstream.port, self.project)) logger.debug('Change %s: Sending upstream as ' 'username %s, email %s, name %s' % (self.change_id, username, email, name)) try: env = get_review_env() # Set committer info git.set_config('user.email', email) git.set_config('user.name', name) # Download specific change to local args = [ 'git-review', '-r', 'downstream', '-d', '%s,%s' % (self.change_id, self.patchset_id) ] logger.debug('Change %s: running: %s' % (self.change_id, ' '.join(args))) out = subprocess.check_output(args, stderr=subprocess.STDOUT, env=env) logger.debug("Change %s: %s" % (self.change_id, out)) # Send downloaded change to upstream args = [ 'git-review', '-y', '-r', 'upstream', self.branch, '-t', self.topic ] logger.debug('Change %s: running: %s' % (self.change_id, ' '.join(args))) out = subprocess.check_output(args, stderr=subprocess.STDOUT, env=env) logger.debug("Change %s: %s" % (self.change_id, out)) upstream_url = self.get_upstream_url(upstream) msg = 'Sent to upstream: %s' % (upstream_url) # Send comment to downstream gerrit with link to change in # upstream gerrit ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) except subprocess.CalledProcessError as e: msg = "Could not send to upstream:\n%s" % e.output ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) logger.error("Change %s: Unable to send to upstream" % self.change_id) logger.error("Change %s: %s" % (self.change_id, out)) except Exception: msg = 'Could not send to upstream: Error running git-review' ssh.exec_once('gerrit review -m %s %s' % (pipes.quote(msg), self.revision)) logger.exception("Change %s: Unable to send to upstream" % self.change_id) finally: # Change to old current working directory os.chdir(old_cwd) # Attempt to clean up created directory shutil.rmtree(repo_dir)
def _config(self, remote, conf, groups): """ Builds the groups file and project.config file for a project. @param remote - gerrit.Remote object @param conf - Dict containing git config information @param groups - List of groups """ if not self.config: return msg = "Project %s: Configuring." % self.name logger.info(msg) print msg repo_dir = '~/tmp' repo_dir = os.path.expanduser(repo_dir) repo_dir = os.path.abspath(repo_dir) uuid_dir = str(uuid4()) repo_dir = os.path.join(repo_dir, uuid_dir) # Make Empty directory - We want this to stop and fail on OSError logger.debug( "Project %s: Creating directory %s" % (self.name, repo_dir) ) os.makedirs(repo_dir) # Save the current working directory old_cwd = os.getcwd() origin = 'origin' try: # Change cwd to that repo os.chdir(repo_dir) # Git init empty directory git.init() # Add remote origin ssh_url = 'ssh://%[email protected]%s:%s/%s' % ( remote.username, remote.host, remote.port, self.name ) git.add_remote(origin, ssh_url) # Fetch refs/meta/config for project refspec = 'refs/meta/config:refs/remotes/origin/meta/config' git.fetch(origin, refspec) # Checkout refs/meta/config git.checkout_branch('meta/config') # Get md5 of existing config _file = os.path.join(repo_dir, 'project.config') contents = '' try: with open(_file, 'r') as f: contents = f.read() except IOError: pass existing_md5 = hashlib.md5(contents).hexdigest() # Get md5 of new config with open(self.config, 'r') as f: contents = f.read() new_md5 = hashlib.md5(contents).hexdigest() msg = "Project %s: Md5 comparision\n%s\n%s" msg = msg % (self.name, existing_md5, new_md5) logger.debug(msg) print msg # Only alter if checksums do not match if existing_md5 != new_md5: logger.debug( "Project %s: config md5's are different." % self.name ) # Update project.config file _file = os.path.join(repo_dir, 'project.config') with open(_file, 'w') as f: f.write(contents) # Update groups file group_contents = groups_file_contents(groups) _file = os.path.join(repo_dir, 'groups') with open(_file, 'w') as f: f.write(group_contents) # Git config user.email git.set_config('user.email', conf['git-config']['email']) # Git config user.name git.set_config('user.name', conf['git-config']['name']) # Add groups and project.config git.add(['groups', 'project.config']) # Git commit git.commit(message='Setting up %s' % self.name) # Git push git.push(origin, refspecs='meta/config:refs/meta/config') logger.info("Project %s: pushed configuration." % self.name) else: msg = "Project %s: config unchanged." % self.name logger.info(msg) print msg finally: # Change to old current working directory os.chdir(old_cwd) # Attempt to clean up created directory shutil.rmtree(repo_dir)
def _config(self, remote, conf, groups): """ Builds the groups file and project.config file for a project. @param remote - gerrit.Remote object @param conf - Dict containing git config information @param groups - List of groups """ if not self.config: return msg = "Project %s: Configuring." % self.name logger.info(msg) print msg repo_dir = '~/tmp' repo_dir = os.path.expanduser(repo_dir) repo_dir = os.path.abspath(repo_dir) uuid_dir = str(uuid4()) repo_dir = os.path.join(repo_dir, uuid_dir) # Make Empty directory - We want this to stop and fail on OSError logger.debug("Project %s: Creating directory %s" % (self.name, repo_dir)) os.makedirs(repo_dir) # Save the current working directory old_cwd = os.getcwd() origin = 'origin' try: # Change cwd to that repo os.chdir(repo_dir) # Git init empty directory git.init() # Add remote origin ssh_url = 'ssh://%[email protected]%s:%s/%s' % (remote.username, remote.host, remote.port, self.name) git.add_remote(origin, ssh_url) # Fetch refs/meta/config for project refspec = 'refs/meta/config:refs/remotes/origin/meta/config' git.fetch(origin, refspec) # Checkout refs/meta/config git.checkout_branch('meta/config') # Get md5 of existing config _file = os.path.join(repo_dir, 'project.config') contents = '' try: with open(_file, 'r') as f: contents = f.read() except IOError: pass existing_md5 = hashlib.md5(contents).hexdigest() # Get md5 of new config with open(self.config, 'r') as f: contents = f.read() new_md5 = hashlib.md5(contents).hexdigest() msg = "Project %s: Md5 comparision\n%s\n%s" msg = msg % (self.name, existing_md5, new_md5) logger.debug(msg) print msg # Only alter if checksums do not match if existing_md5 != new_md5: logger.debug("Project %s: config md5's are different." % self.name) # Update project.config file _file = os.path.join(repo_dir, 'project.config') with open(_file, 'w') as f: f.write(contents) # Update groups file group_contents = groups_file_contents(groups) _file = os.path.join(repo_dir, 'groups') with open(_file, 'w') as f: f.write(group_contents) # Git config user.email git.set_config('user.email', conf['git-config']['email']) # Git config user.name git.set_config('user.name', conf['git-config']['name']) # Add groups and project.config git.add(['groups', 'project.config']) # Git commit git.commit(message='Setting up %s' % self.name) # Git push git.push(origin, refspecs='meta/config:refs/meta/config') logger.info("Project %s: pushed configuration." % self.name) else: msg = "Project %s: config unchanged." % self.name logger.info(msg) print msg finally: # Change to old current working directory os.chdir(old_cwd) # Attempt to clean up created directory shutil.rmtree(repo_dir)