Skip to content

Commit

Permalink
Initial commit with first working implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
stefandesu committed Jan 17, 2024
0 parents commit 183af76
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.DS_Store
node_modules/
/dist*/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

data/

# Temporary folder
temp/

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
36 changes: 36 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Publish Docker
on:
push:
branches:
- main

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

jobs:
publish:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Docker Meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
-
name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and Push
uses: docker/build-push-action@v4
with:
push: true
labels: ${{ steps.meta.outputs.labels }}
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
node_modules/
/dist*/
/data*/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM ubuntu:22.04
WORKDIR /root

# Use bash as shell (instead of sh)
SHELL ["/bin/bash", "-c"]

RUN apt update
# Install dependencies
RUN apt install -y curl git wget unzip jq
# Install fnm for managing Node.js versions
RUN curl -fsSL https://fnm.vercel.app/install | bash

COPY . .

# Directory where all Cocoda installations will live
RUN mkdir -p /www/cocoda

CMD ./docker-entrypoint.sh
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Cocoda Versions (Docker)

Docker image to manage and serve multiple instances of [Cocoda Mapping Tool](https://github.com/gbv/cocoda).

Note: Experimental.

## Usage via Docker Compose

```yml
version: "3"

services:
cocoda:
image: ghcr.io/gbv/cocoda-versions
volumes:
- ./data/cocoda:/www/cocoda
ports:
- 8080:80
environment:
- TAGS=0.2.0 1.0.0 dev
restart: unless-stopped
```
In the bind mount `./data/cocoda`, the static files of all Cocoda instances will be placed (to prevent rebuilding them every time). In that folder, you can also specify custom Cocoda configurations as `{instance-name}.json`. These will be built in addition to the defined `TAGS`. Custom configurations will use branch `master` by default; a different branch for a particular instance can be specific inside its configuration file as `_branch`.

A special tag `all` can be used to build ALL existing Cocoda versions, plus branches `dev` and `master`. This can be used to provide a history of old Cocoda versions.

The HTTP server serves the instances under the subpath `/cocoda/`, i.e. in the above example, branch `dev` will be availble at http://localhost:8080/cocoda/dev/.

## To-Do
- [ ] Consider using other HTTP server instead of [http-server](https://github.com/http-party/http-server)
- [ ] Separate build step from container start (only start HTTP server on container start)
- [ ] Update specific versions/branches without restarting container.
14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: "3"

services:
cocoda:
build: .
volumes:
- ./data/cocoda:/www/cocoda
- ./data/cocoda.git:/root/cocoda/
- ./test.mjs:/root/test.mjs
ports:
- 8091:80
environment:
- TAGS=dev
# restart: unless-stopped
9 changes: 9 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

# Prepare Node environment via fnm
export PATH="/root/.local/share/fnm:$PATH"
eval "`fnm env --shell bash`"
fnm install 20
npm i -g zx

./start.mjs
94 changes: 94 additions & 0 deletions start.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env zx

await $`node --version`
await $`npm --version`

if (!await fs.pathExists("cocoda")) {
await $`mkdir cocoda`
}
await cd("cocoda")

if (!await fs.pathExists(".git")) {
await $`git clone https://github.com/gbv/cocoda.git .`
}

if (!await fs.pathExists("node_modules")) {
await $`npm ci`
}

// Determine tags
const tags = new Set(process.env.TAGS ? process.env.TAGS.split(" ") : ["all"])
if (tags.has("all")) {
tags.delete("all")
const allTags = await $`git tag`
;`${allTags}`.split("\n").filter(Boolean).forEach(tag => tags.add(tag))
tags.add("master")
tags.add("dev")
}

const targetFolder = "/www/cocoda"

// Target folder also contains custom configs
const customConfigs = await glob([`${targetFolder}/*.json`])
const instances = []
for (const configFile of customConfigs) {
const name = path.basename(configFile, ".json")
if (tags.has(name)) {
tags.delete(name)
}
// Read config file
const instance = { name, configFile }
try {
const { _branch } = await fs.readJson(configFile)
instance.branch = _branch || "master"
instances.push(instance)
} catch (error) {
console.error(`Error: Skipping custom instance ${name} because JSON could not be parsed.`)
}
}

// Add tags to instances
for (const tag of tags) {
instances.push({ name: tag, branch: tag })
}

const updatedBranches = new Set()

for (const { name, configFile, branch } of instances) {
console.log(`Cocoda Instance: ${name} (branch/tag: ${branch}, config: ${configFile ?? "none"})`)
if (await fs.pathExists(`${targetFolder}/${name}`)) {
// No updates for non-branches
if (branch.match(/^\d/)) {
console.log("- instance already built and no updates necessary")
continue
}

// Skip if there are no changes with origin
await $`git fetch`.quiet()
const diff = await $`git diff ${branch} origin/${branch}`.quiet()
if (!`${diff}`.trim() && !updatedBranches.has(branch)) {
console.log("- instance already built and no updates necessary")
continue
}
updatedBranches.add(branch)
console.log(`- There's an update to branch ${branch}. Pulling changes and rebuilding Cocoda...`)
await $`git pull origin ${branch}`.quiet()
}
// Build version via build-all.sh script
await $`./build/build-all.sh ${branch}`
// Move files to target folder
if (await fs.pathExists(`${targetFolder}/${name}`)) {
await $`rm -r ${targetFolder}/${name}`
}
await $`mv releases/${branch} ${targetFolder}/${name}`
// Link config file if needed
if (configFile) {
await $`rm ${targetFolder}/${name}/cocoda.json`
await $`ln -s ${configFile} ${targetFolder}/${name}/cocoda.json`
}
console.log(`- Successfully built instance ${name}!`)
}

const port = process.env.PORT ?? "8091"
console.log(`Starting HTTP server on port ${port}...`)
await $`npx http-server -s -d false -p ${port} /www/`

0 comments on commit 183af76

Please sign in to comment.