Blame README.md

Packit Service eebd6f
# Cockpit Composer
Packit Service eebd6f
Packit Service eebd6f
[![codecov](https://codecov.io/gh/osbuild/cockpit-composer/branch/master/graph/badge.svg)](https://codecov.io/gh/osbuild/cockpit-composer)
Packit Service eebd6f
Packit Service eebd6f
**The web interface for Composer!**
Packit Service eebd6f
Packit Service eebd6f
Composer generates custom images suitable for deploying systems or uploading to
Packit Service eebd6f
the cloud. It integrates into [Cockpit](https://cockpit-project.org/) as a
Packit Service eebd6f
frontend for [osbuild](https://github.com/osbuild).
Packit Service eebd6f
Packit Service 0c2606
## Making changes to Cockpit Composer
Packit Service eebd6f
Packit Service eebd6f
Here's where to get the code:
Packit Service eebd6f
Packit Service eebd6f
    $ git clone https://github.com/osbuild/cockpit-composer.git
Packit Service eebd6f
    $ cd cockpit-composer/
Packit Service eebd6f
Packit Service eebd6f
The remainder of the commands assume you're in the top level of the
Packit Service eebd6f
Cockpit Composer git repository checkout.
Packit Service eebd6f
Packit Service eebd6f
### Getting the development dependencies
Packit Service eebd6f
Packit Service eebd6f
On Fedora or Red Hat Enterprise Linux:
Packit Service eebd6f
Packit Service eebd6f
* First install Cockpit on your local machine as described in: https://cockpit-project.org/running.html.
Packit Service eebd6f
* Next install and start osbuild-composer:
Packit Service eebd6f
```
Packit Service eebd6f
    $ sudo yum install osbuild-composer
Packit Service eebd6f
    $ sudo systemctl start osbuild-composer
Packit Service eebd6f
```
Packit Service eebd6f
Packit Service eebd6f
* Cockpit Composer uses Node.js during development. Node.js is not used at runtime. To make changes on Cockpit you'll want to install Node.js, NPM.
Packit Service eebd6f
```
Packit Service eebd6f
    $ sudo yum install nodejs npm
Packit Service eebd6f
```
Packit Service eebd6f
Packit Service eebd6f
In addition, for testing, the following dependencies are required:
Packit Service eebd6f
Packit Service eebd6f
    $ sudo dnf install curl expect xz rpm-build chromium-headless \
Packit Service eebd6f
        libvirt-daemon-kvm libvirt-client python3-libvirt
Packit Service eebd6f
Packit Service eebd6f
### Building
Packit Service eebd6f
Packit Service eebd6f
Run
Packit Service eebd6f
Packit Service eebd6f
    $ make
Packit Service eebd6f
Packit Service eebd6f
to build everything. You can only run `make` from the top-level and it will always rebuild the Cockpit Composer.
Packit Service eebd6f
Packit Service eebd6f
Cockpit Composer is built using [React](https://reactjs.org/). For inspecting the React component hierarchy, including component props and state, you can run
Packit Service eebd6f
Packit Service eebd6f
    $ npm run build:debug
Packit Service eebd6f
Packit Service eebd6f
### Running integration test
Packit Service eebd6f
Packit Service eebd6f
Run test without visually seeing what the browser is doing:
Packit Service eebd6f
Packit Service eebd6f
    $ make check
Packit Service eebd6f
Packit Service eebd6f
In the case you wish to visually see what the browser is doing you will want to run:
Packit Service eebd6f
Packit Service eebd6f
    $ TEST_SHOW_BROWSER=true make check
Packit Service eebd6f
Packit Service eebd6f
or
Packit Service eebd6f
Packit Service eebd6f
    $ make debug-check
Packit Service eebd6f
Packit Service eebd6f
By default the cockpit-composer will be installed into `$TEST_OS`in [Makefile](Makefile) and test will be run on Chromium. To run it on Firefox, a environment variable ```TEST_BROWSER=firefox``` needs to be added, like:
Packit Service eebd6f
Packit Service eebd6f
    $ TEST_BROWSER=firefox make check
Packit Service eebd6f
Packit Service eebd6f
To test cockpit-composer in different OS, set the `$TEST_OS` environment variable, for example:
Packit Service eebd6f
Packit Service eebd6f
    $ TEST_OS=fedora-32 make check
Packit Service eebd6f
Packit Service eebd6f
### Running eslint
Packit Service eebd6f
Packit Service eebd6f
Cockpit Composer uses [ESLint](https://eslint.org/) to automatically check
Packit Service eebd6f
JavaScript code style in `.js` files.
Packit Service eebd6f
Packit Service eebd6f
The linter is executed within every build as a webpack preloader.
Packit Service eebd6f
Packit Service eebd6f
For developer convenience, the ESLint can be started explicitly by:
Packit Service eebd6f
Packit Service eebd6f
    $ npm run eslint
Packit Service eebd6f
Packit Service eebd6f
Rules configuration can be found in the `package.json` file.
Packit Service eebd6f
Packit Service eebd6f
### Working on your local machine
Packit Service eebd6f
Packit Service eebd6f
It's easy to set up your local Linux machine for rapid development of Cockpit Composer's JavaScript code. After building, run this command from your top level Cockpit Composer checkout directory, and make sure to run it as the same user that you'll use to log into Cockpit Composer below.
Packit Service eebd6f
Packit Service eebd6f
    $ mkdir -p ~/.local/share/cockpit
Packit Service eebd6f
    $ ln -s $(pwd)/public/dist ~/.local/share/cockpit/composer
Packit Service eebd6f
Packit Service eebd6f
This will cause cockpit to read JavaScript and HTML files directly from the built package output directory instead of using the installed Cockpit UI files.
Packit Service eebd6f
Packit Service eebd6f
Now you can log into Cockpit Composer on your local Linux machine at the following address. Use the same user and password that you used to log into your Linux desktop.
Packit Service eebd6f
Packit Service eebd6f
https://localhost:9090/composer
Packit Service eebd6f
Packit Service eebd6f
After every change to your sources, run `make` to update all the webpacks, and reload cockpit in your browser.
Packit Service eebd6f
Packit Service eebd6f
### Directory Layout
Packit Service eebd6f
Packit Service eebd6f
```shell
Packit Service eebd6f
.
Packit Service eebd6f
├── /components/                # Shared or generic UI components
Packit Service eebd6f
│   ├── /Layout/                # Website layout component
Packit Service eebd6f
│   ├── /Link/                  # Link component to be used insted of 
Packit Service eebd6f
│   └── /...                    # etc.
Packit Service eebd6f
├── /core/                      # Core framework
Packit Service eebd6f
│   ├── /actions/               # Redux actions
Packit Service eebd6f
│   ├── /reducers/              # Redux reducers
Packit Service eebd6f
│   ├── /sagas/                 # Redux saga files
Packit Service eebd6f
│   ├── /apiCalls.js            # All API calls to lorax-composer
Packit Service eebd6f
│   ├── /constants.js           # lorax-composer API path
Packit Service eebd6f
│   ├── /history.js             # Handles client-side navigation
Packit Service eebd6f
│   ├── /router.js              # Handles routing and data fetching
Packit Service eebd6f
│   ├── /selectors.js           # Simple “selector” for Redux
Packit Service eebd6f
│   ├── /store.js               # Application state manager (Redux)
Packit Service eebd6f
│   └── /utils.js               # Utility for group API URL
Packit Service eebd6f
├── /data/                      # Provide API for internal use
Packit Service eebd6f
│   ├── /BlueprintApi.js        # Blueprint API
Packit Service eebd6f
│   ├── /MetadataApi.js         # Metadata API
Packit Service eebd6f
│   └── /NotificationsApi.js    # Notification API
Packit Service eebd6f
├── /node_modules/              # 3rd-party libraries and utilities
Packit Service eebd6f
├── /pages/                     # React components for web pages
Packit Service eebd6f
│   ├── /blueprint/             # Blueprint page
Packit Service eebd6f
│   ├── /blueprints/            # Blueprints page
Packit Service eebd6f
│   ├── /blueprintEdit/         # Edit blueprint page
Packit Service eebd6f
│   └── /error/                 # Error page
Packit Service eebd6f
├── /po/                        # Translated result by Weblate
Packit Service eebd6f
├── /public/                    # Static files
Packit Service eebd6f
│   ├── /dist/                  # The folder for compiled output
Packit Service eebd6f
│   ├── /js/                    # Javascript files included in index.ejs
Packit Service eebd6f
│   ├── /custom.css             # CSS file included in index.ejs
Packit Service eebd6f
│   ├── /manifest.json          # manifest file for Cockpit integration
Packit Service eebd6f
│   └── /index.ejs              # Template for index.html
Packit Service eebd6f
├── /test/                      # Integration test
Packit Service eebd6f
├── /utils/                     # Utility and helper classes
Packit Service eebd6f
│── babel.config.js             # babel configurations
Packit Service eebd6f
│── cockpit-composer.spec.in    # Cockpit-composer spec file
Packit Service 784c3d
│── Dockerfile.buildrpm         # Dockerfile for building RPM on Github Actions
Packit Service eebd6f
│── io.weldr.cockpit-composer.metainfo.xml         # Makes Composer appear on Cockpit's "Applications" page
Packit Service eebd6f
│── main.js                     # React application entry point
Packit Service eebd6f
│── Makefile                    # Makefile
Packit Service eebd6f
│── package.json                # The list of project dependencies and NPM scripts
Packit Service eebd6f
│── routes.json                 # This list of application routes
Packit Service eebd6f
│── rpmversion.sh               # Generate the version and release strings for spec file
Packit Service eebd6f
└── webpack.config.js           # Bundling and optimization settings for Webpack
Packit Service eebd6f
```
Packit Service eebd6f
Packit Service eebd6f
### Cockpit API
Packit Service eebd6f
Packit Service eebd6f
To keep Cockpit Composer working with Cockpit API all code should follow the following rules.
Packit Service eebd6f
Packit Service eebd6f
 * All urls in the html and javascript need to use relative paths.
Packit Service eebd6f
 * All requests to the API should be made using ```utils.apiFetch```. Any non API ```fetch``` requests
Packit Service eebd6f
   must use ```credentials: 'same-origin'``` so that cookies are included with those ajax requests.
Packit Service eebd6f
 * Use hashes for navigation within the SPA so that cockpit can keep the top level location display
Packit Service eebd6f
   up to date.
Packit Service eebd6f
Packit Service eebd6f
### Package as an RPM/SRPM
Packit Service eebd6f
Packit Service eebd6f
This project can be packaged as either a noarch rpm or an srpm.
Packit Service eebd6f
Packit Service eebd6f
```shell
Packit Service eebd6f
$ make rpm                # Or, `make srpm`
Packit Service eebd6f
```
Packit Service eebd6f
Packit Service eebd6f
### i18n
Packit Service eebd6f
Packit Service eebd6f
For a general guide on how to write translatable strings, see [weldr.io](http://weldr.io/Translating-welder-web-strings/)
Packit Service eebd6f
Packit Service eebd6f
There are a lot of parts involved in translating a string. Here's an overview of the process, from start to finish:
Packit Service eebd6f
Packit Service eebd6f
**Step 1**. During development, the developer adds a translatable string. See [weldr.io](http://weldr.io/Translating-welder-web-strings/)
Packit Service eebd6f
for details on how to indicate that the string is translatable, and what the string may contain. In general, the string
Packit Service eebd6f
is added using [react-intl](https://github.com/yahoo/react-intl) `MessageDescriptor`s, but without explicit `id` attributes.
Packit Service eebd6f
Packit Service eebd6f
*Debugging generated messages*
Packit Service eebd6f
Packit Service eebd6f
To see if or how messages are generated, `make po/cockpit-composer.pot` can be run to generate `po/cockpit-composer.pot`,
Packit Service eebd6f
which is the file, that is uploaded for translators later on.
Packit Service eebd6f
As part of this process, [babel-plugin-react-intl-auto](https://github.com/akameco/babel-plugin-react-intl-auto)
Packit Service eebd6f
will add `id` attributes to all of the messages, and [babel-plugin-react-intl](https://github.com/yahoo/babel-plugin-react-intl)
Packit Service eebd6f
will extract all of the messages to JSON files, written to `./build/messages`. [react-intl-po](https://github.com/evenchange4/react-intl-po) is
Packit Service eebd6f
used to collect the JSON files into a gettext-style POT file (po/cockpit-composer.pot).
Packit Service eebd6f
Packit Service eebd6f
**Step 2**. With `make upload-pot` the PO template gets uploaded to the [Weblate translation platform](https://translate.fedoraproject.org/projects/cockpit-composer/)
Packit Service eebd6f
where everybody can contribute translations to various languages. This is part of [bots/po-refresh](https://github.com/cockpit-project/bots/blob/master/po-refresh)
Packit Service eebd6f
which is invoked regularly by [bots/po-trigger](https://github.com/cockpit-project/bots/blob/master/po-trigger).
Packit Service eebd6f
Packit Service eebd6f
**Step 3**. Translators provide translations on Weblate.
Packit Service eebd6f
Packit Service eebd6f
**Step 4**. With `make download-po` Weblate's translations are downloaded to `po/XX.po`. This is also done by
Packit Service eebd6f
[bots/po-refresh](https://github.com/cockpit-project/bots/blob/master/po-refresh).
Packit Service eebd6f
Packit Service eebd6f
**Step 5**. The user runs cockpit-composer. Based on the user's browser configuration, cockpit-composer determines the user's preferred
Packit Service eebd6f
language, and if translations are available, these translations are provided to react-intl's `<IntlProvider>`. react-intl
Packit Service eebd6f
then displays translated strings where possible.
Packit Service eebd6f
Packit Service eebd6f
## Making A New Release Of cockpit-composer
Packit Service eebd6f
Packit Service eebd6f
When the project is ready for a new release, do the following:
Packit Service eebd6f
Packit Service eebd6f
 * Tag the release with `make NEWTAG=X.Y.Z tag`, bumping .Z to the next version unless there are major changes.
Packit Service eebd6f
 * Edit the commit list to reflect the changes that will be visible to users (it shows up on the GitHub Releases page)
Packit Service eebd6f
 * Sign the tag with your GPG key
Packit Service eebd6f
Packit Service eebd6f
(an editor should open automatically, and gpg is required to be setup in order to sign the tag).
Packit Service eebd6f
Packit Service 0c2606
Then push the tag with `git push --tags`. This triggers the [release.yml](.github/workflows/release.yml)
Packit Service 0c2606
[GitHub action](https://github.com/features/actions) workflow.
Packit Service 0c2606
Packit Service 0c2606
The workflow runs [cockpituous](https://github.com/cockpit-project/cockpituous/tree/master/release)
Packit Service 0c2606
to build a new release of cockpit-composer, with the [cockpituous-release](./utils/cockpituous-release) control file.
Packit Service 0c2606
This uses the shared [cockpit-project organization secrets](https://github.com/organizations/cockpit-project/settings/secrets).
Packit Service eebd6f
Packit Service eebd6f
Finally, import the new `.srpm` into the appropriate RHEL release.
Packit Service eebd6f
Packit Service 0c2606
## Automated maintenance
Packit Service 0c2606
Packit Service 0c2606
It is important to keep your [NPM modules](./package.json) up to date, to keep
Packit Service 0c2606
up with security updates and bug fixes. This is done with the
Packit Service 0c2606
[npm-update bot script](https://github.com/cockpit-project/bots/blob/master/npm-update)
Packit Service 0c2606
which is run daily or upon [manual request](https://github.com/osbuild/cockpit-composer/actions) through the
Packit Service 0c2606
[npm-update.yml](.github/workflows/npm-update.yml) [GitHub action](https://github.com/features/actions).
Packit Service 0c2606
Packit Service 0c2606
Similarly, translations are refreshed every Tuesday evening (or manually) through the
Packit Service 0c2606
[po-refresh.yml](.github/workflows/po-refresh.yml) action.
Packit Service 0c2606
Packit Service eebd6f
## License
Packit Service eebd6f
Packit Service eebd6f
This source code is licensed under the MIT license found in the [`LICENSE.txt`](LICENSE.txt) file.
Packit Service eebd6f
Packit Service eebd6f
---
Packit Service eebd6f
Made with ♥ by the [OSBuild team](https://github.com/orgs/osbuild/people), [Welder team](https://github.com/orgs/weldr/people), [Cockpit team](https://github.com/orgs/cockpit-project/people), and contributors