diff --git a/Documentation/conf.py b/Documentation/conf.py index d7dd257725..1e9f013a6f 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -19,7 +19,10 @@ import pathlib import subprocess +import urllib.parse +import docutils.nodes +import docutils.parsers.rst # -- Project information ----------------------------------------------------- @@ -225,6 +228,21 @@ def generate_doxygen(app): '.markdown': 'markdown', }) +class NewIssueDirective(docutils.parsers.rst.Directive): + has_content = True + optional_arguments = float('inf') + + def run(self): + qs = urllib.parse.urlencode([ + ('title', ' '.join(self.arguments)), + ('body', '\n'.join(self.content.data)), + ]) + refuri = f'https://github.com/gramineproject/gramine/issues/new?{qs}' + para = docutils.nodes.paragraph() + para += docutils.nodes.reference('', refuri, refuri=refuri) + return [para] + def setup(app): app.add_css_file('css/gramine.css') app.connect('builder-inited', generate_doxygen) + app.add_directive('new-issue', NewIssueDirective) diff --git a/Documentation/devel/DCO/index.rst b/Documentation/devel/DCO/index.rst index 023eff9474..0d5dad6500 100644 --- a/Documentation/devel/DCO/index.rst +++ b/Documentation/devel/DCO/index.rst @@ -1 +1,6 @@ .. include:: ../../../DCO + +.. note:: + + For cryptographical “code signing”, as opposed to “signing off” your + commits, please refer to :ref:`code-signing`. diff --git a/Documentation/devel/maintainer-manual.rst b/Documentation/devel/maintainer-manual.rst new file mode 100644 index 0000000000..6dfdb4e40e --- /dev/null +++ b/Documentation/devel/maintainer-manual.rst @@ -0,0 +1,195 @@ +Maintainer's manual +=================== + +Release process +--------------- + +Create new checklist issue (fill all ```` before submitting): + +.. new-issue:: Release checklist + + - [ ] create release PRs (@) + - gramine: # + - gramine-scaffolding: # + - contrib: # + - [ ] draft release notes (@) + - [ ] draft blogpost (@) + - [ ] draft #community announcement (@) + - [ ] update installation instructions (if a distro was released since last release) (@) + + iterate (update version, build and upload unstable packages) + + final stretch: + - [ ] get QA signoff (@) + - [ ] approve PRs (@) + - [ ] update version to final and push commits (@) + - [ ] build final packages (@) + - [ ] upload packages to release notes (@) + - [ ] push tag (@) + - [ ] switch release notes to pushed tag (@) + - [ ] merge PR (@) + - [ ] publish release notes (@) + - [ ] publish blogpost (@) + - [ ] publish on #community (@) + +Create a PR +^^^^^^^^^^^ + +.. code-block:: sh + + git checkout -b /release- + scripts/release.sh ~rc1 + git push -u origin /release- + firefox https://github.com/gramineproject/gramine/pull/new//release- + +Then set the PR on reviewable.io to be reviewed commit-by-commit. + +Update version in the PR +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: sh + + git reset --hard HEAD~ + scripts/release.sh X.Y~rcN + git push --force + +Create a tag +^^^^^^^^^^^^ + +.. code-block:: sh + + git tag -m "Gramine " v HEAD~ + git push v + +.. _code-signing: + +Code signing +------------ + +.. note:: + + “Code signing” is not to be confused with “signing off” your commits. + + “Signing off” is (in our project) a |~| legal device for a |~| sort of + signature by which you assert that you are holding copyrights to the code + you're submitting (or your're authorized by copyright holder to submit the + code). “Signing off” is done by writing ``Signed-off-by:`` line to the + commit message (maybe using :command:`git commit -s`) and does not carry + a |~| separate cryptographic signature. For details, please read + :doc:`DCO/index`, and keep in mind that in other projects meaning of the + ``Signed-off-by:`` line might be different. + + “Code signing” refers to the process of cryptographically signing your + contributions (commits and tags), so other people are able to mathematically + prove that the contribution came from the holder of a |~| particular + cryptographic key. It has no legal meaning. It can be done using + :command:`git commit -S` or by configuring :program:`git` (see below). + +Generating key +^^^^^^^^^^^^^^ + +First, you need to generate your own key pair using :program:`gpg`. The key +needs to be "sign only"! Otherwise, if you also add encrypt capability, people +will add your key to their :abbr:`MUA (Mail User Agent)`\ s and will encrypt +e-mail messages to you using code signing key. This is not desired, the key +generated for the purpose of code signing should not be used in any other +context (e.g. e-mail or signing code in other projects). + +In user ID, please write your name and comment saying that the key is meant for +code signing in this project. + +The key needs to be RSA (at least 3072 to match overall security level in SGX) +or Curve25519. 25519 keys are preferred, because they are smaller and faster to +use. In some versions of :program:`gpg` you need to use ``--full-gen-key +--expert`` to be able to choose ECC keys. + +.. code-block:: none + + % gpg --full-gen-key --expert + gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) + (7) DSA (set your own capabilities) + (8) RSA (set your own capabilities) + (9) ECC and ECC + (10) ECC (sign only) + (11) ECC (set your own capabilities) + (13) Existing key + (14) Existing key from card + Your selection? 10 + Please select which elliptic curve you want: + (1) Curve 25519 + (3) NIST P-256 + (4) NIST P-384 + (5) NIST P-521 + (6) Brainpool P-256 + (7) Brainpool P-384 + (8) Brainpool P-512 + (9) secp256k1 + Your selection? 1 + Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years + Key is valid for? (0) + Key does not expire at all + Is this correct? (y/N) y + + GnuPG needs to construct a user ID to identify your key. + + Real name: Wojciech Porczyk + Email address: woju@invisiblethingslab.com + Comment: Gramine code signing key + You selected this USER-ID: + "Wojciech Porczyk (Gramine code signing key) " + + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o + We need to generate a lot of random bytes. It is a good idea to perform + some other action (type on the keyboard, move the mouse, utilize the + disks) during the prime generation; this gives the random number + generator a better chance to gain enough entropy. + gpg: /home/user/.gnupg/trustdb.gpg: trustdb created + gpg: key 044D9664E7A77E16 marked as ultimately trusted + gpg: directory '/home/user/.gnupg/openpgp-revocs.d' created + gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/9C4D27D9157EF771A4283926044D9664E7A77E16.rev' + public and secret key created and signed. + + pub ed25519 2024-02-22 [SC] + 9C4D27D9157EF771A4283926044D9664E7A77E16 + uid Wojciech Porczyk (Gramine code signing key) + +.. yes, this is actual log from generating my own key! + +Submitting key to GitHub +^^^^^^^^^^^^^^^^^^^^^^^^ + +https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account#adding-a-gpg-key + +Setting up git +^^^^^^^^^^^^^^ + +*(Substitute key ID for your own key. The following example matches key ID from +the example generation listing.)* + +.. code-block:: sh + + git config --global commit.gpgsign true + git config --global user.signingkey 9C4D27D9157EF771A4283926044D9664E7A77E16 + +If you are using Split GPG feature of Qubes OS +(https://www.qubes-os.org/doc/split-gpg/#using-git-with-split-gpg): + +.. code-block:: sh + + git config --global gpg.program qubes-gpg-client-wrapper + +and remember to set ``QUBES_GPG_DOMAIN`` environment variable in your shell +config file. diff --git a/Documentation/index.rst b/Documentation/index.rst index 7c977d8e8d..453c73ae85 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -217,6 +217,7 @@ Indices and tables devel/setup devel/coding-style devel/howto-doc + devel/maintainer-manual devel/charter devel/DCO/index diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000000..9f34aa8be6 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2024 Wojtek Porczyk + +set -e + +: ${D:="bookworm bullseye jammy focal"} + +bump() { + v="$1" + test -n "$v" + + find . -name meson.build \( -path \*/subprojects/\* -o -print \) \ + | while read meson_build + do + printf 'patching %s\n' "$meson_build" >&2 + sed -i -e "s/^\(\s*version: '\).*\(',\)$/\1$v\2/" "$meson_build" + git add "$meson_build" + done + + echo patching debian/changelog >&2 + d="$D" + case "$v" in + *~UNRELEASED) + d=UNRELEASED ;; + *~*) + d=$(printf %s "$d" | sed 's/\&2 + sed -i -e "s/^\(Version: \).*$/\1$v/" gramine.spec + git add gramine.spec + fi + + if test -w packaging/alpine/APKBUILD + then + echo patching packaging/alpine/APKBUILD >&2 + sed -i -e "s/^\(_real_pkgver=\).*$/\1$v/" packaging/alpine/APKBUILD + git add packaging/alpine/APKBUILD + fi + + # python version spec forbids ~, it needs after last number "rcN" (without + # a dot) or ".postN" (with a dot): + # https://packaging.python.org/en/latest/specifications/version-specifiers/ + v_py=$(printf %s "$v" | sed -e 's/post~UNRELEASED/.post0/g' -e 's/~//g') + + if test -w pyproject.toml + then + echo patching pyproject.toml >&2 + sed -i -e "s/^\(version\s*=\).*$/version = \"$v_py\"/" pyproject.toml + git add pyproject.toml + fi + + if test -w graminescaffolding/__init__.py + then + echo patching graminescaffolding/__init__.py >&2 + sed -i -e "s/^\(__version__\s*=\).*$/__version__ = \"$v_py\"/" \ + graminescaffolding/__init__.py + git add graminescaffolding/__init__.py + fi +} + +commit() { + v="$1" + test -n "$v" + shift + + git commit --signoff --message "Bump version to $v" "$@" +} + + +if test -z "$1" +then + echo usage: "$0" VERSION >&2 + exit 2 +fi +V="$1" +VP="${1%~*}"post~UNRELEASED + +cd "$(git rev-parse --show-toplevel)" + +bump "$V" + +# to fix a mistake: +# git reset --hard HEAD~ +# release.sh X.Y +case "$(git log -n1 --format=%s)" in +"Bump "*) commit "$V" --amend ;; +*) commit "$V" ;; +esac + +bump "$VP" +commit "$VP"