-
Allan Blanchard authoredAllan Blanchard authored
build-release.sh 14.13 KiB
#! /usr/bin/env bash
##########################################################################
# #
# This file is part of Frama-C. #
# #
# Copyright (C) 2007-2023 #
# CEA (Commissariat à l'énergie atomique et aux énergies #
# alternatives) #
# #
# you can redistribute it and/or modify it under the terms of the GNU #
# Lesser General Public License as published by the Free Software #
# Foundation, version 2.1. #
# #
# It is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU Lesser General Public License for more details. #
# #
# See the GNU Lesser General Public License version 2.1 #
# for more details (enclosed in the file licenses/LGPLv2.1). #
# #
##########################################################################
# Note:
#
# While this script can be run locally, it is meant to run in the Frama-C CI.
# Thus, it expects to be run from the root of the Frama-C directory and that
# some CI artifacts are available. Namely:
# - 'frama-c.tar.gz'
# - 'api' directory (with api archives inside)
# - 'manuals' directory (with all manuals incl. acsl + version text files)
# Availability of the files is checked when the script starts. The script also
# checks that:
# - the version is stable (VERSION file does not contain '+dev')
# - the commit is tagged with the version (if it contains ~, replaced by -)
# - releases/<VERSION_MAJOR>.<VERSION_MINOR>.md exists
# The script generates the following directories:
# - wiki (for the public Frama-C instance)
# - website
# - opam-repository
# - release-data.json
# with the correct tree for generated files.
##########################################################################
# Check binaries
function echo_red {
echo -e "\e[31m$1\e[0m"
}
function echo_green {
echo -e "\e[32m$1\e[0m"
}
function show_step {
echo ""
echo "### $1"
echo ""
}
show_step "Checking binaries availability"
if ! command -v git-lfs >/dev/null 2>/dev/null; then
echo_red "git-lfs is required"
exit 127
fi
# grep needs to be installed
if ! command -v grep --version >/dev/null 2>/dev/null; then
echo_red "grep is required"
exit 127
fi
MANUALS_DIR="./manuals"
API_DIR="./api"
FRAMAC_COM_DOWNLOAD="https://www.frama-c.com/download"
##########################################################################
# Check stable or beta and build names
show_step "Checking version"
VERSION="$(cat VERSION)"
VERSION_SAFE="$(cat VERSION | sed 's/~/-/')"
VERSION_MODIFIER=$(sed VERSION -e s/[0-9.]*\\\(.*\\\)/\\1/)
VERSION_MAJOR=$(sed VERSION -e s/\\\([0-9]*\\\).[0-9]*.*/\\1/)
VERSION_MINOR=$(sed VERSION -e s/[0-9]*.\\\([0-9]*\\\).*/\\1/)
TAG="$(git describe --tag)"
CODENAME="$(cat VERSION_CODENAME)"
LOWER_CODENAME="$(echo "$CODENAME" | tr '[:upper:]' '[:lower:]')"
VERSION_AND_CODENAME="${VERSION_SAFE}-${CODENAME}"
if [ "$VERSION_MINOR" != 0 ]; then
PREVIOUS="$VERSION_MAJOR.$((VERSION_MINOR - 1))"
else
PREVIOUS="$((VERSION_MAJOR - 1)).0"
fi
PREVIOUS_NAME=$(git show $PREVIOUS:VERSION_CODENAME)
if [ "$VERSION_MODIFIER" == "+dev" ]; then
echo "Development version ($VERSION)"
echo_red "Aborting"
exit 2
fi
if [ "$VERSION_SAFE" != "$TAG" ]; then
echo "The current commit is not tagged with the current version:"
echo "Frama-C Version: $VERSION_SAFE"
echo "Frama-C Tag : $TAG"
echo_red "Aborting"
exit 2
fi
if test -n "$VERSION_MODIFIER"; then
FINAL_RELEASE=no
else
FINAL_RELEASE=yes
fi
echo "Ready to build release: Frama-C $VERSION - $CODENAME"
echo "MAJOR: $VERSION_MAJOR"
echo "MINOR: $VERSION_MINOR"
echo "FINAL: $FINAL_RELEASE"
##########################################################################
# Check input files
function prepare_file {
echo -n "Searching for '$1' ... "
if [ ! -f "$1" ]; then
echo_red "FAILED (aborting)"
exit 2
fi
echo_green "OK"
chmod 644 "$1"
}
show_step "Searching for a Frama-C source archive"
TARGZ_BASE="frama-c.tar.gz"
TARGZ_GENERIC="frama-c-source-dist.tar.gz"
TARGZ_VERSION="frama-c-$VERSION_SAFE-$CODENAME.tar.gz"
prepare_file $TARGZ_BASE
show_step "Searching for a Frama-C API archive"
API_FILES=(
frama-c
frama-c-server
)
for file in "${API_FILES[@]}"; do
prepare_file "$API_DIR/$file-api.tar.gz"
done
show_step "Searching for manuals"
MANUALS=(
"acsl"
"acsl-implementation"
"aorai-manual"
"e-acsl"
"e-acsl-implementation"
"e-acsl-manual"
"eva-manual"
"metrics-manual"
"plugin-development-guide"
"rte-manual"
"user-manual"
"wp-manual"
)
COMPANIONS=(
"aorai-example"
"hello"
)
for manual in "${MANUALS[@]}"; do
prepare_file "$MANUALS_DIR/$manual.pdf"
done
for companion in "${COMPANIONS[@]}"; do
prepare_file "$MANUALS_DIR/$companion.tar.gz"
done
prepare_file "$MANUALS_DIR/acsl-version.txt"
ACSL_VERSION=$(cat "$MANUALS_DIR/acsl-version.txt")
prepare_file "$MANUALS_DIR/e-acsl-version.txt"
EACSL_VERSION=$(cat "$MANUALS_DIR/e-acsl-version.txt")
show_step "Searching for changes"
CHANGES="releases/$VERSION_MAJOR.$VERSION_MINOR.md"
prepare_file "$CHANGES"
##########################################################################
# File copy
function generic_name {
if [ "$1" == "frama-c" ]; then echo "frama-c-source-dist"
elif [ "$1" == "acsl" ]; then echo "acsl"
elif [ "$1" == "e-acsl" ]; then echo "e-acsl"
elif [[ $1 =~ ^e-acsl.*$ ]]; then echo "$1"
else echo "frama-c-$1"
fi
}
function version_name {
if [ "$1" == "acsl" ]; then echo "acsl-$ACSL_VERSION"
elif [ "$1" == "e-acsl" ]; then echo "e-acsl-$EACSL_VERSION"
else echo "$1-$VERSION_AND_CODENAME"
fi
}
# For the 3 next functions
# $1 : name
# $2 : extension
function copy_manual_normal {
if [ "$FINAL_RELEASE" = "yes" ]; then
cp "$MANUALS_DIR/$1.$2" "$MANS_TARGET_DIR/$(generic_name "$1").$2"
fi
cp "$MANUALS_DIR/$1.$2" "$MANS_TARGET_DIR/$(version_name "$1").$2"
}
function copy_manual_e_acsl {
EACSL_TARGET_DIR="$MANS_TARGET_DIR/e-acsl"
if [ "$FINAL_RELEASE" = "yes" ]; then
cp "$MANUALS_DIR/$1.$2" "$EACSL_TARGET_DIR/$(generic_name "$1").$2"
fi
cp "$MANUALS_DIR/$1.$2" "$EACSL_TARGET_DIR/$(version_name "$1").$2"
}
function copy_api {
if [ "$FINAL_RELEASE" = "yes" ]; then
cp "$API_DIR/$1-api.$2" "$MANS_TARGET_DIR/$1-api.$2"
fi
cp "$API_DIR/$1-api.$2" "$MANS_TARGET_DIR/$1-$VERSION_AND_CODENAME-api.$2"
}
function copy_files {
for manual in "${MANUALS[@]}"; do
if [[ $manual =~ ^e-acsl.*$ ]]; then
copy_manual_e_acsl "$manual" "pdf"
else
copy_manual_normal "$manual" "pdf"
fi
done
for companion in "${COMPANIONS[@]}"; do
copy_manual_normal "$companion" "tar.gz"
done
for api in "${API_FILES[@]}"; do
copy_api "$api" "tar.gz"
done
# Eva has an old manual name that might be in use:
if [ "$FINAL_RELEASE" = "yes" ]; then
cp "$MANS_TARGET_DIR/frama-c-eva-manual.pdf" "$MANS_TARGET_DIR/frama-c-value-analysis.pdf"
fi
cp $TARGZ_BASE "$GZ_TARGET_DIR/$TARGZ_VERSION"
if [ "$FINAL_RELEASE" = "yes" ]; then
cp $TARGZ_BASE "$GZ_TARGET_DIR/$TARGZ_GENERIC"
fi
}
##########################################################################
# Make opam
show_step "Building opam repository file"
OPAM_DIR="opam-repository"
OPAM_FC_DIR="$OPAM_DIR/packages/frama-c/frama-c.$VERSION"
mkdir -p $OPAM_DIR
mkdir -p $OPAM_FC_DIR
OPAM_VERSION="opam-version: \"2.0\""
if [ "$FINAL_RELEASE" = "yes" ]; then
OPAM_VERSION_FIX="$OPAM_VERSION"
else
OPAM_VERSION_FIX="$OPAM_VERSION\navailable: opam-version >= \"2.1.0\"\nflags: avoid-version"
fi
cat opam \
| grep -v "^version\:" \
| grep -v "^name\:" \
| sed -e "s/$OPAM_VERSION/$OPAM_VERSION_FIX/" \
> $OPAM_FC_DIR/opam
cat >>$OPAM_FC_DIR/opam << EOL
url {
src: "$FRAMAC_COM_DOWNLOAD/$TARGZ_VERSION"
checksum: "sha256=$(sha256sum $TARGZ_BASE | cut -d" " -f1)"
}
EOL
echo "Opam file built"
##########################################################################
# Make wiki
show_step "Building wiki"
WIKI_DIR="wiki"
mkdir -p $WIKI_DIR
echo "Download directory built"
WIKI_PAGE="$WIKI_DIR/Frama-C-${VERSION_AND_CODENAME}.md"
echo "# Frama-C release $VERSION ($CODENAME)" > $WIKI_PAGE
echo "## Sources" >> $WIKI_PAGE
echo "- [$TARGZ_VERSION]($FRAMAC_COM_DOWNLOAD/$TARGZ_VERSION)" >> $WIKI_PAGE
echo "" >> $WIKI_PAGE
echo "## Manuals" >> $WIKI_PAGE
for manual in "${MANUALS[@]}"; do
if [[ $manual =~ ^e-acsl.*$ ]]; then
DIR="$FRAMAC_COM_DOWNLOAD/e-acsl"
else
DIR="$FRAMAC_COM_DOWNLOAD"
fi
NAME=$(version_name $manual)
echo "- [$manual]($DIR/$NAME.pdf)" >> $WIKI_PAGE
done
echo "" >> $WIKI_PAGE
echo "## Companion archives" >> $WIKI_PAGE
for archive in "${COMPANIONS[@]}"; do
NAME=$(version_name "$archive")
echo "- [$archive]($FRAMAC_COM_DOWNLOAD/$NAME.tar.gz)" >> $WIKI_PAGE
done
echo "" >> $WIKI_PAGE
echo "## Main changes" >> $WIKI_PAGE
sed 's/\(\#.*\)/##\1/' $CHANGES >> $WIKI_PAGE
echo "Wiki page built"
##########################################################################
# Make release
show_step "Building release json file"
JSON_DATA="release-data.json"
cat >$JSON_DATA <<EOL
{
"name": "Frama-C $VERSION $CODENAME",
"tag_name": "$VERSION_SAFE",
"ref": "stable/$LOWER_CODENAME",
"assets": {
"links": [
{
"name": "API Documentation",
"url": "https://frama-c.com/download/frama-c-$VERSION_AND_CODENAME-api.tar.gz",
"link_type":"other"
},
{
"name": "Server API Documentation",
"url": "https://frama-c.com/download/frama-c-server-$VERSION_AND_CODENAME-api.tar.gz",
"link_type":"other"
},
{
"name": "Official source archive",
"url": "https://frama-c.com/download/$TARGZ_VERSION",
"link_type":"other"
}
]
},
EOL
echo " \"description\": \"# Main changes since $PREVIOUS $PREVIOUS_NAME\n$(jq <"$CHANGES" --raw-input 'sub("^#";"##")' | jq --slurp 'join("\n")' | sed 's/^.//;s/.$//')\"" >> $JSON_DATA
echo "}" >> $JSON_DATA
echo "Release data file built"
##########################################################################
# Make website
show_step "Building website"
WEBSITE_DIR="./website"
WEBSITE_DL_DIR="$WEBSITE_DIR/download"
WEBSITE_INST_DIR="$WEBSITE_DIR/html/installations"
WEBSITE_EVENTS_DIR="$WEBSITE_DIR/_events"
WEBSITE_VERSIONS_DIR="$WEBSITE_DIR/_fc-versions"
mkdir -p $WEBSITE_DIR
# Downloads
mkdir -p $WEBSITE_DL_DIR
mkdir -p $WEBSITE_DL_DIR/e-acsl
GZ_TARGET_DIR=$WEBSITE_DL_DIR
MANS_TARGET_DIR=$WEBSITE_DL_DIR
copy_files
echo "Download directory built"
# Install
mkdir -p $WEBSITE_INST_DIR
INSTALL_WEBPAGE="$WEBSITE_INST_DIR/$LOWER_CODENAME.md"
EXT="$FRAMAC_VERSION_CODENAME (released on $(date +%Y-%m-%d))"
cat >$INSTALL_WEBPAGE <<EOL
---
layout: installation_page
version: $LOWER_CODENAME
title: Installation instructions for Frama-C $VERSION ($CODENAME)
---
EOL
sed ./INSTALL.md -e "s/^\(# Installing Frama-C\)$/\1 $EXT/" >>$INSTALL_WEBPAGE
echo "Installation file built"
# Event
mkdir -p $WEBSITE_EVENTS_DIR
TEXTUAL_VERSION="Frama-C $VERSION ($CODENAME)"
TEXTUAL_PREVIOUS="Frama-C $PREVIOUS ($PREVIOUS_NAME)"
if [ "$FINAL_RELEASE" = "no" ]; then
EVENT_TITLE="Beta release of $TEXTUAL_VERSION"
else
EVENT_TITLE="Release of $TEXTUAL_VERSION"
fi
VERSION_PAGE="/fc-versions/$LOWER_CODENAME.html"
EVENT_WEBPAGE="$WEBSITE_EVENTS_DIR/framac-$VERSION_SAFE.md"
cat >$EVENT_WEBPAGE <<EOL
---
layout: default
date: $(date +\"%d-%m-%Y\")
short_title: $TEXTUAL_VERSION
title: $EVENT_TITLE
link: /fc-versions/$LOWER_CODENAME.html
---
$TEXTUAL_VERSION is out. Download it [here]($VERSION_PAGE).
Main changes with respect to $TEXTUAL_PREVIOUS include:
EOL
sed 's/\(\#.*\)/###\1/' $CHANGES >>$EVENT_WEBPAGE
echo "Event file built"
# Version
mkdir -p $WEBSITE_VERSIONS_DIR
VERSION_WEBPAGE="$WEBSITE_DIR/_fc-versions/$LOWER_CODENAME.md"
if [ "$FINAL_RELEASE" = "no" ]; then
ACSL_OR_BETA="beta: true"
else
ACSL_VERSION_WEBSITE="$(echo $ACSL_VERSION | sed -n 's/1.\([0-9][0-9]\)/\1/p')"
ACSL_OR_BETA="acsl: $ACSL_VERSION_WEBSITE"
fi
cat >$VERSION_WEBPAGE <<EOL
---
layout: version
number: $VERSION_MAJOR
name: $CODENAME
$ACSL_OR_BETA
releases:
- number: $VERSION_MINOR
categories:
- name: Frama-C v$VERSION $CODENAME
files:
- name: Source distribution
link: /download/$TARGZ_VERSION
help: Compilation instructions
help_link: /html/installations/$LOWER_CODENAME.html
- name: User manual
link: /download/user-manual-$VERSION_AND_CODENAME.pdf
- name: Plug-in development guide
link: /download/plugin-development-guide-$VERSION_AND_CODENAME.pdf
help: Hello plug-in tutorial archive
help_link: /download/hello-$VERSION_AND_CODENAME.tar.gz
- name: API Documentation
link: /download/frama-c-$VERSION_AND_CODENAME-api.tar.gz
- name: Server API Documentation
link: /download/frama-c-server-$VERSION_AND_CODENAME-api.tar.gz
- name: ACSL $ACSL_VERSION ($CODENAME implementation)
link: /download/acsl-implementation-$VERSION_AND_CODENAME.pdf
- name: Plug-in Manuals
sort: true
files:
- name: Aoraï manual
link: /download/aorai-manual-$VERSION_AND_CODENAME.pdf
help: Aoraï example
help_link: /download/aorai-example-$VERSION_AND_CODENAME.tar.gz
- name: Metrics manual
link: /download/metrics-manual-$VERSION_AND_CODENAME.pdf
- name: Rte manual
link: /download/rte-manual-$VERSION_AND_CODENAME.pdf
- name: Eva manual
link: /download/eva-manual-$VERSION_AND_CODENAME.pdf
- name: WP manual
link: /download/wp-manual-$VERSION_AND_CODENAME.pdf
- name: E-ACSL manual
link: /download/e-acsl/e-acsl-manual-$VERSION_AND_CODENAME.pdf
---
EOL
echo "Version file built"