Repository navigation
feat(odd): models for gap and ref #836
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: apps and images | |
| concurrency: | |
| group: jinks-apps-images | |
| cancel-in-progress: false | |
| on: | |
| push: | |
| branches: | |
| - '**' | |
| tags: | |
| - v* | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| env: | |
| IMAGE_NAME: jinks-demo | |
| JINKS_IMAGE: ghcr.io/eeditiones/jinks | |
| jobs: | |
| test-jinks: | |
| name: test jinks image | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/tags/v') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| EXIST_BASE: [6.4.0] | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Build Jinks image for testing | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| build-args: | | |
| EXIST_VERSION=${{ matrix.EXIST_BASE }} | |
| load: true | |
| tags: exist-db | |
| cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache | |
| - name: Start docker image | |
| run: docker run --publish 8080:8080 --name db --detach exist-db | |
| - name: Run Cypress e2e test | |
| uses: cypress-io/github-action@v7 | |
| with: | |
| browser: firefox | |
| - name: Retrieve eXist log | |
| if: failure() | |
| run: docker cp db:/exist/logs/exist.log . | |
| - name: Publish log as artifact | |
| if: failure() | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: jinks-deploy-exist-${{ matrix.EXIST_BASE }}-log | |
| path: ./exist.log | |
| - name: Stop docker | |
| run: docker stop db || true | |
| push-jinks: | |
| name: push jinks | |
| needs: test-jinks | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/tags/v') | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: linux/amd64,linux/arm64 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| id: buildx | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository }} | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern=v{{major}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Add latest tag for releases | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| echo "tags<<EOF" >> $GITHUB_OUTPUT | |
| echo -e "${{ steps.meta.outputs.tags }}\nghcr.io/${{ github.repository }}:latest" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| id: tags_with_latest | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Push jinks | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/tags/v') | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| build-args: | | |
| PUBLISHER_VERSION=main | |
| EXIST_VERSION=6.4.0 | |
| builder: ${{ steps.buildx.outputs.name }} | |
| push: true | |
| sbom: true | |
| tags: ${{ steps.tags_with_latest.outputs.tags || steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache | |
| cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max | |
| generate-apps: | |
| name: generate apps | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build Jinks image from source | |
| # Build the image from this checkout (Dockerfile BUILD=local) so jinks is | |
| # autodeployed into a clean DB. Pulling the prebuilt image and mounting | |
| # build/ does not work: eXist autodeploy never upgrades an already-installed | |
| # package, so jinks create would keep running the image's stale profiles. | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| build-args: | | |
| EXIST_VERSION=6.4.0 | |
| load: true | |
| tags: jinks-server:ci | |
| cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache | |
| - name: Start jinks container | |
| run: | | |
| docker run -d \ | |
| --name jinks-server \ | |
| -p 8080:8080 \ | |
| jinks-server:ci | |
| - name: Wait for server to start | |
| timeout-minutes: 10 | |
| run: | | |
| echo "Waiting for server to start..." | |
| until docker logs jinks-server 2>&1 | grep -q "Server has started"; do | |
| echo "Still waiting..." | |
| sleep 4 | |
| done | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 'lts/*' | |
| - name: Install CLI tools | |
| run: npm install -g @teipublisher/jinks-cli @existdb/xst | |
| - name: Generate tei-publisher app | |
| working-directory: demo | |
| run: jinks create -c tp_config.json | |
| - name: Generate tp-serafin app | |
| working-directory: demo | |
| run: jinks create -c ser_config.json | |
| - name: Generate tp-workbench app | |
| working-directory: demo | |
| run: jinks create -c workbench_config.json | |
| - name: Verify deployed apps | |
| run: jinks list | |
| - name: Smoke test - verify apps loaded correctly | |
| run: | | |
| for app in tei-publisher tp-serafin tp-workbench; do | |
| echo "Checking $app..." | |
| response=$(curl -s -o /tmp/smoke-${app}.txt -w "%{http_code}" \ | |
| -X POST -d "user=tei&password=tei" \ | |
| http://localhost:8080/exist/apps/${app}/api/login) | |
| if [ "$response" != "200" ] && [ "$response" != "401" ]; then | |
| echo "Smoke test FAILED for $app: /api/login returned HTTP $response" | |
| echo "Response body:" | |
| cat /tmp/smoke-${app}.txt | |
| exit 1 | |
| fi | |
| echo "$app OK (HTTP $response)" | |
| done | |
| - name: Smoke test tp-workbench ODD transforms | |
| run: | | |
| xst get /db/apps/tp-workbench/transform/teipublisher-web.xql /tmp/teipublisher-web.xql | |
| if grep -q 'namespace global="http://www.tei-c.org/tei-simple/config"' /tmp/teipublisher-web.xql; then | |
| echo "FAIL: teipublisher-web.xql binds global to config.xqm (stale Jinks profiles?)" | |
| exit 1 | |
| fi | |
| if ! grep -q 'odd-global.xqm' /tmp/teipublisher-web.xql; then | |
| echo "FAIL: teipublisher-web.xql does not import odd-global.xqm" | |
| exit 1 | |
| fi | |
| echo "OK: teipublisher-web.xql imports odd-global.xqm" | |
| - name: Extract XAR files for generated apps | |
| working-directory: demo | |
| run: | | |
| jinks run tei-publisher download | |
| jinks run tp-serafin download | |
| jinks run tp-workbench download | |
| - name: List generated XAR files | |
| working-directory: demo | |
| run: | | |
| echo "Generated XAR files:" | |
| ls -lh *.xar || echo "No XAR files found!" | |
| - name: Commit container for test jobs | |
| run: | | |
| # Flush the database before snapshotting: committing a running eXist | |
| # instance leaves a stale journal and the test jobs restart with recovery. | |
| docker stop -t 120 jinks-server | |
| docker commit jinks-server temp/jinks-server:$GITHUB_SHA | |
| mkdir -p path/to/artifacts | |
| docker save temp/jinks-server:$GITHUB_SHA > path/to/artifacts/docker-image.tar | |
| - name: Upload container artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: docker-artifact | |
| path: path/to/artifacts | |
| retention-days: 3 | |
| - name: Upload XAR artifacts | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: demo-apps-xars | |
| path: demo/*.xar | |
| retention-days: 30 | |
| - name: Stop jinks container | |
| if: always() | |
| run: docker rm -f jinks-server || true | |
| push-demo: | |
| name: push demo | |
| needs: [push-jinks, generate-apps, test-tp, test-workbench, test-serafin] | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/tags/v') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: linux/amd64,linux/arm64 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| id: buildx | |
| - name: Download XAR artifacts | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: demo-apps-xars | |
| path: demo/ | |
| - name: Verify XAR files | |
| working-directory: demo | |
| run: | | |
| echo "XAR files to include in image:" | |
| ls -lh *.xar | |
| if [ ! -f "tei-publisher.xar" ] || [ ! -f "tp-serafin.xar" ] || [ ! -f "tp-workbench.xar" ]; then | |
| echo "Error: Missing required XAR files" | |
| exit 1 | |
| fi | |
| - name: Set JINKS_VERSION | |
| id: jv | |
| run: | | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT | |
| else | |
| echo "version=latest" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository }}-demo | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern=v{{major}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Add latest tag for releases | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| echo "tags<<EOF" >> $GITHUB_OUTPUT | |
| echo -e "${{ steps.meta.outputs.tags }}\nghcr.io/${{ github.repository }}-demo:latest" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| id: tags_with_latest | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Push demo | |
| timeout-minutes: 25 | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: demo | |
| file: demo/Dockerfile.demo | |
| platforms: linux/amd64,linux/arm64 | |
| build-args: | | |
| JINKS_VERSION=${{ steps.jv.outputs.version }} | |
| builder: ${{ steps.buildx.outputs.name }} | |
| push: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| sbom: true | |
| tags: ${{ steps.tags_with_latest.outputs.tags || steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=registry,ref=ghcr.io/${{ github.repository }}-demo:buildcache | |
| cache-to: type=registry,ref=ghcr.io/${{ github.repository }}-demo:buildcache,mode=max | |
| test-tp: | |
| name: test tp | |
| runs-on: ubuntu-latest | |
| needs: generate-apps | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Cypress tests on tei-publisher | |
| uses: ./.github/actions/cypress-test-for-demo-app | |
| with: | |
| app-name: tei-publisher | |
| test-workbench: | |
| name: test workbench | |
| runs-on: ubuntu-latest | |
| needs: generate-apps | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Cypress tests on tp-workbench | |
| uses: ./.github/actions/cypress-test-for-demo-app | |
| with: | |
| app-name: tp-workbench | |
| test-serafin: | |
| name: test serafin | |
| runs-on: ubuntu-latest | |
| needs: generate-apps | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Cypress tests on tp-serafin | |
| uses: ./.github/actions/cypress-test-for-demo-app | |
| with: | |
| app-name: tp-serafin |