diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b8e1226f..ae94670bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). [[#1851](https://github.com/remindmodel/remind/pull/1851)] - **testthat** ignore missing historical.mif in tests because it is an optional input file [[#1857](https://github.com/remindmodel/remind/pull/1857)] +- **scripts** Add scripts for preparing a release + [[#1871](https://github.com/remindmodel/remind/pull/1871)] ### fixed - included CCS from plastic waste incineration in CCS mass flows so it is diff --git a/scripts/start/defineInputData.R b/scripts/start/defineInputData.R new file mode 100644 index 000000000..9b5498d38 --- /dev/null +++ b/scripts/start/defineInputData.R @@ -0,0 +1,21 @@ +# | (C) 2006-2024 Potsdam Institute for Climate Impact Research (PIK) +# | authors, and contributors see CITATION.cff file. This file is part +# | of REMIND and licensed under AGPL-3.0-or-later. Under Section 7 of +# | AGPL-3.0, you are granted additional permissions described in the +# | REMIND License Exception, version 1.0 (see LICENSE file). +# | Contact: remind@pik-potsdam.de +#' construct list of input data files +#' @param cfg list of configs +#' @param remindPath path to REMIND main folder + +defineInputData <- function(cfg, remindPath = ".") { + + regicode <- madrat::regionscode(file.path(remindPath, cfg$regionmapping)) + cfg$input <- c(paste0("rev",cfg$inputRevision,"_",regicode,"_", tolower(cfg$model_name),".tgz"), + paste0("rev",cfg$inputRevision,"_",regicode,ifelse(cfg$extramappings_historic == "","",paste0("-", madrat::regionscode(cfg$extramappings_historic))),"_", tolower(cfg$validationmodel_name),".tgz"), + paste0("CESparametersAndGDX_",cfg$CESandGDXversion,".tgz")) + + # Specify for each element of input_new whether to stop if the respective file could not be downloaded + cfg$stopOnMissing <- c(TRUE, FALSE, TRUE) + return(cfg) +} diff --git a/scripts/start/updateInputData.R b/scripts/start/updateInputData.R index 8f1dd6d39..8a6448618 100644 --- a/scripts/start/updateInputData.R +++ b/scripts/start/updateInputData.R @@ -19,30 +19,25 @@ updateInputData <- function(cfg, remindPath = ".", gamsCompile = FALSE) { } else { input_old <- "no_data" } - regicode <- madrat::regionscode(file.path(remindPath, cfg$regionmapping)) - input_new <- c(paste0("rev",cfg$inputRevision,"_",regicode,"_", tolower(cfg$model_name),".tgz"), - paste0("rev",cfg$inputRevision,"_",regicode,ifelse(cfg$extramappings_historic == "","",paste0("-", madrat::regionscode(cfg$extramappings_historic))),"_", tolower(cfg$validationmodel_name),".tgz"), - paste0("CESparametersAndGDX_",cfg$CESandGDXversion,".tgz")) - # Specify for each element of input_new whether to stop if the respective file could not be downloaded - stopOnMissing <- c(TRUE, FALSE, TRUE) + cfg <- defineInputData(cfg, remindPath) # check if all input files are already there missinginput <- if (isTRUE(gamsCompile)) NULL else missingInputData() requiredinput <- grep("config\\/gdx-files|modules\\/29_CES_parameters\\/load\\/input", missinginput, value = TRUE, invert = TRUE) # download and distribute needed data - if (! setequal(input_new, input_old) || isTRUE(cfg$force_download) || length(requiredinput) > 0) { + if (! setequal(cfg$input, input_old) || isTRUE(cfg$force_download) || length(requiredinput) > 0) { message(if (isTRUE(gamsCompile)) paste0(" ", cfg$title, ": "), if (isTRUE(cfg$force_download)) "You set 'cfg$force_download = TRUE'" else "Your input data are outdated, incomplete or in a different regional resolution", ". New input data are downloaded and distributed.") condSuppress <- function(x) if (isTRUE(gamsCompile)) suppressMessages(x) else x - condSuppress(download_distribute(files = input_new, + condSuppress(download_distribute(files = cfg$input, repositories = cfg$repositories, # defined in your environment variables modelfolder = remindPath, debug = FALSE, - stopOnMissing = if (isTRUE(gamsCompile)) FALSE else stopOnMissing) + stopOnMissing = if (isTRUE(gamsCompile)) FALSE else cfg$stopOnMissing) ) } else if (! isTRUE(gamsCompile)) { message("No input data downloaded and distributed. To enable that, delete input/source_files.log or set cfg$force_download to TRUE.") diff --git a/scripts/utils/postRelease.R b/scripts/utils/postRelease.R new file mode 100644 index 000000000..34ef37e26 --- /dev/null +++ b/scripts/utils/postRelease.R @@ -0,0 +1,53 @@ +# This script is part of a longer workflow. +# Before running this script please perform the steps described here +# https://gitlab.pik-potsdam.de/REMIND/remind-rse/-/wikis/How-to-create-a-REMIND-release + +# in your fork switch to develop and execute this script in the main folder Rscript scripts/utils/postRelease.R + +postRelease <- function() { + gert::git_fetch("upstream") + gert::git_merge("upstream/master") + + pattern <- "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)." + stopifnot(any(grepl(pattern, readLines("CHANGELOG.md"), fixed = TRUE))) + textToAdd <- paste("", + "", + "", + "## [Unreleased]", + "", + "### input data/calibration", + "", + "### changed", + "-", + "", + "### added", + "-", + "", + "### removed", + "-", + "", + "### fixed", + "-", + sep = "\n") + + readLines("CHANGELOG.md") |> + sub(pattern = pattern, replacement = paste0(pattern, textToAdd), fixed = TRUE) |> + writeLines("CHANGELOG.md") + + message("Please perform the following step manually:\n", + "git add -p\n", + "--> When done press ENTER to commit, push and create PR") + gms::getLine() + + gert::git_commit("merge master into develop") + gert::git_push() + # gh pr create --help + # --base branch The branch into which you want your code merged + # --head branch The branch that contains commits for your pull request (default [current branch]) + system(paste0("gh pr create --base develop --title 'merge master into develop' --body ''")) +} + +postRelease() +message("warnings:") +print(warnings()) + diff --git a/scripts/utils/release.R b/scripts/utils/release.R new file mode 100644 index 000000000..5149db9ee --- /dev/null +++ b/scripts/utils/release.R @@ -0,0 +1,99 @@ +# This script is part of a longer workflow. +# Before running this script please perform the steps described here +# https://gitlab.pik-potsdam.de/REMIND/remind-rse/-/wikis/How-to-create-a-REMIND-release + +# in your fork switch to temporary branch (e.g. release-candidate) and +# execute this script in the main folder Rscript scripts/utils/release.R x.y.z + +release <- function(newVersion) { + if (Sys.which("sbatch") == "") { + stop("release must be created on cluster") + } + + releaseDate <- format(Sys.time(), "%Y-%m-%d") + + # Get old version from CITATION.cff + oldVersion <- readLines("CITATION.cff") |> + grep(pattern = "^version: (.*)$", value = TRUE) |> + sub(pattern = "^version: (.*)$", replacement = "\\1") |> + sub(pattern = "dev", replacement = "") + + # Update CHANGELOG.md + githubUrl <- "https://github.com/remindmodel/remind/compare/" + readLines("CHANGELOG.md") |> + # Add version and date of new release + sub(pattern = "## [Unreleased]", replacement = paste0("## [", newVersion, "] - ", releaseDate), fixed = TRUE) |> + # Add two lines with github links that compare versions + sub(pattern = paste0("\\[Unreleased\\]: ", githubUrl, "v(.+)\\.\\.\\.develop"), + replacement = paste0("[Unreleased]: ", githubUrl, "v", newVersion, "...develop\n", + "[", newVersion, "]: ", githubUrl, "v\\1...v", newVersion)) |> + writeLines("CHANGELOG.md") + + # Update version and release date in CITATION.cff + readLines("CITATION.cff") |> + sub(pattern = "^version:.*$", replacement = paste("version:", newVersion)) |> + sub(pattern = "^date-released:.*$", replacement = paste("date-released:", releaseDate)) |> + writeLines("CITATION.cff") + + # Update version in README.md + readLines("README.md") |> + gsub(pattern = oldVersion, replacement = newVersion) |> + writeLines("README.md") + + # Create documentation + message("creating documentation using goxygen...") + goxygen::goxygen(unitPattern = c("\\[","\\]"), + includeCore = TRUE, + output = "html", + max_num_edge_labels = "adjust", + max_num_nodes_for_edge_labels = 15, + startType = NULL) + + # Upload html documentation to RSE server + message("uploading documentation to RSE server") + exitCode <- system(paste0("rsync -e ssh -avz doc/html/* ", + "rse@rse.pik-potsdam.de:/webservice/doc/remind/", newVersion)) + stopifnot(exitCode == 0) + + # Upload input data to RSE server + message("Uploading input data to RSE server") + source("config/default.cfg") + cfg <- defineInputData(cfg) + # Keep mandatory input files only + cfg$input <- cfg$input[cfg$stopOnMissing] + gms::publish_data(cfg,target = "dataupload@rse.pik-potsdam.de:/remind/public") + + message("If not already done please perform the two following steps manually now:\n", + "1. CHANGELOG.md: sort lines in each category: input data/calibration, changed, added, removed, fixed; remove empty categories\n", + "2. git add -p\n", + "--> When done press ENTER to commit, push and create PR") + gms::getLine() + + message("Committing and pushing changes") + gert::git_commit(paste("remind release", newVersion)) + gert::git_push() + + message("Creating tag") + tag <- paste0("v",newVersion) + git_tag_create(name = tag, message = "new tag", repo = ".") + git_tag_push(name = tag, repo = ".") + + message("Creating a PR on GitHub") + # gh pr create --help + # --base branch The branch into which you want your code merged + # --head branch The branch that contains commits for your pull request (default [current branch]) + system(paste0("gh pr create --base master --title 'remind release ", newVersion, "' --body ''")) +} + +# Source function definition of defineInputData() +source("scripts/start/defineInputData.R") + +# Ask user for release version +arguments <- commandArgs(TRUE) +if (length(arguments) != 1) { + stop("Please pass the new version number, e.g. `Rscript scripts/utils/release.R 0.8.15`") +} + +release(arguments) +message("warnings:") +print(warnings())