diff --git a/home/modules/contribute/assets/images/release-note-generator/cb-release-notes-menu-options.png b/home/modules/contribute/assets/images/release-note-generator/cb-release-notes-menu-options.png new file mode 100644 index 0000000000..39b860bb7b Binary files /dev/null and b/home/modules/contribute/assets/images/release-note-generator/cb-release-notes-menu-options.png differ diff --git a/home/modules/contribute/assets/images/release-note-generator/docs-server-test-example.png b/home/modules/contribute/assets/images/release-note-generator/docs-server-test-example.png new file mode 100644 index 0000000000..10c08a499d Binary files /dev/null and b/home/modules/contribute/assets/images/release-note-generator/docs-server-test-example.png differ diff --git a/home/modules/contribute/assets/images/release-note-generator/retrieve-parameters.png b/home/modules/contribute/assets/images/release-note-generator/retrieve-parameters.png new file mode 100644 index 0000000000..50d1ecb8de Binary files /dev/null and b/home/modules/contribute/assets/images/release-note-generator/retrieve-parameters.png differ diff --git a/home/modules/contribute/nav.adoc b/home/modules/contribute/nav.adoc index 8db7232c58..62e742c97c 100644 --- a/home/modules/contribute/nav.adoc +++ b/home/modules/contribute/nav.adoc @@ -37,5 +37,11 @@ ** xref:generate-rest-api.adoc[] ** xref:extensions.adoc[] +* Release Note Generator + ** xref:release-note-generator/design-guide.adoc[Release Note Generator Design Guide] + ** xref:release-note-generator/adding-a-new-product.adoc[Adding a New Product] + ** xref:release-note-generator/generate_ai_summaries.adoc[Generate AI Summaries] + //* Additional Resources (Pending) + diff --git a/home/modules/contribute/pages/release-note-generator/adding-a-new-product.adoc b/home/modules/contribute/pages/release-note-generator/adding-a-new-product.adoc new file mode 100644 index 0000000000..df39312c75 --- /dev/null +++ b/home/modules/contribute/pages/release-note-generator/adding-a-new-product.adoc @@ -0,0 +1,289 @@ += Adding a New Product +:description: Demonstrates how to add a new product to the Release Note Generator. +:page-pagination: full +:page-topic-type: howto + +[abstract] +{description} + +== Prerequisites +This guide is intended for technical writers and developers who are familiar with the Release Note Generator. If you are new to the tool, please refer to the link:https://confluence.issues.couchbase.com/wiki/spaces/DOCS/pages/3338961232/Other+Tools[installation and use of the Release Note Generator] guide for more information. +Before you begin, make sure that you have the release note generator installed and running. + +You should also familiarize yourself with the xref:./design-guide.adoc[]. + +You will also need a code editor or an IDE for editing the YAML configuration file. + +You should also have a terminal application running. + +== Overview + +The Release Note Generator has been designed so that it can be extended to support new Couchbase products without having to +alter the Python script itself. Adding a new product involves two steps: + +. Add the new product release set to `cb_release_notes_config.yaml`. +. Create a new Jinja template for rendering the AsciiDoc file for your new release note. + + +== Adding a new product + +To demonstrate this process, we're going to create a test release note configuration for Couchbase Server. +(There are already two existing configurations for this product, so this one can be safely deleted later). + +NOTE: You should run the following commands from the directory where your Release Notes Generator is installed. + +=== Step {counter: step}: Make a copy of your `cb_release_notes_config.yaml` file. + +You can make a copy of the file using the following terminal command: + +[source, shell] +---- +cp cb_release_notes_config.yaml cb_release_notes_config.yaml.spare +---- + +=== Step {counter: step}: Name your release product + +Edit the original `cb_release_notes_config.yaml` file +and add the new `name` item underneath the `release_settings` section: + +[source, yaml] +---- +release_settings: + - name: "Docs Server (test)" +---- + +=== Step {counter: step}: Define your parameters + +The user will need to supply parameters that need to be fed to the script. +These can vary depending on what's going to appear on the release note, +and what the JQL will need to gather the tickets. +The most common parameters are: + +[horizontal] + +Release date:: +This will appear in the release note heading. + + +Release number:: +The label that our JQL will use to find the release tag. + +File path:: +This is a mandatory item needed for each release set. +It supplies the name of the AsciiDoc file that the script generates. + +Other parameters that the SQL will need, (such as the project name), are fixed values +and don't need to be parameterized. + +[source, yaml] +.Add the input parameters +---- +release_settings: + - name: "Docs Server (test)" + fields: + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: release_number + type: text + message: 'Enter the release label:' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' +---- + +=== Step {counter: step}: Define your JQL statement + +Now, you add the URL and the JQL statements used to retrieve the Jira tickets that match your parameters: + +[source, yaml] +.Adding the JQL statement +---- + - name: "Docs Server (test)" + fields: + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: release_number + type: text + message: 'Enter the release label:' + - name: release_text + type: text + message: 'Enter the release number for the title line:' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' + url: https://jira.issues.couchbase.com + jql: project = "Couchbase Server" # <.> + AND type IN (Epic, Bug, Improvement, Task, "Technical Task") + AND fixVersion in ({{release_number}}) # <.> + AND labels IN (releasenote,releasenotecomplete) + ORDER BY key ASC # <.> +---- +<.> Note that the JQL statement restricts the query to tickets belonging to the Couchbase Server project, +and also ensures that the ticket is either a Bug or a New Feature. +<.> We supply the `release_number` parameter to the JQL statement so that we only pick up tickets from the specified release. +<.> The `ORDER BY key` clause ensures that the tickets are returned in ascending order based on their Jira key. +This is important to ensure that the tickets are passed to the template in the correct order. + +[#define-release-note-field] +=== Step {counter: step}: Define the release note field. + +The script needs to know which field in a Jira ticket holds the release note description. +The script uses this to ensure that the ticket's release note description field has been filled in. +If the field hasn't been filled in, +the script can optionally use AI to generate a release note summary from the +ticket and comments. +For most of the Couchbase projects, this was added some time after the Jira system was set up, +so the new field was added as a custom field called `customfield_11402`. + +[source,yaml, subs="+quotes"] +.Define the `release_notes_field` +---- + - name: "Docs Server (test)" + fields: + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: release_number + type: text + message: 'Enter the release label:' + - name: release_text + type: text + message: 'Enter the release number for the title line:' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' + url: https://jira.issues.couchbase.com + jql: project = "Couchbase Server" + AND type IN (Epic, Bug, Improvement, Task, "Technical Task") + AND fixVersion in ({{release_number}}) + AND labels IN (releasenote,releasenotecomplete) + ORDER BY key ASC + #release_note_field: 'customfield_11402'# +---- + +Any item from the `fields` list can be designated as a `release_note_field` (e.g. the ticket's `summary` field). +Alternatively, if the project doesn't have a release note field, then set `release_note_field` to `None`. + +.Retrieving JIRA field names +**** +The field names for Jira often differ from the names displayed on the ticket's page. + +The easiest way to get the field names is to +use the `CURL` and `jq` commands to retrieve an existing ticket with a public security level: + +[source,shell, subs="+quotes"] +---- +curl -X GET --location "https://jira.issues.couchbase.com/rest/api/2/issue/CBG-4977" \ + -H "Authorization: Basic ##" \ + -H "Content-Type: application/json" | jq +---- + +This will render the complete ticket (including field names) to the standard output. +**** + + + +[#define-your-jinja-template] +=== Step {counter: step}: Define your JINJA template + +Before creating the rendering template, you need to add it's location to your release set. +You can share templates between release sets. + +[source,yaml] +.Define the Jinja template +---- + - name: "Docs Server (test)" + fields: + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: release_number + type: text + message: 'Enter the release label:' + - name: release_text + type: text + message: 'Enter the release number for the title line:' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' + url: https://jira.issues.couchbase.com + jql: project = "Couchbase Server" + AND type IN (Epic, Bug, Improvement, Task, "Technical Task") + AND fixVersion in ({{release_number}}) + AND labels IN (releasenote,releasenotecomplete) + AND ("Release Notes[Labels]" NOT IN (suppress-{{release_number}}) OR "Release Notes[Labels]" IS EMPTY) + AND summary !~ "System Test" AND resolution not in (Declined, "Won't Fix") + AND reporter not in (membersOf(couchbase-qe-team)) + ORDER BY key ASC + release_note_field: 'customfield_11402' + template: docs-server-test.jinja2 +---- + +=== Step {counter: step}: Create your JINJA template + +The templates reside in the `templates` directory, as defined near the top of the configuration file. +Use your editor to create a new template file in this directory. The file should be called `docs-server-test.jinja2`, +as defined in the release set configuration. (<>) + +Copy the template below into your file, then save the file. + +[source, text] +.Create the Jinja template +---- +{%- macro generate_issue_table(filtered_issues, title, suffix) %} <1> + +{% if filtered_issues | length > 0 -%} + + {{- "[#dlist-fixed-issues-" ~ user_settings.fields.release_number | replace_dots('') ~ "-" ~ suffix ~ "]\n"}} + {{- "=== " ~ title }} + + {% for issue in filtered_issues %} <2> + + {{- "*" ~ url_with_jira(user_settings.release_set.url, issue.key) ~ "*::"}} <3> + + {{- issue.raw['fields'][user_settings.release_set.release_note_field] }} <4> + + {% endfor %} + +{%- endif %} + +{%- endmacro %} + + +[#release-{{ user_settings.fields.release_number | replace_dots('') }}] +== Release {{ user_settings.fields.release_number }} ({{ user_settings.fields.release_date }}) + +Couchbase Server {{ user_settings.fields.release_number }} was released in {{ user_settings.fields.release_date }}. +This maintenance release contains fixes to issues. + +{{ "[#dlist-fixed-issues-" ~ user_settings.fields.release_number | replace_dots('') ~ "]"}} +== Fixed Issues + +{% include "docs-server-components.jinja2" %} + +---- + +We won't cover the breadth of what you can do with JINJA templates, +but we will highlight some of the features used in this example: + +<1> We can define reusable macros that can be called from anywhere within the template. +<2> We can define a `for … endfor` loop to iterate over the list of issues passed to the template. +<3> We can access all the fields of an issue using the dot notation. +<4> Use the parameter `user_settings.release_set.release_note_field` to access the release not description from the ticket. +to filter issues based on field values. + +=== Step {counter: step}: Run the Release Note Generator + +From the terminal screen, run the application using the following command: + +[source, shell] +---- +./cb-release-note +---- + +.Running the generator with the new release set +image::release-note-generator/docs-server-test-example.png[Running the Release Note Generator] + + diff --git a/home/modules/contribute/pages/release-note-generator/design-guide.adoc b/home/modules/contribute/pages/release-note-generator/design-guide.adoc new file mode 100644 index 0000000000..c14570f2b0 --- /dev/null +++ b/home/modules/contribute/pages/release-note-generator/design-guide.adoc @@ -0,0 +1,288 @@ += Couchbase Release Note Generator Design Guide +:description: This document describes the architecture and high-level design of the Couchbase Release Note Generator. +:page-topic-type: concept +:page-pagination: next + +:jql-fn: footnote:jql-footnote[JIRA Query Language] +[abstract] +{description} + +== Overview + +Producing release notes for the number of products that Couchbase offers is time-consuming. +For this reason, the Technical Communications team has created a Python script that can generate release notes from JIRA tickets. + +The problem is made slightly more complicated because each product has its own format its release note. +To get around this problem, the script uses a different template file for each product. + +NOTE: The plan is that all the products share the same format. + +== Design Goals + +When deciding on the design of the Couchbase Release Note Generator, the team considered the following goals: + +* Flexibility: The script should be able to handle new products and formats without requiring changes to the Python script. +* Extensibility: The script should be easy to extend and modify to accommodate new requirements or changes in the JIRA data. +* Maintainability: The codebase should be well-organized and easy to understand, making it easier to maintain and debug over time. +* Allow for the optional use of AI to generate the release notes. + +== Release Note Generator Process Architecture + +The script is designed to be flexible and extendable. +It uses a modular architecture that allows for the addition of new products and formats. + +[mermaid] +.Release Note Generator Process Flow +---- +flowchart LR + +jira@{shape: disk, label: "Couchbase\n JIRA\n database"} +script@{shape: process, label: "CB Release Notes Generator\n (Python script)"} +configuration@{shape: docs, label: "configuration files"} +templates@{shape: docs, label: "jinja\ntemplates"} +asciidoc@{shape: lined-document, label: "Generated\n AsciiDoc file"} +user@{ shape: manual-input, label: "Documentarian"} + +jira JtoS@====> script +templates TtoS@====> script +configuration CtoS@====> script +script StoA@====> asciidoc +user ====> script + +JtoS@{curve: linear} +TtoS@{curve: linear} +CtoS@{curve: linear} +StoA@{curve: linear} +---- + +. On invocation, the script loads the `release sets` from the configuration file, +and displays them on screen. +. The user selects one of the release sets (`Couchbase Server`, `Couchbase Mobile`, `Couchbase Operator` ...) +. The user enters a series of parameters as defined in the selected `release set`: (`release date`, `release label` ...) +.The script executes the JQL{empty}{jql-fn} statement defined in the `release set`, +supplying the parameters entered by the user. +. The script collects the JIRA tickets that match the query. +. The script loads the Jinja template defined in the release set and uses it to render the release note as an AsciiDoc file. + + +== Logic Flow + +=== Step {counter:flow}: Render the menu options + +When the script is invoked, the first thing it does is load the configuration file: `cb_release_notes_config.yaml`. +This file contains instructions on how to generate release notes for all supported products, as well as the location of the `.passwords.yaml`, +a hidden file that contains security tokens for accessing JIRA. + +CAUTION: The contents of `.passwords.yaml` should be kept securely on your local machine. +The file should not be shared or stored under version control. + +[source, yaml] +---- +# Configuration file for the release notes builder + +# $schema: ./cb_release_config_schema.yaml + +version: "2.2" + +password_file: ./.passwords.yaml +templates_directory: ./templates +jira_batch_size: 50 + +release_settings: + + - name: "Fixes and enhancements (Server 8.0+)" + + - name: "Couchbase Mobile" + + - name: "Couchbase Operator" + + +---- + +At this high level, the contents of the configuration file are pretty straightforward: + +[horizontal] +version:: +The current version number of the release note generator. + +password_file:: +The location and name of the password file. +It is recommended that this file is prefixed with the `.` character which will hide the file under the macOS file system. + +templates_directory:: +The location of the JinJa templates that the script will use to render the release notes in AsciiDoc. + +jira_batch_size:: +Instead of fetching the Jira tickets in one go, the script can retrieve them in batches of a given size. ++ +NOTE: In practice, a release note shouldn't contain more than 50 tickets, +so there is probably little point in changing the value. + +release_settings:: +Defines the instructions for retrieving the tickets from the Jira database. +Each setting defines the `name` (as shown) which the script uses to generate an on-screen menu +from which the user can select the product to generate the release note for. ++ +.Release Notes Generator menu options +image::release-note-generator/cb-release-notes-menu-options.png[Release Notes Generator menu options] + +In the following steps, we'll look at the release set options in more detail. + +=== Step {counter:flow}: Get the parameters + +In this example, assume that the user has selected the first menu option: `Fixes and enhancements (Server 8.0+)`. +The script will then load the release set configuration for the selected product: +[source, yaml] +---- +- name: "Fixes and enhancements (Server 8.0+)" + fields: + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: release_number + type: text + message: 'Enter the release label:' + - name: release_text + type: text + message: 'Enter the release number for the title line:' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' + +---- +[#fields] +The fields represent a list of parameters that the script will ask the user for +by displaying a prompt for the parameter on-screen: + +[horizontal] +name:: +The name of the parameter (the name elements can be separated using the underscore character: `_`) + +type:: +The parameter type can be one of the following: ++ +-- +[horizontal] +text::: +A basic character string. +This is the most commonly used field type. + +multiline::: +Another text field with the option of launching your system editor +for entering large amounts of text. +Handy to have, but rarely used. + +choice::: +Allows for a single selection from a sublist of items denoted by `choices`. + +select::: +Allows for a single selection from a sublist of items denoted by `choices`. + +file::: +This allows for the entry of a filename (with support for file path completion). ++ +NOTE: This is the only item considered to be mandatory, +as it is required to pick up the name of the AsciiDoc file to which the release note is eventually written. +-- ++ +message:: +The prompt that is displayed for the user to enter the required information. + +In our example, the prompts displayed will look something like this, +each item being filled in by the user before the script displays the next prompt. + +.Get parameters from the user +image::release-note-generator/retrieve-parameters.png[] + +TIP: The script will save the parameters as they're entered, +then present them again on its next invocation. + +=== Step {counter:flow}: Retrieve the Jira tickets +Having picked up the parameters, the script will then run a JQL query to retrieve the tickets for the release. + +[source,YAML] +---- + +url: https://jira.issues.couchbase.com +jql: project = "Couchbase Server" + AND type IN (Epic, Bug, Improvement, Task, "Technical Task") + AND fixVersion in ({{release_number}}) + AND labels IN (releasenote,releasenotecomplete) + AND ("Release Notes[Labels]" NOT IN (suppress-{{release_number}}) OR "Release Notes[Labels]" IS EMPTY) + AND summary !~ "System Test" AND resolution not in (Declined, "Won't Fix") + AND reporter not in (membersOf(couchbase-qe-team)) + ORDER BY key ASC +---- + +It only needs two configuration items for this: + +[horizontal] + +url:: +The URL of the Jira instance. For this to work, you must have a token defined in `.passwords.yaml`. ++ +[WARNING] +.public/private tickets +==== +The script uses the Jira API to retrieve the tickets, +and due to what I assume is a deliberate limitation, +the API will only retrieve items that have a security level set to `public` or `none`. +==== + +jql:: +A valid JQL{empty}footnote:jql-footnote[] statement that the script will use to retrieve the tickets. +Pay close attention to the field parameters delimited by `{{}}`; +these are the named parameters that will be replaced with the values +entered by the user from the xref:#fields[`fields`] section. + +=== Step {counter:flow}: Set the release note field + +The `release_note_field` tells the generator script where the Jira ticket it will find the release note information. + +[source, yaml] +---- +release_note_field: 'customfield_11402' +---- + +Here, we have informed the script that it will find the release note details in field `customfield_11402` in the Jira ticket. +The release note script makes use of `release_note_field` to determine whether the ticket has its release note filled in. +If not, then the script can fill in the missing release notes using AI. + +You can also reference the release note field in your Jinja template using `user_settings.release_set.release_note_field`. +(For more information on Jinja templates, see the xref:./adding-a-new-product.adoc#define-release-note-field[Defining the release note field].) + + + +=== Step {counter:flow}: Render the release note + +Having retrieved the tickets that match the JQL, +the script will pick up the template designated for the release set. + +[source, yaml] +---- +template: couchbase-server-bug-fixes.jinja2 +---- + +[NOTE] +.Remember the `templates` location! +==== +The location of the Jinja templates is defined in the `templates` section of the configuration file. +==== + +The script will take the collection of tickets and run them through the template, producing the final AsciiDoc file. + +NOTE: The Jinja template system is very similar to template engines such as JSP, ASP, and ThymeLeaf. +The scope of its function is beyond the scope of this design guide, +but you can find information and tutorials at https://jinja.palletsprojects.com + +== Further reading + +For more information on Jinja templates, refer to the official documentation at link:https://jinja.palletsprojects.com[]. + +We have also created a guide for developers on link:https://confluence.issues.couchbase.com/wiki/spaces/DOCS/pages/3230269470/A+Developer+s+Guide+to+Release+Notes[how to prepare Jira tickets for inclusion in release notes]. + +There is also a guide for technical writers covering the link:https://confluence.issues.couchbase.com/wiki/spaces/DOCS/pages/3338961232/Other+Tools[installation and use of the Release Note Generator]. + + + + diff --git a/home/modules/contribute/pages/release-note-generator/generate_ai_summaries.adoc b/home/modules/contribute/pages/release-note-generator/generate_ai_summaries.adoc new file mode 100644 index 0000000000..b330567211 --- /dev/null +++ b/home/modules/contribute/pages/release-note-generator/generate_ai_summaries.adoc @@ -0,0 +1,80 @@ += Generate AI Summaries +:page-topic-type: howto +:page-pagination: prev +:description: The release note generator can use ChatGPT to generate release note summaries + +[abstract] +{description} + +== Overview + +The release note generator has the facility to create summaries of the Jira tickets, +if the `release notes description` field hasn't been populated on any ticket flagged for inclusion in the release note. + +The summaries are generated using the ChatGPT using the ticket's summary and comments as the input to a supplied prompt. + +To make use of this facility, you must supply parameters in both the `.passwords.yaml` and `cb_release_notes_config.yaml`. + +=== AI setup in `.passwords.yaml` +The `.passwords.yaml` file is used to store sensitive information such as API keys and passwords. To use the AI feature, you must add the following parameters to the `.passwords.yaml` file: + +[source, yaml] +.Adding the AI token to `.passwords.yaml` +---- +jira: + https://jira.issues.couchbase.com: + username: doc.umentarian@couchbase.com + token: # Jira token goes here +ai: + chatgpt: + api_key: # ChatGPT API token goes here. +---- + +=== AI Setup in `.cb_release_notes_config.yaml` + +Each release set has its own AI setup. If we use the example from xref:./adding-a-new-product.adoc[]: +[source, yaml] +.Adding the AI Service to `.cb_release_notes_config.yaml` +---- + - name: "Sync Gateway" + fields: + - name: release_number + type: text + message: 'Enter the release number:' + - name: release_date + type: text + message: 'Enter the release date (Month Year):' + - name: file_path + type: file + message: 'Enter the file path for the release notes:' + url: https://jira.issues.couchbase.com + jql: project = CBG AND issuetype in (Bug, "New Feature", Improvement) + AND (fixVersion = {{release_number}} OR labels IN (known_issue)) + ORDER BY key ASC + template: sync-gateway.jinja2 + ai_service: + name: chatgpt + model: 'gpt-4o' + prompt: 'Summarise the following as a short release note + with no version numbers, no headings, no links, + no identifying names or email addresses, and no more than 8 sentences' + +---- + +We have added the `ai_service` section which contains three new elements: + +[horizontal] + +name:: +The name of the AI service. This must match the `ai` service defined in `.passwords.yaml`, +where it also must have a corresponding token. + +model:: +The model name of the AI service. +It's a good idea to check the names of the available models for the ChatGPT service. ++ +CAUTION: Model names are case-sensitive. + +prompt:: +The prompt used to generate the text. +The prompt can impact the quality of the summary, so it's worth experimenting with it. diff --git a/kroki/docker-compose.yml b/kroki/docker-compose.yml index 8616c873ed..e68a2a3d8c 100644 --- a/kroki/docker-compose.yml +++ b/kroki/docker-compose.yml @@ -1,7 +1,6 @@ -version: "3" services: kroki: - image: yuzutech/kroki + image: yuzutech/kroki:latest depends_on: - blockdiag - mermaid @@ -14,19 +13,24 @@ services: - KROKI_EXCALIDRAW_HOST=excalidraw ports: - "9500:8000" + restart: always blockdiag: - image: yuzutech/kroki-blockdiag + image: yuzutech/kroki-blockdiag:latest expose: - "8001" + restart: always mermaid: - image: yuzutech/kroki-mermaid + image: yuzutech/kroki-mermaid:latest expose: - "8002" + restart: always bpmn: - image: yuzutech/kroki-bpmn + image: yuzutech/kroki-bpmn:latest expose: - "8003" + restart: always excalidraw: - image: yuzutech/kroki-excalidraw + image: yuzutech/kroki-excalidraw:latest expose: - "8004" + restart: always