These are informal notes on how to do an OCaml release.

Following these steps requires commit right in the OCaml repository,
as well as SSH access to the inria.fr file servers hosting the
distribution archives and manual.

We are not fully confident that those steps are correct, feel free to
check with other release managers in case of doubt.

Note: we say that a new release is a "testing release" if it is a Beta
version or Release Candidate. Otherwise, we call it a "production
release".


## A few days in advance

Send a mail on caml-devel to warn Gabriel (to make a pass on Changes)
and the OCamlLabs folks (for OPAM testing).

## 0: release environment setup

```
rm -f /tmp/env-$USER.sh
cat >/tmp/env-$USER.sh <<EOF

export MAJOR=4
export MINOR=08
export BUGFIX=0
export PLUSEXT=

export WORKTREE=~/o/\$MAJOR.\$MINOR
  # must be the git worktree for the branch you are releasing

export BRANCH=\$MAJOR.\$MINOR
export VERSION=\$MAJOR.\$MINOR.\$BUGFIX\$PLUSEXT

export REPO=http://github.com/ocaml/ocaml

# these values are specific to caml.inria's host setup
# they are defined in the release manager's .bashrc file
export ARCHIVE_HOST="$OCAML_RELEASE_ARCHIVE_HOST"
export ARCHIVE_PATH="$OCAML_RELEASE_ARCHIVE_PATH"
export WEB_HOST="$OCAML_RELEASE_WEB_HOST"
export WEB_PATH="$OCAML_RELEASE_WEB_PATH"

export DIST="\$ARCHIVE_PATH/ocaml/ocaml-\$MAJOR.\$MINOR"
EOF
source /tmp/env-$USER.sh
echo $VERSION
```


## 1: check repository state

```
cd $WORKTREE
git status  # check that the local repo is in a clean state
git pull
```

## 2: magic numbers

If you are about to do a major release, you should check that the
magic numbers have been updated since the last major release. It is
preferable to do this just before the first testing release for this
major version, typically the first beta.

See the HACKING file of `utils/` for documentation on how to bump the
magic numbers.

## 3: build, refresh dependencies, sanity checks

```
make distclean
git clean -n -d -f -x  # Check that "make distclean" removed everything

INSTDIR=/tmp/ocaml-${VERSION}
rm -rf ${INSTDIR}
./configure -prefix ${INSTDIR}

make -j5
make alldepend

# check that .depend files have no absolute path in them
find . -name .depend | xargs grep ' /'
  # must have empty output

make install
./tools/check-symbol-names runtime/*.a
  # must have empty output and return 0
```


## 4: tests

```
make tests
```


## 5: build, tag and push the new release

```
# at this point, the VERSION file contains N+devD
# increment it into N+dev(D+1); for example,
#   4.07.0+dev8-2018-06-19 => 4.07.0+dev9-2018-06-26
# for production releases: check and change the Changes header
#  (remove "next version" and add a date)
./autogen
git commit -a -m "last commit before tagging $VERSION"

# update VERSION with the new release; for example,
#   4.07.0+dev9-2018-06-26 => 4.07.0+rc2
# Update ocaml-variants.opam with new version.
# Update \year in manual/manual/macros.hva
rm -r autom4te.cache
./autogen
make coreboot -j5
make coreboot -j5 # must say "Fixpoint reached, bootstrap succeeded."
git commit -m "release $VERSION" -a
git tag -m "release $VERSION" $VERSION

# for production releases, change the VERSION file into (N+1)+dev0; for example,
#   4.08.0 => 4.08.1+dev0
# for testing candidates, use N+dev(D+2) instead; for example,
#   4.07.0+rc2 => 4.07.0+dev10-2018-06-26
# Revert ocaml-variants.opam to its "trunk" version.
rm -r autom4te.cache
./autogen
git commit -m "increment version number after tagging $VERSION" VERSION configure ocaml-variants.opam
git push
git push --tags
```

## 5.1: create the release on github (only for a production release)

open https://github.com/ocaml/ocaml/releases
# and click "Draft a new release"
# for a minor release, the description is:
 Bug fixes. See [detailed list of changes](https://github.com/ocaml/ocaml/blob/$MAJOR.$MINOR/Changes).


## 6: create OPAM packages

Create ocaml-variants packages for the new version, copying the particular
switch configuration choices from the previous version.

Do not forget to add/update the checksum field for the tarballs in the
"url" section of the opam files. Use opam-lint before sending the pull
request.

## 7: build the release archives

```
cd $WORKTREE
TMPDIR=/tmp/ocaml-release
git checkout $VERSION
git checkout-index -a -f --prefix=$TMPDIR/ocaml-$VERSION/
cd $TMPDIR
gtar -c --owner 0 --group 0 -f ocaml-$VERSION.tar ocaml-$VERSION
gzip -9 <ocaml-$VERSION.tar >ocaml-$VERSION.tar.gz
xz <ocaml-$VERSION.tar >ocaml-$VERSION.tar.xz
```


## 8: upload the archives and compute checksums

For the first beta of a major version, create the distribution directory on
the server:
```
ssh $ARCHIVE_HOST "mkdir -p $DIST"
```

Upload the archives:
```
scp ocaml-$VERSION.tar.{xz,gz} $ARCHIVE_HOST:$DIST
```

To update the checksum files on the remote host, we first upload the
release environment.
(note: this assumes the user name is the same on the two machines)

```
scp /tmp/env-$USER.sh $ARCHIVE_HOST:/tmp/env-$USER.sh
```

and then login there to update the checksums (MD5SUM, SHA512SUM)

```
ssh $ARCHIVE_HOST
source /tmp/env-$USER.sh
cd $DIST

cp MD5SUM MD5SUM.old
md5sum ocaml-$VERSION.tar.{xz,gz} > new-md5s
# check new-md5s to ensure that they look right, and then
cat new-md5s >> MD5SUM
# if everything worked well,
rm MD5SUM.old new-md5s

# same thing for SHA512
cp SHA512SUM SHA512SUM.old
sha512sum ocaml-$VERSION.tar.{xz,gz} > new-sha512s
cat new-sha512s >> SHA512SUM
rm SHA512SUM.old new-sha512s

# clean up
rm /tmp/env-$USER.sh
exit
```


## 9: update note files (technical documentation)

```
ssh $ARCHIVE_HOST "mkdir -p $DIST/notes"
cd ocaml-$VERSION
scp INSTALL.adoc LICENSE README.adoc README.win32.adoc Changes \
   $ARCHIVE_HOST:$DIST/notes/
```


## 10: upload the reference manual

You don't need to do this if the previous release had the same
$MAJOR.$MINOR ($BRANCH) value and the exact same manual -- this is frequent if
it was a release candidate.

```
cd $WORKTREE
make
make install
export PATH="$INSTDIR/bin:$PATH"
cd manual
make clean
make
rm -rf /tmp/release
mkdir -p /tmp/release
RELEASENAME="ocaml-$BRANCH-"
make -C manual release RELEASE=/tmp/release/$RELEASENAME
scp /tmp/release/* $ARCHIVE_HOST:$DIST/


# upload manual checksums
ssh $ARCHIVE_HOST "cd $DIST; md5sum ocaml-$BRANCH-refman* >>MD5SUM"
ssh $ARCHIVE_HOST "cd $DIST; sha512sum ocaml-$BRANCH-refman* >>SHA512SUM"
```

Releasing the manual online happens on another machine:
Do this ONLY FOR A PRODUCTION RELEASE

```
scp /tmp/env-$USER.sh $ARCHIVE_HOST:/tmp/env-$USER.sh
ssh $ARCHIVE_HOST
source /tmp/env-$USER.sh
scp /tmp/env-$USER.sh $WEB_HOST:/tmp
ssh $WEB_HOST
source /tmp/env-$USER.sh

cd $WEB_PATH/caml/pub/docs
mkdir -p manual-ocaml-$BRANCH
cd manual-ocaml-$BRANCH
rm -fR htmlman ocaml-$BRANCH-refman-html.tar.gz
wget http://caml.inria.fr/pub/distrib/ocaml-$BRANCH/ocaml-$BRANCH-refman-html.tar.gz
tar -xzvf ocaml-$BRANCH-refman-html.tar.gz # this extracts into htmlman/
/bin/cp -r htmlman/* . # move HTML content to docs/manual-caml-$BRANCH
rm -fR htmlman ocaml-$BRANCH-refman-html.tar.gz

cd $WEB_PATH/caml/pub/docs
rm manual-ocaml
ln -sf manual-ocaml-$BRANCH manual-ocaml
```


## 11: prepare web announce for the release

For production releases, you should get in touch with ocaml.org to
organize the webpage for the new release. See

  <https://github.com/ocaml/ocaml.org/issues/819>


## 13: announce the release on caml-list and caml-announce

See the email announce templates at the end of this file.



# Announces

## Announcing a production release:

```
Dear OCaml users,

We have the pleasure of celebrating <event> by announcing the release of
OCaml version $VERSION.
This is mainly a bug-fix release, see the list of changes below.

It is (or soon will be) available as a set of OPAM switches,
and as a source download here:
  https://caml.inria.fr/pub/distrib/ocaml-$BRANCH/

Happy hacking,

-- Damien Doligez for the OCaml team.

<< insert the relevant Changes section >>
```

## Announcing a release candidate:

```
Dear OCaml users,

The release of OCaml version $MAJOR.$MINOR.$BUGFIX is imminent.  We have
created a release candidate that you can test.

The source code is available at these addresses:

 https://github.com/ocaml/ocaml/archive/$VERSION.tar.gz
 https://caml.inria.fr/pub/distrib/ocaml-$BRANCH/ocaml-$VERSION.tar.gz

The compiler can also be installed as an OPAM switch with one of the
following commands.

opam switch create ocaml-variants.$VERSION --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git

or

opam switch create ocaml-variants.$VERSION+<VARIANT> --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git

 where you replace <VARIANT> with one of these:
   afl
   default-unsafe-string
   force-safe-string
   flambda
   fp
   fp+flambda

We want to know about all bugs. Please report them here:
 https://github.com/ocaml/ocaml/issues

Happy hacking,

-- Damien Doligez for the OCaml team.

<< insert the relevant Changes section >>
```

## Announcing a beta version:

```
Dear OCaml users,

The release of OCaml $MAJOR.$MINOR.$BUGFIX is approaching. We have created
a beta version to help you adapt your software to the new features
ahead of the release.

The source code is available at these addresses:

 https://github.com/ocaml/ocaml/archive/$VERSION.tar.gz
 https://caml.inria.fr/pub/distrib/ocaml-$BRANCH/$VERSION.tar.gz

The compiler can also be installed as an OPAM switch with one of the
following commands.

opam switch create ocaml-variants.$VERSION --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git

or

opam switch create ocaml-variants.$VERSION+<VARIANT> --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git

 where you replace <VARIANT> with one of these:
   afl
   default-unsafe-string
   force-safe-string
   flambda
   fp
   fp+flambda

We want to know about all bugs. Please report them here:
 https://github.com/ocaml/ocaml/issues

Happy hacking,

-- Damien Doligez for the OCaml team.
```
