Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Tests

permissions: read-all
permissions: {}

on:
push:
Expand All @@ -16,17 +16,30 @@ jobs:
- "artifact-post-action/auto-assign"
- "artifact-post-action/compute-risk"
- "artifact-post-action/post-action-add-comment"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
name: Tests (${{ matrix.tuleap_functions }})
defaults:
run:
working-directory: ${{ matrix.tuleap_functions }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: cachix/install-nix-action@fd24c48048070c1be9acd18c9d369a83f0fe94d7 # v31.8.1
- name: Prepare
run: nix-shell --run "make prepare"
- name: Tests
run: nix-shell --pure --run "make tests"
- name: Build
run: nix-shell --pure --run "make build"
formatting_linting:
name: Check for formatting or linting issues
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: cachix/install-nix-action@fd24c48048070c1be9acd18c9d369a83f0fe94d7 # v31.8.1
- name: Build
run: nix-shell --pure --run 'treefmt --ci'
13 changes: 7 additions & 6 deletions artifact-post-action/auto-assign/javy.nix
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# TODO:
# * build from sources
# * upstream to nixpkgs
{ stdenv
, lib
, fetchurl
, autoPatchelfHook
, gzip
{
stdenv,
lib,
fetchurl,
autoPatchelfHook,
gzip,
}:

stdenv.mkDerivation rec {
Expand All @@ -25,7 +26,7 @@ stdenv.mkDerivation rec {
buildInputs = [
stdenv.cc.cc.lib
];

unpackPhase = ''
runHook preUnpack
gzip -cd "${src}" > javy
Expand Down
4 changes: 3 additions & 1 deletion artifact-post-action/auto-assign/shell.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{ pkgs ? (import ../tools/pinned-nixpkgs.nix) {} }:
{
pkgs ? (import ../../build-support/pinned-nixpkgs.nix) { },
}:

pkgs.mkShellNoCC {
buildInputs = [
Expand Down
10 changes: 8 additions & 2 deletions artifact-post-action/compute-risk-and-residual/shell.nix
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{ pkgs ? (import ./../tools/pinned-nixpkgs.nix) {} }:
{
pkgs ? (import ./../../build-support/pinned-nixpkgs.nix) { },
}:

pkgs.mkShellNoCC {
buildInputs = [
(pkgs.rust-bin.stable.latest.default.override {
targets = [ "wasm32-wasip1" ];
extensions = [ "cargo" "rustc" "rust-src" ];
extensions = [
"cargo"
"rustc"
"rust-src"
];
})
pkgs.gnumake
];
Expand Down
123 changes: 69 additions & 54 deletions artifact-post-action/compute-risk-and-residual/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::error::Error;
use std::io::stdin;
Expand Down Expand Up @@ -51,17 +51,11 @@ enum ListValue {
#[serde(tag = "type")]
enum FieldValue {
#[serde(rename = "string")]
String {
field_id: u32,
},
String { field_id: u32 },
#[serde(rename = "text")]
Text {
field_id: u32,
},
Text { field_id: u32 },
#[serde(rename = "art_link")]
Link {
field_id: u32,
},
Link { field_id: u32 },
#[serde(rename = "sb")]
SelectBox {
field_id: u32,
Expand All @@ -70,15 +64,9 @@ enum FieldValue {
bind_value_ids: Vec<u32>,
},
#[serde(rename = "aid")]
ArtifactId {
field_id: u32,
label: String,
},
ArtifactId { field_id: u32, label: String },
#[serde(rename = "rb")]
RadioButton {
field_id: u32,
label: String,
},
RadioButton { field_id: u32, label: String },
}

#[derive(Serialize, Deserialize)]
Expand All @@ -103,7 +91,7 @@ struct TrackerField {
#[derive(Serialize, Deserialize)]
struct Tracker {
id: u32,
fields: Vec<TrackerField>
fields: Vec<TrackerField>,
}

#[derive(Serialize, Deserialize)]
Expand All @@ -120,32 +108,51 @@ fn convert_label_to_integer(label: String) -> Result<u32, Box<dyn Error>> {
}
}

fn find_select_box_by_label<'a>(changeset: &'a Changeset, target_label: &str) -> Option<&'a FieldValue> {
changeset.values.iter().find(|field_value| match field_value {
FieldValue::SelectBox { label, .. } if label == target_label => true,
_ => false,
})
fn find_select_box_by_label<'a>(
changeset: &'a Changeset,
target_label: &str,
) -> Option<&'a FieldValue> {
changeset
.values
.iter()
.find(|field_value| match field_value {
FieldValue::SelectBox { label, .. } if label == target_label => true,
_ => false,
})
}

fn find_value_matching_label(field_value: &FieldValue) -> Option<String> {
match field_value {
FieldValue::SelectBox { values, .. } => values.first().and_then(|first_value| match first_value {
ListValue::StaticValue { label, .. } => Some(label.to_string()),
_ => None,
}),
FieldValue::SelectBox { values, .. } => {
values.first().and_then(|first_value| match first_value {
ListValue::StaticValue { label, .. } => Some(label.to_string()),
_ => None,
})
}
_ => None,
}
}

fn find_select_box_value_by_label(artifact: &Artifact, target_label: &str) -> Result<Option<u32>, Box<dyn Error>> {
fn find_select_box_value_by_label(
artifact: &Artifact,
target_label: &str,
) -> Result<Option<u32>, Box<dyn Error>> {
find_select_box_by_label(&artifact.current, target_label)
.and_then(|field_value| find_value_matching_label(field_value) )
.and_then(|label| Some(convert_label_to_integer(label)))
.transpose()
.and_then(|field_value| find_value_matching_label(field_value))
.and_then(|label| Some(convert_label_to_integer(label)))
.transpose()
}

fn find_risk_value(artifact: &Artifact, risk_field_label: &str, product: u32) -> Result<Option<FieldValueBinding>, Box<dyn Error>> {
let risk_field_option = artifact.tracker.fields.iter().find(|field| field.label == risk_field_label);
fn find_risk_value(
artifact: &Artifact,
risk_field_label: &str,
product: u32,
) -> Result<Option<FieldValueBinding>, Box<dyn Error>> {
let risk_field_option = artifact
.tracker
.fields
.iter()
.find(|field| field.label == risk_field_label);

if risk_field_option.is_none() {
return Err(format!("Cannot find field {}", risk_field_label).into());
Expand All @@ -157,10 +164,9 @@ fn find_risk_value(artifact: &Artifact, risk_field_label: &str, product: u32) ->
}
let risk_values = risk_field.values.as_ref().unwrap();

let matching_value = risk_values.iter()
.find(|value| {
value.label.as_str() == product.to_string()
});
let matching_value = risk_values
.iter()
.find(|value| value.label.as_str() == product.to_string());

if let Some(matching_value) = matching_value {
Ok(Some(FieldValueBinding {
Expand All @@ -172,7 +178,12 @@ fn find_risk_value(artifact: &Artifact, risk_field_label: &str, product: u32) ->
}
}

fn process_risk_values(artifact: &Artifact, severity_field_label: &str, probability_field_label: &str, risk_field_label: &str) -> Result<Option<FieldValueBinding>, Box<dyn Error>> {
fn process_risk_values(
artifact: &Artifact,
severity_field_label: &str,
probability_field_label: &str,
risk_field_label: &str,
) -> Result<Option<FieldValueBinding>, Box<dyn Error>> {
let severity = find_select_box_value_by_label(&artifact, severity_field_label)?;
if severity.is_none() {
return Ok(None);
Expand All @@ -184,7 +195,7 @@ fn process_risk_values(artifact: &Artifact, severity_field_label: &str, probabil
return Ok(None);
}
let probability_value = probability.unwrap();

let product = severity_value * probability_value;

find_risk_value(artifact, risk_field_label, product)
Expand All @@ -198,26 +209,30 @@ fn main() -> Result<(), Box<dyn Error>> {

let mut bindings: Vec<FieldValueBinding> = Vec::new();
match process_risk_values(&artifact, "Severity", "Probability", "Risk") {
Ok(possible_binding) => {
match possible_binding {
Some(binding) => bindings.push(binding),
None => ()
}
Ok(possible_binding) => match possible_binding {
Some(binding) => bindings.push(binding),
None => (),
},
Err(e) => return Err(e),
}
match process_risk_values(&artifact, "Residual severity", "Residual probability", "Residual risk level") {
Ok(possible_binding) => {
match possible_binding {
Some(binding) => bindings.push(binding),
None => ()
}
match process_risk_values(
&artifact,
"Residual severity",
"Residual probability",
"Residual risk level",
) {
Ok(possible_binding) => match possible_binding {
Some(binding) => bindings.push(binding),
None => (),
},
Err(e) => return Err(e),
}
println!("{}", json!({
"values": bindings
}));
println!(
"{}",
json!({
"values": bindings
})
);

Ok(())
}
10 changes: 8 additions & 2 deletions artifact-post-action/compute-risk/shell.nix
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{ pkgs ? (import ../tools/pinned-nixpkgs.nix) {} }:
{
pkgs ? (import ../../build-support/pinned-nixpkgs.nix) { },
}:

pkgs.mkShellNoCC {
buildInputs = [
(pkgs.rust-bin.stable.latest.default.override {
targets = [ "wasm32-wasip1" ];
extensions = [ "cargo" "rustc" "rust-src" ];
extensions = [
"cargo"
"rustc"
"rust-src"
];
})
pkgs.gnumake
];
Expand Down
35 changes: 18 additions & 17 deletions artifact-post-action/compute-risk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
use serde_json::{json, Value};
use serde_json::{Value, json};
use std::error::Error;
use std::io::stdin;

Expand Down Expand Up @@ -63,11 +63,7 @@ fn main() -> Result<(), Box<dyn Error>> {

let field_risk = json["tracker"]["fields"]
.as_array()
.and_then(|fields| {
fields
.iter()
.find(|&field| field["label"] == "Risk")
});
.and_then(|fields| fields.iter().find(|&field| field["label"] == "Risk"));

if field_risk.is_none() {
return Err("Cannot find field_risk")?;
Expand All @@ -79,25 +75,30 @@ fn main() -> Result<(), Box<dyn Error>> {
return Err("Cannot find Risk values")?;
}

if let (Some(severity_value), Some(probability_value)) = (field_severity_value, field_probability_value) {
if let (Some(severity_value), Some(probability_value)) =
(field_severity_value, field_probability_value)
{
let product = severity_value * probability_value;

let matching_value = risk_values.unwrap().into_iter()
.find(|&value| {
let matching_value = risk_values.unwrap().into_iter().find(|&value| {
let value_label = value["label"].as_str().unwrap_or_default();
value_label == product.to_string()
});

if let Some(matching_value) = matching_value {
let field_id = field_risk.unwrap()["field_id"].as_i64().unwrap_or(0);
println!("{}", json!({
"values": [{
"field_id": field_id,
"bind_value_ids": [
matching_value["id"]
]
}]
}).to_string());
println!(
"{}",
json!({
"values": [{
"field_id": field_id,
"bind_value_ids": [
matching_value["id"]
]
}]
})
.to_string()
);

Ok(())
} else {
Expand Down
Loading