diff --git a/.env b/.env index da8778c9..b76fefbf 100644 --- a/.env +++ b/.env @@ -1,3 +1 @@ -COMPOSER_DEV_ARG= -IMAGE_TAG=develop DATA_FOLDER= diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..ac74a2c8 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,67 @@ +name: CI Pipeline + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + push: + branches: + - master + +jobs: + generate-version: + runs-on: ubuntu-latest + outputs: + trunkver: ${{ steps.trunkver.outputs.trunkver }} + steps: + - name: Get a version tag + id: trunkver + uses: crftd-tech/trunkver@main + with: + prerelease: ${{ github.ref == 'refs/heads/master' && 'false' || 'true' }} + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Bring up test stack + run: docker compose up --wait + - name: Debug bring up test stack + if: failure() + run: docker compose logs + - name: Project Tests + run: docker compose exec app bash ./project_tests.sh + - name: Smoke Tests + run: docker compose exec app bash ./smoke_tests.sh + build-and-push: + needs: [generate-version, tests] + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' + env: + IMAGE_REPO: ghcr.io/elifesciences/api-dummy + IMAGE_TAG: ${{ github.ref == 'refs/heads/master' && needs.generate-version.outputs.trunkver || format('{0}-{1}', github.head_ref || github.ref_name, needs.generate-version.outputs.trunkver) }} + steps: + - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - 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.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push client image + uses: docker/build-push-action@v6 + with: + push: true + load: false + # Disabled until elifesciences/php or another image with ARM support can be used as a base + # platforms: linux/amd64,linux/arm64 + target: prod + tags: | + ${{ env.IMAGE_REPO }}:${{ github.sha }} + ${{ env.IMAGE_REPO }}:${{ env.IMAGE_TAG }} diff --git a/Dockerfile b/Dockerfile index fecf8c66..8431ccad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,13 @@ -ARG image_tag=latest -FROM elifesciences/api-dummy_composer:${image_tag} AS build -FROM ghcr.io/elifesciences/php:8.0-cli@sha256:f681973227dbab578218a98f252dfd36fd42016b74be6d0044221a7d8cdcc4e6 +FROM composer:1.10 AS build + +COPY composer.json composer.lock ./ +RUN composer --no-interaction install --no-suggest --prefer-dist + +FROM elifesciences/php_7.0_cli:656bb4bdf1e49a5e80337e2a7c4f44f10c3f52b0 AS base USER elife + ENV PROJECT_FOLDER=/srv/api-dummy -RUN mkdir ${PROJECT_FOLDER} WORKDIR ${PROJECT_FOLDER} COPY --chown=elife:elife smoke_tests.sh ./ @@ -15,4 +18,24 @@ COPY --chown=elife:elife src/ src/ USER www-data EXPOSE 8080 + +CMD ["php", "-S", "0.0.0.0:8080", "-t", "web/"] + +FROM base AS prod + +FROM base AS test + +USER root +RUN mkdir -p build && chown www-data:www-data build + +USER www-data +COPY --chown=elife:elife phpcs.xml.dist phpunit.xml.dist project_tests.sh ./ +COPY --chown=elife:elife test/ test/ + +CMD ["./project_tests.sh"] + +FROM test AS dev + +COPY --from=build /usr/bin/composer /usr/bin/composer + CMD ["php", "-S", "0.0.0.0:8080", "-t", "web/"] diff --git a/Dockerfile.ci b/Dockerfile.ci deleted file mode 100644 index f5ed5493..00000000 --- a/Dockerfile.ci +++ /dev/null @@ -1,24 +0,0 @@ -ARG image_tag=develop -FROM elifesciences/api-dummy_composer_dev:${image_tag} AS build -FROM ghcr.io/elifesciences/php:8.0-cli@sha256:f681973227dbab578218a98f252dfd36fd42016b74be6d0044221a7d8cdcc4e6 - -ENV PROJECT_FOLDER=/srv/api-dummy - -USER root - -WORKDIR ${PROJECT_FOLDER} -RUN mkdir -p build && \ - chown --recursive elife:elife . && \ - chown www-data:www-data build - -USER elife - -COPY --chown=elife:elife phpcs.xml.dist phpunit.xml.dist project_tests.sh ./ -COPY --chown=elife:elife web/ web/ -COPY --chown=elife:elife test/ test/ -COPY --from=build --chown=elife:elife /app/vendor/ vendor/ -COPY --chown=elife:elife data/ data/ -COPY --chown=elife:elife src/ src/ - -USER www-data -CMD ["./project_tests.sh"] diff --git a/Dockerfile.composer b/Dockerfile.composer deleted file mode 100644 index c1559cb4..00000000 --- a/Dockerfile.composer +++ /dev/null @@ -1,13 +0,0 @@ -FROM composer:2.2 - -ARG composer_dev_arg - -COPY composer.json \ - composer.lock \ - ./ - -RUN composer --no-interaction install ${composer_dev_arg} --ignore-platform-reqs --no-autoloader --no-suggest --prefer-dist - -COPY test/ test/ - -RUN composer --no-interaction dump-autoload ${composer_dev_arg} --classmap-authoritative diff --git a/Jenkinsfile b/Jenkinsfile index 7a658417..31a3f1b1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ elifePipeline { } stage 'Build image', { - sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml -f docker-compose.ci.yml build" + sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml build" image = DockerImage.elifesciences(this, 'api-dummy', commit) elifePullRequestOnly { prNumber -> // push immediately to allow downstream exploration even with automated tests failing @@ -18,12 +18,12 @@ elifePipeline { } stage 'Project tests', { - dockerProjectTests 'api-dummy', commit try { - sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d" - sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml -f docker-compose.ci.yml exec -T cli ./smoke_tests.sh" + sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml up -d" + sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml exec -T app ./project_tests.sh" + sh "IMAGE_TAG=${commit} docker-compose -f docker-compose.yml exec -T app ./smoke_tests.sh" } finally { - sh 'docker-compose -f docker-compose.yml -f docker-compose.ci.yml down' + sh 'docker-compose -f docker-compose.yml down' } } @@ -31,7 +31,7 @@ elifePipeline { stage 'Push image', { image.push() } - + stage 'Approval', { elifeGitMoveToBranch commit, 'approved' image.tag('approved').push() @@ -40,18 +40,4 @@ elifePipeline { }, 'elife-libraries--ci' ) - - elifeMainlineOnly { - stage 'Deploy on demo', { - checkout scm - elifeGitMoveToBranch commit, 'master' - elifeOnNode( - { - image.tag('latest').push() - }, - 'elife-libraries--ci' - ) - builderDeployRevision 'api-dummy--demo', commit - } - } } diff --git a/README.md b/README.md index 79960d77..b7a44476 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,30 @@ eLife 2.0 Dummy API This contains a dummy implementation of the [eLife 2.0 API](https://github.com/elifesciences/api-raml). -##Import article +## Import article ```$sh -cd /srv/api-dummy -./bin/import 09560 +docker compose run app ./bin/import 09560 ``` -The above command should result in a data fixture for article 09560 being created at `/srv/api-dummy/data/articles/09560.json` +The above command should result in a data fixture for article 09560 being created at `data/articles/09560.json` ## Run locally ```$sh -cd /srv/api-dummy -php -S localhost:5001 ./web/index.php +docker compose up ``` -Then visit [http://localhost:5001/articles](http://localhost:5001/articles) in your browser. +Then visit [http://localhost:8080/articles](http://localhost:8080/articles) in your browser. + +## Update local vendor for development + +```$sh +docker compose -f docker-compose.dev.yml run composer install +``` + +## Run tests + +```$sh +docker compose run --rm app ./project_tests.sh +``` diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml deleted file mode 100644 index d87da3b0..00000000 --- a/docker-compose.ci.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: '3' - -services: - composer: - build: - args: - composer_dev_arg: --no-dev - composer-dev: - build: - context: . - dockerfile: Dockerfile.composer - args: - composer_dev_arg: - image: elifesciences/api-dummy_composer_dev:${IMAGE_TAG} - command: /bin/bash - ci: - build: - context: . - dockerfile: Dockerfile.ci - args: - image_tag: ${IMAGE_TAG} - image: elifesciences/api-dummy_ci:${IMAGE_TAG} - depends_on: - - composer-dev diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 00000000..2e3b820a --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,10 @@ +services: + composer: + build: + context: . + dockerfile: Dockerfile + target: build + volumes: + - ./composer.json:/app/composer.json + - ./composer.lock:/app/composer.lock + - ./vendor:/app/vendor diff --git a/docker-compose.override.yml b/docker-compose.override.yml index d38747d9..fed61ab6 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,16 +1,5 @@ -version: '3' - services: - composer: - volumes: - - ./composer.json:/app/composer.json - - ./composer.lock:/app/composer.lock - - vendor:/app/vendor - cli: - volumes: - - ./:/srv/api-dummy - - /srv/api-dummy/build - - vendor:/srv/api-dummy/vendor - -volumes: - vendor: + app: + depends_on: + composer: + condition: service_completed_successfully diff --git a/docker-compose.yml b/docker-compose.yml index 76cd091d..2e726952 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,24 +1,30 @@ -version: '3' - +version: "2.4" services: composer: build: context: . - dockerfile: Dockerfile.composer - args: - composer_dev_arg: ${COMPOSER_DEV_ARG} - image: elifesciences/api-dummy_composer:${IMAGE_TAG} - command: /bin/bash - cli: + dockerfile: Dockerfile + target: build + command: install + volumes: + - ./composer.json:/app/composer.json + - ./composer.lock:/app/composer.lock + - vendor:/app/vendor + + app: build: context: . dockerfile: Dockerfile - args: - image_tag: ${IMAGE_TAG} + target: dev + image: elifesciences/api-dummy:${IMAGE_TAG:-dev} environment: DATA_FOLDER: ${DATA_FOLDER} - image: elifesciences/api-dummy:${IMAGE_TAG} ports: - "8080:8080" - depends_on: - - composer + volumes: + - ./:/srv/api-dummy + - /srv/api-dummy/build + - vendor:/srv/api-dummy/vendor + +volumes: + vendor: