Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare connector for deployment #2

Merged
merged 3 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
12 changes: 12 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"privatePackages": { "version": true, "tag": true }
}
42 changes: 42 additions & 0 deletions .github/workflows/changesets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: changesets

on:
push:
branches:
- main

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js 20
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
with:
node-version: lts/*

- name: Install Dependencies
run: npm install

- name: Configure git
run: |
git config --global user.name 'Neo4j Team GraphQL'
git config --global user.email '[email protected]'

- name: Create Release Pull Request
uses: changesets/action@aba318e9165b45b7948c60273e0b72fce0a64eb9 # v1.4.7
with:
title: changesets for branch `${{ github.ref_name }}`
version: npm run changeset-version
publish: npm run release
setupGitUser: false
env:
GITHUB_TOKEN: ${{ secrets.TEAM_GRAPHQL_PERSONAL_ACCESS_TOKEN }}
49 changes: 49 additions & 0 deletions .github/workflows/dryrun.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Example modified from https://docs.github.com/en/actions/publishing-packages/publishing-docker-images
name: Builds a Docker image

# Configures this workflow to run every time a change is pushed to selected tags and branches
on:
pull_request:
branches:
- main
paths:
- "**/CHANGELOG.md"

# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
dry-run:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.TEAM_GRAPHQL_USERNAME }}
password: ${{ secrets.TEAM_GRAPHQL_PERSONAL_ACCESS_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
95 changes: 95 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Example modified from https://docs.github.com/en/actions/publishing-packages/publishing-docker-images
name: Create and publish a Docker image

# Configures this workflow to run on release
on:
push:
tags:
- "*"

# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.TEAM_GRAPHQL_USERNAME }}
password: ${{ secrets.TEAM_GRAPHQL_PERSONAL_ACCESS_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build connector definition
run: |
set -e pipefail
export DOCKER_IMAGE=$(echo "$DOCKER_METADATA_OUTPUT_JSON" | jq -r '.tags[0]')
make build
working-directory: ./connector-definition
- uses: actions/upload-artifact@v4
with:
name: connector-definition.tgz
path: ./connector-definition/dist/connector-definition.tgz
compression-level: 0 # Already compressed

release-connector:
name: Release connector
runs-on: ubuntu-latest
needs: build-and-push-image
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: connector-definition.tgz
path: ./connector-definition/dist
- name: Upload connector artefact to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.TEAM_GRAPHQL_PERSONAL_ACCESS_TOKEN }}
file: ./connector-definition/dist/connector-definition.tgz
asset_name: connector-definition.tgz
tag: ${{ github.ref }}
# - name: Get version from tag
# id: get-version
# run: |
# echo "tagged_version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
# shell: bash
# - uses: mindsers/changelog-reader-action@v2
# id: changelog-reader
# with:
# version: ${{ steps.get-version.outputs.tagged_version }}
# path: ./CHANGELOG.md
# - uses: softprops/action-gh-release@v1
# with:
# draft: false
# tag_name: v${{ steps.get-version.outputs.tagged_version }}
# body: ${{ steps.changelog-reader.outputs.changes }}
# files: |
# ./connector-definition/dist/connector-definition.tgz
# fail_on_unmatched_files: true
31 changes: 22 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Use Node.js 18 as the base image
FROM node:18 AS build-stage
# Use Node.js 20 as the base image for both build and production stages
FROM node:20 AS build-stage

# Set the working directory inside the container
# Set the working directory inside the container for the build stage
WORKDIR /usr/src/app

# Copy package.json and package-lock.json (if you have one) to the working directory
# Copy package.json and package-lock.json (if available) to the working directory
COPY package*.json ./

# Install both production and development dependencies
RUN npm install

# Install TypeScript globally
RUN npm install -g typescript

# Copy the entire project
Expand All @@ -19,8 +20,9 @@ COPY . .
RUN tsc

# Start a new stage for the production environment
FROM node:18 AS production
FROM node:20 AS production

# Set working directory for the production stage
WORKDIR /usr/src/app

# Copy package.json and package-lock.json to the working directory
Expand All @@ -29,10 +31,21 @@ COPY package*.json ./
# Install only production dependencies
RUN npm ci --only=production

# Copy compiled JavaScript from the previous stage
# Copy compiled JavaScript from the build stage
COPY --from=build-stage /usr/src/app/dist ./dist

EXPOSE 8100
# Define the environment variable for configuration directory with a default value, which can be overridden
ENV HASURA_CONFIGURATION_DIRECTORY=/etc/connector

# Define the command to run the app using CMD
CMD ["node", "./dist/src/index.js", "serve", "--configuration=/etc/connector/config.json"]
# Set the default port environment variable and allow it to be overridden
ENV HASURA_CONNECTOR_PORT=8080

# Expose the port specified by the HASURA_CONNECTOR_PORT environment variable
EXPOSE $HASURA_CONNECTOR_PORT

# Copy the entrypoint script into the container and make it executable
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# Use the entrypoint script to handle startup and signal trapping
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
32 changes: 13 additions & 19 deletions cli.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Command } from "@commander-js/extra-typings";
import { readFileSync, writeFileSync } from "fs";
import { writeFile } from "fs/promises";
import path from "path";
import { doUpdateConfiguration } from "./src/handlers/updateConfiguration";
import { Neo4j } from "./src/neo4j";
import {
CONFIGURATION_FILE_NAME,
syncConfigurationFile,
} from "./src/connector-config/syncConfigurationFile";
const program = new Command();

program
Expand All @@ -13,14 +15,17 @@ program
program
.command("initialize")
.description("Initialize a configuration file for the Neo4j connector")
.option("--context <fileName>", "context")
.action((str) => {
.option("--context <directoryName>", "context")
.action(async (str) => {
const emptyConfig = {
typedefs: undefined,
};
console.log(emptyConfig);
if (str.context) {
writeFileSync(path.resolve(str.context), JSON.stringify(emptyConfig));
await writeFile(
path.resolve(str.context, CONFIGURATION_FILE_NAME),
JSON.stringify(emptyConfig)
);
}
});

Expand All @@ -29,22 +34,11 @@ program
.description(
"Update the configuration file for the Neo4j connector by introspecting the DB"
)
.option("--context <fileName>", "context")
.option("--context <directoryName>", "context")
.action(async (str) => {
if (str.context) {
console.log("str", str.context, program.args[0]);
try {
const prevConfig = JSON.parse(
readFileSync(path.resolve(str.context), "utf8")
);

const updatedConfig = await doUpdateConfiguration(prevConfig);
writeFileSync(path.resolve(str.context), JSON.stringify(updatedConfig));
} catch (error) {
console.error("Failed to update configuration:", error);
} finally {
await Neo4j.getInstance().cleanDriver();
}
await syncConfigurationFile(str.context);
}
});

Expand Down
21 changes: 21 additions & 0 deletions connector-definition/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.DEFAULT_GOAL := build
SHELL = /usr/bin/env bash

.PHONY: build
build: dist/connector-definition.tgz

.PHONY: clean
clean:
rm -rf dist

dist dist/.hasura-connector:
mkdir dist
mkdir dist/.hasura-connector

dist/.hasura-connector/connector-metadata.yaml: DOCKER_IMAGE ?= $(error The DOCKER_IMAGE variable must be defined)
dist/.hasura-connector/connector-metadata.yaml: connector-metadata.yaml dist/.hasura-connector
cp -f connector-metadata.yaml dist/.hasura-connector/
yq -i '.packagingDefinition.dockerImage = "$(DOCKER_IMAGE)"' dist/.hasura-connector/connector-metadata.yaml

dist/connector-definition.tgz: dist/.hasura-connector/connector-metadata.yaml
shopt -s dotglob && cd dist && tar -czvf connector-definition.tgz *
16 changes: 16 additions & 0 deletions connector-definition/connector-definition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
packagingDefinition:
type: PrebuiltDockerImage
dockerImage: ghcr.io/neo4j/ndc-connector-image:v0.0.1
supportedEnvironmentVariables:
- name: NEO4J_URL
description: The url for the Neo4j Database
- name: NEO4J_USER
description: The username for the Neo4j Database
- name: NEO4J_PASS
description: The password for the Neo4j Database
commands:
update: docker run --rm -e NEO4J_URL="$NEO4J_URL" -e NEO4J_USER="$NEO4J_USER" -e NEO4J_PASS="$NEO4J_PASS" -v "$HASURA_CONFIGURATION_DIRECTORY":/etc/connector ghcr.io/neo4j/ndc-connector-image:v0.0.1 update
dockerComposeWatch:
- path: ./
target: /etc/connector
action: sync+restart
7 changes: 7 additions & 0 deletions connector-definition/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
connector:
develop:
watch:
- path: ./
target: /etc/connector
action: sync+restart
Loading