|
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
|