Skip to content

Commit

Permalink
Merge branch 'main' into automated_fixup_code_of_conduct_file_exists
Browse files Browse the repository at this point in the history
  • Loading branch information
Illidian4368 authored Jan 31, 2025
2 parents 5f556e4 + f5fc461 commit f5a0d3d
Show file tree
Hide file tree
Showing 944 changed files with 54,624 additions and 31,407 deletions.
138 changes: 138 additions & 0 deletions .github/workflows/generate-release-yml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env rust-script
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

//!
//! ```cargo
//! [dependencies]
//! anyhow = "1.0.72"
//! atomicwrites = "0.4.1"
//! yaml-rust = "0.4.5"
//! ```
use std::io::Write;
use std::path::Path;

use anyhow::anyhow;
use anyhow::bail;
use atomicwrites::AllowOverwrite;
use atomicwrites::AtomicFile;
use yaml_rust::yaml::Hash;
use yaml_rust::Yaml;
use yaml_rust::YamlEmitter;
use yaml_rust::YamlLoader;

type Pattern = Box<dyn Fn(&str, &str) -> String + 'static>;

fn parse_pattern(pattern: &String) -> Option<(Pattern, Vec<&'static str>)> {
// TODO: generalize this with an external table or something
if pattern.contains("%UBUNTU_LTS_VERSION%") {
Some((
Box::new(move |p: &str, s: &str| p.replace("%UBUNTU_LTS_VERSION%", s)),
vec!["20", "22"],
))
} else if pattern.contains("%FEDORA_STABLE_VERSION%") {
Some((
Box::new(move |p: &str, s: &str| p.replace("%FEDORA_STABLE_VERSION%", s)),
vec!["36", "37", "38"],
))
} else {
None
}
}

fn substitute_value(pattern: &Pattern, value: &Yaml, substitution: &str) -> Yaml {
match value {
Yaml::String(str) => Yaml::String(pattern(&str, substitution)),
Yaml::Array(arr) => Yaml::Array(
arr.iter()
.map(|v| substitute_value(pattern, v, substitution))
.collect(),
),
Yaml::Hash(hm) => {
let mut new = Hash::new();
for (key, value) in hm.iter() {
new.insert(
substitute_value(pattern, &key, substitution),
substitute_value(pattern, &value, substitution),
);
}
Yaml::Hash(new)
}
otherwise => otherwise.clone(),
}
}

fn expand_value(value: &Yaml) -> Yaml {
match value {
Yaml::Array(arr) => Yaml::Array(arr.iter().map(expand_value).collect()),
Yaml::Hash(hm) => {
let mut new = Hash::new();
for (key, value) in hm.iter() {
//println!("key = {:?}", key);
if let Yaml::String(key_str) = key {
if let Some((pat, substitutions)) = parse_pattern(&key_str) {
for substitution in substitutions {
new.insert(
Yaml::String(pat(&key_str, substitution)),
substitute_value(&pat, &value, substitution),
);
}
} else {
new.insert(key.clone(), expand_value(value));
}
} else {
// What does a non-string key mean anyways?
new.insert(key.clone(), expand_value(value));
}
}
Yaml::Hash(new)
}
otherwise => otherwise.clone(),
}
}

fn main() -> anyhow::Result<()> {
let Some(base_path) = std::env::var_os("RUST_SCRIPT_BASE_PATH") else {
bail!("RUST_SCRIPT_BASE_PATH must be set");
};
let base_path = Path::new(&base_path);
let input_path = base_path.join("release.yml.in");
let output_path = base_path.join("release.yml");

let contents = match std::fs::read_to_string(&input_path) {
Ok(contents) => contents,
Err(e) => {
bail!("Unable to read {}: {}", input_path.display(), e);
}
};
let doc = match YamlLoader::load_from_str(&contents) {
Ok(doc) => doc,
Err(e) => {
bail!("Unable to parse {}: {}", input_path.display(), e);
}
};

let new_doc: Vec<Yaml> = doc.iter().map(expand_value).collect();

let mut out_str = String::new();
out_str.extend("# \x40generated by generate-release-yml.rs\n".chars());

let mut emitter = YamlEmitter::new(&mut out_str);
for doc in new_doc {
match emitter.dump(&doc) {
Ok(()) => (),
Err(e) => {
bail!("Unable to generate {}: {}", output_path.display(), e);
}
}
}

let af = AtomicFile::new(&output_path, AllowOverwrite);
af.write(|f| f.write_all(&out_str.as_bytes()))
.map_err(|e| anyhow!("Unable to write {}: {}", output_path.display(), e))
}
Loading

0 comments on commit f5a0d3d

Please sign in to comment.