From patchwork Mon Oct 28 23:09:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Donnellan X-Patchwork-Id: 1185742 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4729Sq09MDz9sPK for ; Tue, 29 Oct 2019 10:11:23 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4729Sp5QRgzDvt5 for ; Tue, 29 Oct 2019 10:11:22 +1100 (AEDT) X-Original-To: snowpatch@lists.ozlabs.org Delivered-To: snowpatch@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=ajd@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4729Qx4hSKzF0PJ for ; Tue, 29 Oct 2019 10:09:45 +1100 (AEDT) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x9SN8x6M081389 for ; Mon, 28 Oct 2019 19:09:41 -0400 Received: from e06smtp02.uk.ibm.com (e06smtp02.uk.ibm.com [195.75.94.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 2vx9mxg7jr-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 28 Oct 2019 19:09:40 -0400 Received: from localhost by e06smtp02.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 28 Oct 2019 23:09:37 -0000 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp02.uk.ibm.com (192.168.101.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Mon, 28 Oct 2019 23:09:35 -0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x9SN9Yn147120536 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 28 Oct 2019 23:09:35 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D4B195204F; Mon, 28 Oct 2019 23:09:34 +0000 (GMT) Received: from ozlabs.au.ibm.com (unknown [9.192.253.14]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 39F145204E; Mon, 28 Oct 2019 23:09:34 +0000 (GMT) Received: from intelligence.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher DHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id 35706A020A; Tue, 29 Oct 2019 10:09:32 +1100 (AEDT) From: Andrew Donnellan To: snowpatch@lists.ozlabs.org Date: Tue, 29 Oct 2019 10:09:23 +1100 X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 19102823-0008-0000-0000-000003288ABF X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19102823-0009-0000-0000-00004A47CA74 Message-Id: <20191028230923.11613-1-ajd@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-10-28_07:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1908290000 definitions=main-1910280215 Subject: [snowpatch] [PATCH] Implement tunable preservation of remote branches X-BeenThere: snowpatch@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Continuous Integration for patch-based workflows List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: snowpatch-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "snowpatch" From: Russell Currey A new parameter, branch_preserve_policy, allows users to specify whether they want to preserve all remote branches, just full series or standalone patches, or none (default, current behaviour). In addition, users can specify a separate remote to push to, allowing branches to be preserved while still deleting them from the main remote used for testing. Signed-off-by: Russell Currey [ajd: rebase on master] Signed-off-by: Andrew Donnellan --- docs/configuration.md | 18 ++++++++++++++++-- examples/openpower.toml | 2 ++ src/main.rs | 25 +++++++++++++++++++++++-- src/settings.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index d4c383fefe9e..0a49b00ed502 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -147,7 +147,21 @@ Example: - `base_remote_name`: the name of the remote where base branches are retrieved from (Optional, defaults to value of remote_name) -- `push_results`: whether test results should be pushed to Patchwork for this project +- `push_results`: whether test results should be pushed to Patchwork for this + project + +- `branch_preserve_policy`: set the policy for how snowpatch will handle + branches on git remotes after tests have run. + + "ALL": preserves all branches on the remote. + "SERIES": only preserves full series or standalone patches. + "NONE": deletes branches on the remote after testing. + + (Optional, defaults to NONE) + +- `branch_preserve_remote`: only valid if `branch_preserve_policy` is not NONE. + Specify the name of a git remote that will only be used for branch + preservation. If set, branches will be deleted on the main remote. (Optional) Individual jobs contain the following: @@ -172,4 +186,4 @@ Individual jobs contain the following: - `warn_on_fail`: if true, this job will return a warning rather than a failure if it fails (Optional, defaults to false) -- Any further parameters will be passed to Jenkins as build parameters \ No newline at end of file +- Any further parameters will be passed to Jenkins as build parameters diff --git a/examples/openpower.toml b/examples/openpower.toml index d72d47ad7c69..a85f9f916981 100644 --- a/examples/openpower.toml +++ b/examples/openpower.toml @@ -43,6 +43,8 @@ token = "33333333333333333333333333333333" remote_uri = "git@github.com:ruscur/skiboot.git" base_remote_name = "origin" push_results = false + branch_preserve_policy = "SERIES" # defaults to NONE + branch_preserve_remote = "gitlab" # branch to push to, but not delete from [[projects.skiboot.jobs]] job = "skiboot-compile-test-snowpatch" diff --git a/src/main.rs b/src/main.rs index 999b16cbdabe..ad1733a23a95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,7 +65,7 @@ mod jenkins; use jenkins::JenkinsBackend; mod settings; -use settings::{Config, Job, Project}; +use settings::{BranchPreservePolicy, Config, Job, Project}; mod git; @@ -194,6 +194,9 @@ fn test_patch( hefty_tests: bool, ) -> Vec { let repo = project.get_repo().unwrap(); + let preserve_policy = project + .branch_preserve_policy + .unwrap_or(BranchPreservePolicy::None); let mut results: Vec = Vec::new(); if !path.is_file() { return results; @@ -206,6 +209,7 @@ fn test_patch( _ => &project.remote_name, }) .unwrap(); + let preserve_remote = &project.branch_preserve_remote; let mut push_callbacks = RemoteCallbacks::new(); push_callbacks.credentials(|_, _, _| git::cred_from_settings(&settings.git)); @@ -244,6 +248,18 @@ fn test_patch( if output.is_ok() { git::push_to_remote(&mut remote, &branch, false, &mut push_opts).unwrap(); + if preserve_remote.is_some() + && (preserve_policy == BranchPreservePolicy::All + || (preserve_policy == BranchPreservePolicy::Series && hefty_tests)) + { + git::push_to_remote( + &mut repo.find_remote(preserve_remote.as_ref().unwrap()).unwrap(), + &branch, + false, + &mut push_opts, + ) + .unwrap(); + } } git::delete_branch(&repo, &tag).unwrap_or_else(|err| { @@ -323,7 +339,12 @@ fn test_patch( results.append(&mut thread.join().unwrap()); // Delete the remote branch now it's not needed any more - git::push_to_remote(&mut remote, &branch, true, &mut push_opts).unwrap(); + if preserve_remote.is_some() + || preserve_policy == BranchPreservePolicy::None + || (preserve_policy == BranchPreservePolicy::Series && !hefty_tests) + { + git::push_to_remote(&mut remote, &branch, true, &mut push_opts).unwrap(); + } } if !successfully_applied { diff --git a/src/settings.rs b/src/settings.rs index e20d2e856834..b3b82894a876 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -29,6 +29,13 @@ use std::io::Read; // TODO: Give more informative error messages when we fail to parse. +#[derive(Deserialize, Clone, PartialEq, Copy)] +pub enum BranchPreservePolicy { + All, + Series, + None, +} + #[derive(Deserialize, Clone)] pub struct Git { pub user: String, @@ -68,6 +75,10 @@ pub struct Project { pub base_remote_name: Option, pub jobs: Vec, pub push_results: bool, + #[serde(default)] // necessary for serde to treat as optional + #[serde(deserialize_with = "parse_preserve_policy")] + pub branch_preserve_policy: Option, + pub branch_preserve_remote: Option, pub category: Option, } @@ -89,6 +100,22 @@ pub struct Job { pub parameters: BTreeMap, } +fn parse_preserve_policy<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + + match s.as_ref() { + "ALL" => Ok(Some(BranchPreservePolicy::All)), + "SERIES" => Ok(Some(BranchPreservePolicy::Series)), + "NONE" => Ok(Some(BranchPreservePolicy::None)), + _ => Err(serde::de::Error::custom( + "branch_preserve_policy not one of ALL, SERIES, NONE", + )), + } +} + impl<'de> Deserialize<'de> for Job { fn deserialize(deserializer: D) -> Result where