diff --git a/.github/workflows/build.yml b/.github/old-workflows/gnm-style.yml similarity index 97% rename from .github/workflows/build.yml rename to .github/old-workflows/gnm-style.yml index 3348888..ac799a7 100644 --- a/.github/workflows/build.yml +++ b/.github/old-workflows/gnm-style.yml @@ -1,9 +1,9 @@ name: Build and upload -on: - push: - branchs: ["main"] - workflow_dispatch: {} +#on: +# push: +# branchs: ["main"] +# workflow_dispatch: {} jobs: concierge-graphql: diff --git a/.github/workflows/concierge-graphql.yml b/.github/workflows/concierge-graphql.yml new file mode 100644 index 0000000..8fd8787 --- /dev/null +++ b/.github/workflows/concierge-graphql.yml @@ -0,0 +1,52 @@ +name: Concierge GraphQL + +on: + push: + branches: ["*"] + workflow_dispatch: {} + +jobs: + concierge-graphql: + runs-on: ubuntu-latest + + # The first two permissions are needed to interact with GitHub's OIDC Token endpoint. + # The second set of three permissions are needed to write test results back to GH + permissions: + id-token: write + contents: read + issues: read + checks: write + packages: write + pull-requests: write + + steps: + - uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Setup JDK + uses: actions/setup-java@v3 + with: + distribution: corretto + java-version: 17 + cache: sbt + + - name: Build and test + env: + SBT_JUNIT_OUTPUT: ./junit-tests + JAVA_OPTS: -Dsbt.log.noformat=true + BUILD_NUMBER: ${{ github.run_number }} + run: | + sbt 'test;docker:publish' + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v1 + if: always() #runs even if there is a test failure + with: + files: junit-tests/*.xml \ No newline at end of file diff --git a/.github/workflows/graphiql-explorer.yml b/.github/workflows/graphiql-explorer.yml new file mode 100644 index 0000000..2cf1351 --- /dev/null +++ b/.github/workflows/graphiql-explorer.yml @@ -0,0 +1,55 @@ +name: GraphiQL explorer + +on: + push: + branches: ["*"] + workflow_dispatch: {} + +jobs: + graphiql-explorer: + runs-on: ubuntu-latest + + # The first two permissions are needed to interact with GitHub's OIDC Token endpoint. + # The second set of three permissions are needed to write test results back to GH + permissions: + id-token: write + contents: read + issues: read + checks: write + packages: write + pull-requests: write + + steps: + - uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v3 + with: + node-version: 18.x + cache: 'yarn' + cache-dependency-path: explorer/yarn.lock + + - run: yarn install --frozen-lockfile + name: Prepare to build explorer + working-directory: explorer + + - run: yarn build + name: Build explorer + working-directory: explorer + + + - name: Build and push + uses: docker/build-push-action@v5 + with: + push: true + platforms: linux/amd64,linux/arm64 + context: explorer + tags: ghcr.io/guardian/concierge-graphql/graphiql-explorer:${{ github.run_number }} \ No newline at end of file diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml deleted file mode 100644 index 4fb26aa..0000000 --- a/.github/workflows/snyk.yml +++ /dev/null @@ -1,18 +0,0 @@ -# This action runs snyk monitor on every push to main -name: Snyk - -on: - push: - branches: - - main - workflow_dispatch: - -jobs: - security: - uses: guardian/.github/.github/workflows/sbt-node-snyk.yml@main - with: - DEBUG: true - ORG: guardian-capi - SKIP_NODE: true - secrets: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} \ No newline at end of file diff --git a/build.sbt b/build.sbt index f7c87fe..a4c0a6f 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,6 @@ enablePlugins(DebianPlugin, JavaServerAppPackaging, SystemdPlugin, DockerPlugin, AshScriptPlugin) - +import scala.sys.process._ +import com.typesafe.sbt.packager.docker ThisBuild / version := "0.1.0" ThisBuild / scalaVersion := "2.13.11" @@ -11,10 +12,36 @@ packageSummary := "A proof-of-concept for doing CAPI queries with GraphQL" val prometheusVersion = "0.16.0" +lazy val ensureDockerBuildx = taskKey[Unit]("Ensure that docker buildx configuration exists") +lazy val dockerBuildWithBuildx = taskKey[Unit]("Build docker images using buildx") +lazy val dockerBuildxSettings = Seq( + ensureDockerBuildx := { + if (Process("docker buildx inspect multi-arch-builder").! == 1) { + Process("docker buildx create --use --name multi-arch-builder", baseDirectory.value).! + } + }, + dockerBuildWithBuildx := { + streams.value.log("Building and pushing image with Buildx") + dockerAliases.value.foreach( + alias => Process("docker buildx build --platform=linux/arm64,linux/amd64 --push -t " + + alias + " .", baseDirectory.value / "target" / "docker"/ "stage").! + ) + }, + publish in Docker := Def.sequential( + publishLocal in Docker, + ensureDockerBuildx, + dockerBuildWithBuildx + ).value +) + lazy val root = (project in file(".")) .settings( + dockerBuildxSettings, name := "concierge-graphql", dockerBaseImage := "amazoncorretto:17-alpine", + dockerRepository := Some("ghcr.io/guardian/concierge-graphql"), + dockerAliases := Seq(docker.DockerAlias(registryHost=dockerRepository.value, username=None, name="concierge-graphql", tag=Some(sys.env.getOrElse("BUILD_NUMBER", "DEV")))), + dockerExposedPorts := Seq(9000), libraryDependencies ++= Seq( "org.http4s" %% "http4s-core" % "0.23.21", "org.http4s" %% "http4s-dsl" % "0.23.21", diff --git a/customimages/elasticsearch/Dockerfile b/customimages/elasticsearch/Dockerfile new file mode 100644 index 0000000..d8f7a62 --- /dev/null +++ b/customimages/elasticsearch/Dockerfile @@ -0,0 +1,3 @@ +FROM elasticsearch:7.17.14 + +RUN yes | bin/elasticsearch-plugin install repository-s3 diff --git a/deployment/concierge-graphql.yaml b/deployment/concierge-graphql.yaml new file mode 100644 index 0000000..e5bf9d7 --- /dev/null +++ b/deployment/concierge-graphql.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + service: concierge-graphql + stack: concierge-graphql + name: concierge-graphql +spec: + ports: + - name: webapp + port: 9000 + targetPort: 9000 + selector: + service: concierge-graphql + stack: concierge-graphql +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + service: concierge-graphql + stack: concierge-graphql + name: concierge-graphql +spec: + replicas: 1 + revisionHistoryLimit: 5 + selector: + matchLabels: + service: concierge-graphql + stack: concierge-graphql + template: + metadata: + labels: + service: concierge-graphql + stack: concierge-graphql + spec: + containers: + - name: concierge-graphql + image: ghcr.io/guardian/concierge-graphql/concierge-graphql:3 + env: + - name: ELASTICSEARCH_HOST + value: capi-elasticsearch + ports: + - containerPort: 9000 + readinessProbe: + httpGet: + path: /healthcheck + port: 9000 + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /healthcheck + port: 9000 + initialDelaySeconds: 15 + periodSeconds: 3 + diff --git a/deployment/elasticsearch.yaml b/deployment/elasticsearch.yaml new file mode 100644 index 0000000..29f5522 --- /dev/null +++ b/deployment/elasticsearch.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert + kompose.version: 1.19.0 (f63a961c) + creationTimestamp: null + labels: + io.kompose.service: capi-elasticsearch + name: capi-elasticsearch +spec: + type: NodePort + ports: + - name: '9200' + port: 9200 + targetPort: 9200 + - name: '9300' + port: 9300 + targetPort: 9300 + selector: + service: elasticsearch + stack: concierge-graphql +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + service: elasticsearch + stack: concierge-graphql + name: capi-elasticsearch +spec: + replicas: 1 + selector: + matchLabels: + service: elasticsearch + stack: concierge-graphql + serviceName: capi-elasticsearch + template: + metadata: + labels: + service: elasticsearch + stack: concierge-graphql + name: capi-elasticsearch + spec: + #initContainers: + #- image: elasticsearch:7.17.14 + # name: install-plugins + # command: + # - bin/elasticsearch-plugin + # - install + # - repository-s3 + containers: + - env: + - name: ES_JAVA_OPTS + value: -Xmx2048m -Xms2048m + - name: discovery.type + value: single-node + image: andyg42/elasticsearch-with-s3snap:7.17.14 + name: capi-elasticsearch + ports: + - containerPort: 9200 + - containerPort: 9300 + volumeMounts: + - mountPath: /usr/share/elasticsearch/data + name: esdata + volumeClaimTemplates: + - metadata: + name: esdata + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 80Gi + diff --git a/deployment/graphiql-explorer.yaml b/deployment/graphiql-explorer.yaml new file mode 100644 index 0000000..ba50cb6 --- /dev/null +++ b/deployment/graphiql-explorer.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + service: graphiql-server + stack: graphiql-server + name: graphiql-server +spec: + ports: + - name: webapp + port: 9000 + targetPort: 9000 + selector: + service: graphiql-server + stack: graphiql-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + service: graphiql-server + stack: graphiql-server + name: graphiql-server +spec: + replicas: 1 + revisionHistoryLimit: 5 + selector: + matchLabels: + service: graphiql-server + stack: graphiql-server + template: + metadata: + labels: + service: graphiql-server + stack: graphiql-server + spec: + containers: + - name: graphiql-server + image: ghcr.io/guardian/concierge-graphql/graphiql-server:3 + ports: + - containerPort: 9000 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 2 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 3 \ No newline at end of file diff --git a/deployment/ingress.yaml b/deployment/ingress.yaml new file mode 100644 index 0000000..eeb2bb8 --- /dev/null +++ b/deployment/ingress.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: concierge-graphql-ingress +spec: + rules: + - host: concierge-graphql.test + http: + paths: + - path: /query + pathType: Prefix + backend: + service: + name: concierge-graphql + port: + number: 9000 + - path: / + pathType: Prefix + backend: + service: + name: graphiql-explorer + port: + number: 80 \ No newline at end of file diff --git a/explorer/Dockerfile b/explorer/Dockerfile new file mode 100644 index 0000000..87ea44b --- /dev/null +++ b/explorer/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:mainline-alpine + +COPY build/* /usr/share/nginx/html \ No newline at end of file diff --git a/explorer/buildit.sh b/explorer/buildit.sh new file mode 100755 index 0000000..d132df2 --- /dev/null +++ b/explorer/buildit.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +if [ -d build/ ]; then + rm -rf build +fi + +yarn --frozen-lockfile +yarn run build +docker build . -t graphiql-explorer:DEV \ No newline at end of file diff --git a/explorer/src/main.tsx b/explorer/src/main.tsx index fa32eda..54294e1 100644 --- a/explorer/src/main.tsx +++ b/explorer/src/main.tsx @@ -5,7 +5,7 @@ import ReactDOM from 'react-dom'; import 'graphiql/graphiql.css'; -const fetcher = createGraphiQLFetcher({ url: 'http://localhost:9000/query', headers: {'X-Consumer-Username': ":internal"} }); +const fetcher = createGraphiQLFetcher({ url: "/query", headers: {'X-Consumer-Username': ":internal"} }); const rootElem = document.createElement('div'); rootElem.setAttribute("style","height: 100vh");