Reset updater

This commit is contained in:
Nathan McCarty 2021-12-23 13:11:49 -05:00
parent 60ec7b5e22
commit fcd11b66bd
Signed by: thatonelutenist
GPG Key ID: D70DA3DD4D1E9F96
8 changed files with 1772 additions and 287 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
**/result/**
**/result
**/target

View File

@ -10,11 +10,7 @@
utils.lib.eachSystem [ "x86_64-linux" ] (system:
let
sources = builtins.fromJSON (builtins.readFile ./sources.json);
in
with import nixpkgs { system = system; };
{
packages.jdks = builtins.mapAttrs
(name: value:
buildAdoptLike = with import nixpkgs {system = system;}; name: value:
let
cpuName = stdenv.hostPlatform.parsed.cpu.name;
runtimeDependencies = [
@ -26,12 +22,12 @@
runtimeLibraryPath = lib.makeLibraryPath runtimeDependencies;
in
stdenv.mkDerivation rec {
name = "jdk${value.version}";
name = "jdk${toString value.major_version}";
src = builtins.fetchurl {
url = value.url;
url = value.link;
sha256 = value.sha256;
};
version = value.version;
version = value.java_version;
buildInputs = with pkgs; [
alsa-lib
fontconfig
@ -83,17 +79,24 @@
find "$out" -name libfontmanager.so -exec \
patchelf --add-needed libfontconfig.so {} \;
'';
}
};
in
with import nixpkgs { system = system; };
{
packages.adoptium = (builtins.mapAttrs
(name: value:
buildAdoptLike name value
)
sources.${system}.versions;
sources.${system}.adoptium.versions) // {
latest = buildAdoptLike "latest" sources.${system}.adoptium.latest;
stable = buildAdoptLike "stable" sources.${system}.adoptium.stable;
lts = buildAdoptLike "lts" sources.${system}.adoptium.lts;
};
packages.jdk = self.packages.jdks.18;
packages.jdk-lts = self.packages.jdks.17;
packages.jdk18 = self.packages.jdks.18;
packages.jdk17 = self.packages.jdks.17;
packages.jdk16 = self.packages.jdks.16;
packages.jdk11 = self.packages.jdks.11;
packages.latest = self.packages.${system}.adoptium.latest;
packages.stable = self.packages.${system}.adoptium.stable;
packages.lts = self.packages.${system}.adoptium.lts;
defaultPackage = self.packages.jdks.18;
});
}
defaultPackage = self.packages.${system}.stable;
});
}

1
result
View File

@ -1 +0,0 @@
/nix/store/j8c42s14ri5kryqz5fjcjqd736z73bpi-jdk11.0.13+8

View File

@ -1,29 +1,63 @@
{
"x86_64-linux": {
"versions": {
"17": {
"major_version": "17",
"version": "17.0.0+35",
"url": "https://github.com/adoptium/temurin17-binaries/releases/download/jdk17u-2021-10-25-08-48-beta/OpenJDK17U-jdk_x64_linux_hotspot_2021-10-25-08-48.tar.gz",
"sha256": "0lb5mkh752x6d5yvlkcgdr60pas1qxk00jwlr7rm3566ry852vgf"
"adoptium": {
"versions": {
"jdk18": {
"link": "https://github.com/adoptium/temurin18-binaries/releases/download/jdk18-2021-12-17-07-56-beta/OpenJDK18-jdk_x64_linux_hotspot_2021-12-17-07-56.tar.gz",
"major_version": 18,
"java_version": "18-beta+28-202112170011",
"early_access": true,
"sha256": "05jb4qdzb7v8arm1ysghrkyj53k2qaxsb2gnzlkgivgpnv91jbll"
},
"jdk17": {
"link": "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.1%2B12/OpenJDK17U-jdk_x64_linux_hotspot_17.0.1_12.tar.gz",
"major_version": 17,
"java_version": "17.0.1+12",
"early_access": false,
"sha256": "1dj8aky3wv3c6b9r11dsd1rpwz6bnnjc7kzbxqpm5f6bdlkqr8bf"
},
"jdk11": {
"link": "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.13%2B8/OpenJDK11U-jdk_x64_linux_hotspot_11.0.13_8.tar.gz",
"major_version": 11,
"java_version": "11.0.13+8",
"early_access": false,
"sha256": "0c4fa8kbprpgq2h2zv04x85d2jxab8nlyias2dj4x2acpqs0q71v"
},
"jdk8": {
"link": "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u312-b07/OpenJDK8U-jdk_x64_linux_hotspot_8u312b07.tar.gz",
"major_version": 8,
"java_version": "1.8.0_312-b07",
"early_access": false,
"sha256": "022aqglsvs1px07ri8z5kn3lpbp3z90dc6jixdz0mdl3744836b9"
},
"jdk16": {
"link": "https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_linux_hotspot_16.0.2_7.tar.gz",
"major_version": 16,
"java_version": "16.0.2+7",
"early_access": false,
"sha256": "0b1wayg38rckzm1fy4pdm1a1bmjvwvw0vpbxzy7a4nd3fis6sg9j"
}
},
"18": {
"major_version": "18",
"version": "18.0.0+28",
"url": "https://github.com/adoptium/temurin18-binaries/releases/download/jdk18-2021-12-17-07-56-beta/OpenJDK18-jdk_x64_linux_hotspot_2021-12-17-07-56.tar.gz",
"latest": {
"link": "https://github.com/adoptium/temurin18-binaries/releases/download/jdk18-2021-12-17-07-56-beta/OpenJDK18-jdk_x64_linux_hotspot_2021-12-17-07-56.tar.gz",
"major_version": 18,
"java_version": "18-beta+28-202112170011",
"early_access": true,
"sha256": "05jb4qdzb7v8arm1ysghrkyj53k2qaxsb2gnzlkgivgpnv91jbll"
},
"11": {
"major_version": "11",
"version": "11.0.13+8",
"url": "https://github.com/adoptium/temurin11-binaries/releases/download/jdk11u-2021-11-05-11-35-beta/OpenJDK11U-jdk_x64_linux_hotspot_2021-11-05-11-35.tar.gz",
"sha256": "09p60182vz31wxnp43ghlp1q928xfql0wnk7g852s1wiwjr26dm0"
"stable": {
"link": "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.1%2B12/OpenJDK17U-jdk_x64_linux_hotspot_17.0.1_12.tar.gz",
"major_version": 17,
"java_version": "17.0.1+12",
"early_access": false,
"sha256": "1dj8aky3wv3c6b9r11dsd1rpwz6bnnjc7kzbxqpm5f6bdlkqr8bf"
},
"16": {
"major_version": "16",
"version": "16.0.1+9",
"url": "https://github.com/adoptium/temurin16-binaries/releases/download/jdk16u-2021-07-22-01-18-beta/OpenJDK16U-jdk_x64_linux_hotspot_2021-07-22-01-18.tar.gz",
"sha256": "0rgyp5jrwqjxz0ajk94vmwvagk88p5a41sm2ynckq3p7sg992ym0"
"lts": {
"link": "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.1%2B12/OpenJDK17U-jdk_x64_linux_hotspot_17.0.1_12.tar.gz",
"major_version": 17,
"java_version": "17.0.1+12",
"early_access": false,
"sha256": "1dj8aky3wv3c6b9r11dsd1rpwz6bnnjc7kzbxqpm5f6bdlkqr8bf"
}
}
}

1414
updater/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
color-eyre = { version = "0.5.11", default-features = false }
async-std = { version = "1.10.0", features = ["std", "async-global-executor", "futures-lite", "num_cpus", "attributes"], default-features = false }
color-eyre = "0.5.11"
serde = { version = "1.0.132", features = ["derive"] }
serde_json = "1.0.73"
ureq = { version = "2.3.1", features = ["json"] }
url = "2.2.2"
surf = { version = "2.3.2", features = ["h1-client-rustls", "encoding"], default-features = false }

216
updater/src/adoptium.rs Normal file
View File

@ -0,0 +1,216 @@
use std::collections::HashMap;
use color_eyre::{
eyre::{eyre, Context, Result},
Help, SectionExt,
};
use serde::{Deserialize, Serialize};
use surf::Client;
/// Page size
pub const PAGE_SIZE: u64 = 10;
/// Response from `/v3/info/available_releases` endpoint
#[derive(Deserialize, Serialize, Debug)]
pub struct AvailableReleases {
pub available_lts_releases: Vec<u64>,
pub available_releases: Vec<u64>,
pub most_recent_feature_release: u64,
pub most_recent_feature_version: u64,
pub tip_version: u64,
}
/// Package for a particular binary
#[derive(Deserialize, Serialize, Debug)]
pub struct Package {
checksum: String,
checksum_link: String,
download_count: u64,
pub link: String,
metadata_link: String,
name: String,
size: u64,
}
/// Information about a particular binary
#[derive(Deserialize, Serialize, Debug)]
pub struct Binary {
architecture: String,
download_count: u64,
heap_size: String,
image_type: String,
jvm_impl: String,
os: String,
pub package: Package,
project: String,
scm_ref: String,
updated_at: String,
}
/// Information about a source
#[derive(Deserialize, Serialize, Debug)]
pub struct Source {
link: String,
name: String,
size: u64,
}
/// Version data
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)]
pub struct VersionData {
pub build: u64,
pub major: u64,
pub minor: u64,
pub openjdk_version: String,
pub security: u64,
pub semver: String,
}
impl PartialOrd for VersionData {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.major.partial_cmp(&other.major) {
Some(std::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.minor.partial_cmp(&other.minor) {
Some(std::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.security.partial_cmp(&other.security) {
Some(std::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.build.partial_cmp(&other.build)
}
}
impl Ord for VersionData {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap()
}
}
/// Information about a particular feature release
#[derive(Deserialize, Serialize, Debug)]
pub struct Release {
pub binaries: Vec<Binary>,
download_count: u64,
id: String,
release_link: String,
pub release_type: String,
source: Option<Source>,
timestamp: String,
updated_at: String,
vendor: String,
pub version_data: VersionData,
}
impl PartialEq for Release {
fn eq(&self, other: &Self) -> bool {
self.version_data == other.version_data
}
}
impl Eq for Release {}
impl PartialOrd for Release {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.version_data.partial_cmp(&other.version_data)
}
}
impl Ord for Release {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.version_data.cmp(&other.version_data)
}
}
/// Attempts to get the available releases
pub async fn get_available_releases(client: &Client) -> Result<AvailableReleases> {
let endpoint = "https://api.adoptium.net/v3/info/available_releases";
client
.get(endpoint)
.recv_json()
.await
.map_err(|e| eyre!(e))
.context("Failed to request available versions from adoptium")
.with_section(|| endpoint.to_string().header("Failed Request:"))
}
/// Release query struct
#[derive(Deserialize, Serialize, Debug)]
pub struct ReleaseQuery {
architecture: String,
heap_size: String,
image_type: String,
os: String,
page_size: u64,
project: String,
}
/// Attempts to get the release info for a particular version
pub async fn get_release(client: &Client, version: u64, release_type: &str) -> Result<Release> {
let endpoint = format!(
"https://api.adoptium.net/v3/assets/feature_releases/{}/{}",
version, release_type
);
let request = client
.get(endpoint)
.query(&ReleaseQuery {
architecture: "x64".to_string(),
heap_size: "normal".to_string(),
image_type: "jdk".to_string(),
os: "linux".to_string(),
page_size: PAGE_SIZE,
project: "jdk".to_string(),
})
.map_err(|e| eyre!(e))
.context("Failed to build request")?
.build();
let query = request.url().as_str().to_string();
let mut releases: Vec<Release> = client
.recv_json(request)
.await
.map_err(|e| eyre!(e))
.context("Failed to get release information from adoptium")
.with_section(move || query.header("Failed Request"))?;
releases.sort();
match releases.pop() {
Some(release) => Ok(release),
None => Err(eyre!("Adoptium endpoint did not return any valid releases")),
}
}
/// Attempts to get all the versions
pub async fn get_releases(client: &Client) -> Result<HashMap<u64, Release>> {
let available = get_available_releases(client)
.await
.context("Failed to list adoptium releases")?;
let mut output = HashMap::new();
// Get the generally available version of all the available releases
for version in available.available_releases {
let release = get_release(client, version, "ga").await.with_context(|| {
format!(
"Failed to get version {} from the adoptium archive",
version
)
})?;
output.insert(version, release);
}
// See if we already have the latest version
if output.contains_key(&available.most_recent_feature_version) {
// Go ahead and return
Ok(output)
} else {
let version = available.most_recent_feature_version;
// Otherwise try to get an EA version of it
let release = get_release(client, version, "ea").await.with_context(|| {
format!(
"Failed to get version {} (latest) from the adoptium archive",
version
)
})?;
output.insert(version, release);
Ok(output)
}
}

View File

@ -1,227 +1,118 @@
use std::collections::{HashMap, HashSet};
use std::process::Command;
use std::{collections::HashMap, process::Command};
use color_eyre::{
eyre::{bail, Context, ContextCompat, Result},
Help, SectionExt,
eyre::{eyre, Context, Result},
Section, SectionExt,
};
use serde::{Deserialize, Serialize};
use surf::Client;
fn main() -> Result<()> {
color_eyre::install()?;
/// Adoptium API
pub mod adoptium;
// Get the available versions
let versions = get_all_versions()?;
// Uniqueify them
let mut slugs: HashMap<String, (Release, String)> = HashMap::new();
for version in versions {
if let Ok(url) = get_url(&version) {
let slug = version.to_slug();
let entry = slugs.entry(slug).or_insert((version.clone(), url.clone()));
if version > entry.0 {
*entry = (version, url)
}
}
}
let mut sources = Sources {
versions: HashMap::new(),
};
for (_slug, (version, url)) in slugs {
sources.add_release(&version, &url)?;
}
let mut output: HashMap<String, Sources> = HashMap::new();
output.insert("x86_64-linux".to_string(), sources);
let json_output =
serde_json::to_string_pretty(&output).context("Failed to serialize output")?;
println!("{}", json_output);
Ok(())
}
/// Serde serialization format
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct Sources {
versions: HashMap<String, Source>,
}
impl Sources {
fn add_release(&mut self, release: &Release, url: &str) -> Result<()> {
let version = release.to_java_version();
let source = Source {
major_version: release.major.to_string(),
version,
url: url.to_string(),
sha256: get_sha256(url)?,
};
self.versions.insert(release.major.to_string(), source);
Ok(())
}
}
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct Source {
major_version: String,
version: String,
url: String,
/// Java release struct
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct Release {
link: String,
major_version: u64,
java_version: String,
early_access: bool,
sha256: String,
}
/// Serde formatting struct
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, Clone)]
struct Release {
build: usize,
major: usize,
minor: usize,
openjdk_version: String,
security: usize,
semver: String,
/// Sources serialization struct
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct Sources {
versions: HashMap<String, Release>,
latest: Release,
stable: Release,
lts: Release,
}
impl PartialOrd for Release {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.build.partial_cmp(&other.build) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.major.partial_cmp(&other.major) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.minor.partial_cmp(&other.minor) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.openjdk_version.partial_cmp(&other.openjdk_version) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.security.partial_cmp(&other.security) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.openjdk_version.partial_cmp(&other.openjdk_version) {
Some(core::cmp::Ordering::Equal) => Some(core::cmp::Ordering::Equal),
_ => {
let x = self.openjdk_version.split('-').collect::<Vec<_>>();
let x = x[x.len() - 1];
let y = other.openjdk_version.split('-').collect::<Vec<_>>();
let y = y[y.len() - 1];
x.partial_cmp(y)
}
/// System serialization struct
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct System {
adoptium: Sources,
}
impl TryFrom<adoptium::Release> for Release {
type Error = color_eyre::eyre::Report;
fn try_from(value: adoptium::Release) -> Result<Self> {
if value.binaries.len() == 1 {
let package = &value.binaries[0].package;
Ok(Release {
link: package.link.clone(),
major_version: value.version_data.major,
java_version: value.version_data.openjdk_version,
early_access: value.release_type == "ea",
sha256: get_sha256(&package.link).context("Failed to prefetch package")?,
})
} else {
Err(eyre!(
"Adoptium release had an incorrect number of binaries"
))
}
}
}
impl Ord for Release {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap()
}
#[async_std::main]
async fn main() -> Result<()> {
color_eyre::install()?;
// Create a client
let client = Client::new();
// Get list of releases from adoptium, we'll use this for some other things
let available = adoptium::get_available_releases(&client)
.await
.context("Failed to get list of available releases")?;
let lts_version = available
.available_lts_releases
.iter()
.copied()
.max()
.expect("No LTSs?");
// Get adoptium releases
let adoptium_releases = get_adoptium_releases(&client).await?;
// Spit out to the serialization format
let adoptium = Sources {
versions: adoptium_releases
.clone()
.into_iter()
.map(|(k, v)| (format!("jdk{}", k), v))
.collect(),
latest: adoptium_releases
.get(&available.most_recent_feature_version)
.expect("Missing release")
.clone(),
stable: adoptium_releases
.get(&available.most_recent_feature_release)
.expect("Missing release")
.clone(),
lts: adoptium_releases
.get(&lts_version)
.expect("Missing release")
.clone(),
};
let system = System { adoptium };
let mut systems = HashMap::new();
systems.insert("x86_64-linux".to_string(), system);
let output = serde_json::to_string_pretty(&systems).context("Failed to encode sources")?;
println!("{}", output);
Ok(())
}
impl Release {
fn to_slug(&self) -> String {
format!("1.{}.{}", self.major, self.minor)
}
fn to_java_version(&self) -> String {
format!(
"{}.{}.{}+{}",
self.major, self.minor, self.security, self.build
)
}
}
/// Serde formatting struct
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct Versions {
versions: Vec<Release>,
}
/// Get a page of the versions
fn get_versions_page(page: usize) -> Result<Vec<Release>> {
let page = format!("{}", page);
let request = ureq::get("https://api.adoptium.net/v3/info/release_versions")
.query("architecture", "x64")
.query("image_type", "jdk")
.query("os", "linux")
.query("page", &page)
.query("page_size", "50")
.query("project", "jdk");
let url = request.url().to_string();
let response = request
.call()
.with_section(|| format!("Page: {} Url: {}", page, url).header("Failed Request:"))
.context("Failed getting page of versions list")?;
let versions: Versions = response
.into_json()
.with_section(|| format!("Page: {} Url: {}", page, url).header("Failed Request:"))
.context("Failed deserializing page of versions list")?;
Ok(versions.versions)
}
/// Get all the versions available
fn get_all_versions() -> Result<HashSet<Release>> {
let mut versions = HashSet::new();
// Go through the pages until we hit a 404
let mut page_number = 0;
// Err early if the first page fails, so we can have a more useful context message
let mut page =
Ok(get_versions_page(0).context("Failed getting first page in get_all_versions")?);
while let Ok(current_page) = page {
for version in current_page {
versions.insert(version);
}
page_number += 1;
page = get_versions_page(page_number).context("Ran out of pages");
}
Ok(versions)
}
/// Serde deserialization type
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct VersionInfo {
binaries: Vec<BinaryInfo>,
}
/// Serde deserialization type
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct BinaryInfo {
package: PackageInfo,
}
/// Serde deserialization type
#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct PackageInfo {
link: String,
name: String,
}
/// Gets the url for the latest release of a version
fn get_url(version: &Release) -> Result<String> {
let request = ureq::get(&format!(
"https://api.adoptium.net/v3/assets/version/{}",
version.openjdk_version
))
.query("architecture", "x64")
.query("image_type", "jdk")
.query("os", "linux")
.query("page", "0")
.query("page_size", "1")
.query("project", "jdk");
let url = request.url().to_string();
let response = request
.call()
.with_section(|| format!("Url: {}", url).header("Failed Request"))
.context("Failed requesting version information")?;
let version_info: Vec<VersionInfo> = response
.into_json()
.with_section(|| format!("Url: {}", url).header("Failed Request"))
.context("Failed to deserialize response for version information")?;
let version_info = version_info
/// Get the releases from adoptium
pub async fn get_adoptium_releases(client: &Client) -> Result<HashMap<u64, Release>> {
let releases: Result<HashMap<u64, Release>> = adoptium::get_releases(&client)
.await?
.into_iter()
.next()
.context("Nothing providred")?;
.map(|(key, val)| match val.try_into() {
Ok(val) => Ok((key, val)),
Err(err) => Err(err),
})
.collect();
match version_info.binaries.get(0) {
Some(binary_info) => Ok(binary_info.package.link.clone()),
None => bail!("Binary was missing!"),
}
releases.context("Failed getting release from adoptium")
}
/// Gets the nix sha256 for a url