Skip to content

Commit

Permalink
Refactored build to separate browser and electron and added docker bu…
Browse files Browse the repository at this point in the history
…ild for main (#74)

* Created Dockerfile based on theia-ide dockerfile setup and adjusted for CrossModel.
* Updated package configurations and webpack configuration.
* Added docker job to main workflow.
* Updated all @crossbreeze package versions to 0.0.0 and updated versionspec where used.
* Added installing unzip and unzip the vsix to the plugins folder.
* Change crossmodel-lang to version 0.0.0.
* Remove prepare script everywhere.
* Made separate build & watch scripts for browser and electron, in line with start.
* Updated build-and-test action to use build:browser.
* Updated README.
  • Loading branch information
harmen-xb authored Nov 25, 2024
1 parent 2c6314d commit 60fa280
Show file tree
Hide file tree
Showing 21 changed files with 328 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
# We set a timeout here as a fix for the timeout issues which sometimes occur when connecting the the npm repo.
run: |
yarn --skip-integrity-check --network-timeout 100000
yarn build
yarn build:browser
env:
NODE_OPTIONS: --max_old_space_size=4096
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9
Expand Down
51 changes: 51 additions & 0 deletions .github/workflows/cicd-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ on:
branches:
- main

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-test:
uses: ./.github/workflows/build-and-test.yml

# Publish a test report using the playwright result files published in the previous step (execute in Linux only).
publish-playwright-test-report:
name: Publish PlayWright Test Report
Expand Down Expand Up @@ -60,3 +65,49 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

# Create Docker image with CrossModel web application.
docker:
# Only make the docker image when build and test succeeded.
needs: build-and-test
runs-on: ubuntu-latest

permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push
id: push
uses: docker/build-push-action@v6
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
91 changes: 91 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Stage 1: Builder stage
FROM node:20-alpine AS build-stage

# Install OS packages needed for building Theia.
# Packages can be searched here: https://pkgs.alpinelinux.org/packages
RUN apk add \
yarn \
libsecret-dev \
libxkbfile-dev \
make \
g++ \
python3 \
py3-setuptools \
unzip

# Set the working directory
WORKDIR /home/crossmodel

# Copy the current directory contents to the container
COPY . .

# Run the build commands.
# - Download plugins and build application
# - Use yarn autoclean to remove unnecessary files from package dependencies
# - Remove unnecesarry files for the browser application
RUN yarn --pure-lockfile --skip-integrity-check --network-timeout 100000 && \
yarn build:packages && \
yarn build:extensions && \
yarn package:extensions && \
yarn theia:browser build && \
unzip extensions/crossmodel-lang/*.vsix -d applications/browser-app/plugins/crossmodel-lang && \
yarn autoclean --init && \
echo *.ts >> .yarnclean && \
echo *.ts.map >> .yarnclean && \
echo *.spec.* >> .yarnclean && \
yarn autoclean --force && \
yarn cache clean && \
rm -rf .devcontainer .git .github .vscode applications/electron-app docs e2e-tests examples

# Stage 2: Production stage, using a slim image
FROM node:20-alpine AS production-stage

# Create a non-root user with a fixed user id and setup the environment
RUN addgroup -S crossmodel && \
adduser --system --uid 101 crossmodel crossmodel && \
chmod g+rw /home && \
mkdir -p /home/crossmodel && \
chown -R crossmodel:crossmodel /home/crossmodel && \
mkdir -p /home/project

# Install required tools for application: Git, SSH, Bash
# Node is already available in base image
RUN apk add \
bash \
openssh-server \
openssh-client-default \
libsecret \
git

# Copy the mapping example workspace into the project folder.
COPY examples/mapping-example /home/project

# Set the permission of the project folder.
RUN chown -R crossmodel:crossmodel /home/project

ENV HOME=/home/crossmodel
WORKDIR /home/crossmodel

# Copy the build output to the production environment
COPY --from=build-stage --chown=crossmodel:crossmodel /home/crossmodel /home/crossmodel

# Expose the default CrossModel port
EXPOSE 3000

# Specify default shell for Theia and the Built-In plugins directory
# Use installed git instead of dugite
ENV SHELL=/bin/bash \
THEIA_DEFAULT_PLUGINS=local-dir:/home/crossmodel/applications/browser-app/plugins \
USE_LOCAL_GIT=true

# Use the non-root user
USER crossmodel

# Set the working directory to the browser application
WORKDIR /home/crossmodel/applications/browser-app

# Start the application
ENTRYPOINT ["node", "/home/crossmodel/applications/browser-app/lib/backend/main.js"]

# Arguments passed to the application
CMD ["/home/project", "--hostname=0.0.0.0"]
91 changes: 91 additions & 0 deletions Dockerfile.ubuntu
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Stage 1: Builder stage
FROM node:20-bookworm AS build-stage

# Install OS packages needed for building Theia.
RUN apt-get update && \
export DEBIAN_FRONTEND=noninteractive && \
apt-get -y install --no-install-recommends \
libsecret-1-dev \
libxkbfile-dev \
make \
build-essential \
python3 \
unzip

# Set the working directory
WORKDIR /home/crossmodel

# Copy the current directory contents to the container
COPY . .

# Run the build commands.
# - Download plugins and build application
# - Use yarn autoclean to remove unnecessary files from package dependencies
# - Remove unnecesarry files for the browser application
RUN yarn --pure-lockfile --skip-integrity-check --network-timeout 100000 && \
yarn build:packages && \
yarn build:extensions && \
yarn package:extensions && \
yarn theia:browser build && \
unzip extensions/crossmodel-lang/*.vsix -d applications/browser-app/plugins/crossmodel-lang && \
yarn autoclean --init && \
echo *.ts >> .yarnclean && \
echo *.ts.map >> .yarnclean && \
echo *.spec.* >> .yarnclean && \
yarn autoclean --force && \
yarn cache clean && \
rm -rf .devcontainer .git .github .vscode applications/electron-app docs e2e-tests examples

# Stage 2: Production stage, using a slim image
FROM node:20-bookworm-slim AS production-stage

# Create a non-root user with a fixed user id and setup the environment
# Default workspace is located at /home/project
RUN adduser --system --group --uid 101 --home /home/crossmodel crossmodel && \
chmod g+rw /home && \
chown -R crossmodel:crossmodel /home/crossmodel && \
mkdir -p /home/project

# Install required tools for application: Git, SSH, Bash
# Node is already available in base image
RUN apt-get update && \
apt-get install -y \
bash \
openssh-server \
openssh-client \
libsecret-1-0 \
git && \
apt-get clean

# Copy the mapping example workspace into the project folder.
COPY examples/mapping-example /home/project

# Set the permission of the project folder.
RUN chown -R crossmodel:crossmodel /home/project

ENV HOME=/home/crossmodel
WORKDIR /home/crossmodel

# Copy the build output to the production environment
COPY --from=build-stage --chown=crossmodel:crossmodel /home/crossmodel /home/crossmodel

# Expose the default CrossModel port
EXPOSE 3000

# Specify default shell for Theia and the Built-In plugins directory
# Use installed git instead of dugite
ENV SHELL=/bin/bash \
THEIA_DEFAULT_PLUGINS=local-dir:/home/crossmodel/applications/browser-app/plugins \
USE_LOCAL_GIT=true

# Use the non-root user
USER crossmodel

# Set the working directory to the browser application
WORKDIR /home/crossmodel/applications/browser-app

# Start the application
ENTRYPOINT ["node", "/home/crossmodel/applications/browser-app/lib/backend/main.js"]

# Arguments passed to the application
CMD ["/home/project", "--hostname=0.0.0.0"]
45 changes: 36 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ For detailed instructions for a Windows machine, follow [this](./docs/Prerequisi

## Running the application

yarn start:electron
### Browser

_or:_
This will build and start CrossModel as a web application. When the web application is running you can open <http://localhost:3000> in your browser to use CrossModel.

yarn rebuild:electron
cd applications/electron-app
yarn start
yarn build:browser &&
yarn start:browser

### Electron (desktop application)

_or:_ launch `Launch CrossModel Electron` configuration from VS code.
This will build and start CrossModel as a native desktop application for the OS (Windows, Linux or MacOS) where the command is started.

yarn build:electron &&
yarn start:electron

## Example Workspace

Expand All @@ -45,9 +49,13 @@ Currently there is still an issue where new files are not recognized automatical

## Developing

Start watching all packages, including `electron-app`, of your application with
Start watching all packages of your application for either browser or electron version.

yarn watch
yarn watch:browser

_or_

yarn watch:electron

_or_ watch only specific packages with

Expand Down Expand Up @@ -77,11 +85,30 @@ Short steps:

## Packaging

To package the application use
We package CrossModel either for the browser (Docker) or desktop application (Electron).

### Docker

To package the web application we build a docker image. There are currently two Dockerfile definitions, one based on [Alpine Linux](./Dockerfile) and one based on [Ubuntu](./Dockerfile.ubuntu). Some users might prefer Ubuntu over Alpine as based, which is why we have both options.

To create the Alpine based image, execute the following command:

docker build -t crossmodel:0.0.0-alpine -f .\Dockerfile .

To create the Ubuntu based image, execute the following command:

docker build -t crossmodel:0.0.0-ubuntu -f .\Dockerfile.ubuntu .

In the main build action we build and publish the Alpine version.

### Electron

To package CrossModel as a desktop application, execute the following command:

yarn theia:electron package

Depending on the platform, this will produce an executable or an installer for the application under `applications/electron-app/dist`.

Details about the packaging can be configured in `applications/electron-app/electron-builder.yml`.

## Structure
Expand Down
Binary file added applications/browser-app/ico/favicon.ico
Binary file not shown.
9 changes: 5 additions & 4 deletions applications/browser-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
"email": "devops@crossbreeze.nl"
},
"scripts": {
"bundle": "yarn rebuild && theia build --mode development && yarn download:plugins",
"clean": "theia clean && rimraf lib && rimraf src-gen",
"build": "yarn -s rebuild && theia build --app-target=\"browser\" --mode development && yarn download:plugins",
"build:prod": "yarn -s rebuild && theia build --app-target=\"browser\"",
"clean": "theia clean && rimraf lib src-gen",
"download:plugins": "theia download:plugins",
"rebuild": "theia rebuild:browser --cacheRoot ../..",
"start": "theia start --plugins=local-dir:plugins",
Expand All @@ -27,9 +28,9 @@
"@crossbreeze/core": "0.0.0",
"@crossbreeze/form-client": "0.0.0",
"@crossbreeze/glsp-client": "0.0.0",
"@crossbreeze/model-service": "^1.0.0",
"@crossbreeze/model-service": "0.0.0",
"@crossbreeze/product": "0.0.0",
"@crossbreeze/property-view": "^1.0.0",
"@crossbreeze/property-view": "0.0.0",
"@theia/core": "1.49.1",
"@theia/editor": "1.49.1",
"@theia/filesystem": "1.49.1",
Expand Down
21 changes: 17 additions & 4 deletions applications/browser-app/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// @ts-check
const configs = require('./gen-webpack.config.js');
const nodeConfig = require('./gen-webpack.node.config.js');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

/**
* Expose bundled modules on window.theia.moduleName namespace, e.g.
Expand All @@ -15,7 +17,18 @@ configs[0].module.rules.push({
loader: require.resolve('@theia/application-manager/lib/expose-loader')
}); */

module.exports = [
...configs,
nodeConfig.config
];
// serve favico from root
// @ts-ignore
configs[0].plugins.push(
// @ts-ignore
new CopyWebpackPlugin({
patterns: [
{
context: path.resolve('.', '..', '..', 'applications', 'browser-app', 'ico'),
from: '**'
}
]
})
);

module.exports = [...configs, nodeConfig.config];
Loading

0 comments on commit 60fa280

Please sign in to comment.