From c842c4e83797bde68546198cb210d4deee8b148a Mon Sep 17 00:00:00 2001 From: Conrad Taylor Date: Sat, 11 Dec 2021 23:06:08 -0800 Subject: [PATCH 1/3] WIP: add create person mutation. --- .../schema/mutation/create_person_test.exs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 test/zero_phoenix_web/schema/mutation/create_person_test.exs diff --git a/test/zero_phoenix_web/schema/mutation/create_person_test.exs b/test/zero_phoenix_web/schema/mutation/create_person_test.exs new file mode 100644 index 0000000..d7e5091 --- /dev/null +++ b/test/zero_phoenix_web/schema/mutation/create_person_test.exs @@ -0,0 +1,51 @@ +defmodule ZeroPhoenixWeb.Schema.Query.CreatePersonTest do + use ZeroPhoenixWeb.ConnCase, async: true + + import Ecto.Query, only: [first: 1] + + alias ZeroPhoenix.Account.Person + alias ZeroPhoenix.Repo + + setup do + ZeroPhoenix.Seeds.run() + end + + test "create person" do + query = """ + mutation CreatePerson($person: Person!) { + createPerson(person: $person) { + firstName + lastName + email + userName + } + } + """ + + variables = %{ + "firstName" => "Jane", + "lastName" => "Doe", + "email" => "jane@example.com", + "username" => "janed" + } + + response = + post( + build_conn(), + "/graphql", + query: query, + variables: variables + ) + + assert json_response(response, 200) == %{ + "data" => %{ + "createPerson" => %{ + "firstName" => "Jane", + "lastName" => "Doe", + "email" => "jane@example.com", + "username" => "janed" + } + } + } + end +end From e525caff409b8514d6e11b1ab834e5f99118419b Mon Sep 17 00:00:00 2001 From: Conrad Taylor Date: Sat, 11 Dec 2021 23:09:53 -0800 Subject: [PATCH 2/3] Code cleanup. --- .iex.exs | 0 ACTIONS.md | 24 ++++ APOLLO.md | 3 + Dockerfile.sample | 131 ++++++++++++++++++ PRODUCTION-DEPLOYMENT.md | 7 + README-CURL-EXAMPLE.md | 6 + docker-compose.debug.yml | 10 ++ docker-compose.yml.sample | 60 ++++++++ schema.graphql | 29 ++++ .../schema/mutation/create_person_test.exs | 10 +- 10 files changed, 275 insertions(+), 5 deletions(-) create mode 100644 .iex.exs create mode 100644 ACTIONS.md create mode 100644 APOLLO.md create mode 100644 Dockerfile.sample create mode 100644 PRODUCTION-DEPLOYMENT.md create mode 100644 README-CURL-EXAMPLE.md create mode 100644 docker-compose.debug.yml create mode 100644 docker-compose.yml.sample create mode 100644 schema.graphql diff --git a/.iex.exs b/.iex.exs new file mode 100644 index 0000000..e69de29 diff --git a/ACTIONS.md b/ACTIONS.md new file mode 100644 index 0000000..6b902bd --- /dev/null +++ b/ACTIONS.md @@ -0,0 +1,24 @@ +# Let's set up GitHub Actions on our Phoenix app (with Jonathan Clem) + +https://changelog.com/podcast/331 +https://github.com/thechangelog/changelog.com + +## Actions + +https://docs.github.com/en/actions +https://github.com/actions/checkout +https://github.com/actions/cache +https://github.com/actions/github-script + +## Github Community + +https://github.community + +## Twitter Contact + +https://twitter.com/_clem +https://twitter.com/jerodsanto + +## References + +- https://www.youtube.com/watch?v=tiXMPCfZfag diff --git a/APOLLO.md b/APOLLO.md new file mode 100644 index 0000000..ddf6b80 --- /dev/null +++ b/APOLLO.md @@ -0,0 +1,3 @@ +APOLLO_KEY=service:Zero-Phoenix:RLA67gv0rVOE7cyq-H0zxA +APOLLO_GRAPH_VARIANT=current +APOLLO_SCHEMA_REPORTING=true diff --git a/Dockerfile.sample b/Dockerfile.sample new file mode 100644 index 0000000..495679b --- /dev/null +++ b/Dockerfile.sample @@ -0,0 +1,131 @@ +## +## Base +## + +FROM ruby:3.0.2-alpine3.14 as base + +# labels from https://github.com/opencontainers/image-spec/blob/master/annotations.md +LABEL org.opencontainers.image.authors=conradwt@gmail.com +LABEL org.opencontainers.image.created=$CREATED_DATE +LABEL org.opencontainers.image.revision=$SOURCE_COMMIT +LABEL org.opencontainers.image.title="Zero To GraphQL Using Rails" +LABEL org.opencontainers.image.url=https://hub.docker.com/u/conradwt/zero-rails +LABEL org.opencontainers.image.source=https://github.com/conradwt/zero-to-graphql-using-rails +LABEL org.opencontainers.image.licenses=MIT +LABEL com.conradtaylor.ruby_version=$RUBY_VERSION + +# set this with shell variables at build-time. +# If they aren't set, then not-set will be default. +ARG CREATED_DATE=not-set +ARG SOURCE_COMMIT=not-set + +# environment variables +ENV APP_PATH /app +ENV BUNDLE_PATH /usr/local/bundle/gems +ENV TMP_PATH /tmp/ +ENV RAILS_LOG_TO_STDOUT true +ENV RAILS_PORT 3000 + +# create application user. +RUN addgroup --gid 1000 darnoc \ + && adduser --uid 1000 --ingroup darnoc --shell /bin/bash --home darnoc + +# copy entrypoint scripts and grant execution permissions +# COPY ./dev-docker-entrypoint.sh /usr/local/bin/dev-entrypoint.sh +# COPY ./test-docker-entrypoint.sh /usr/local/bin/test-entrypoint.sh +# RUN chmod +x /usr/local/bin/dev-entrypoint.sh && chmod +x /usr/local/bin/test-entrypoint.sh + +# +# https://pkgs.alpinelinux.org/packages?name=&branch=v3.13 +# + +# install build and runtime dependencies +RUN apk -U add --no-cache \ + build-base=0.5-r2 \ + bzip2=1.0.8-r1 \ + ca-certificates=20191127-r5 \ + curl=7.78.0-r0 \ + fontconfig=2.13.1-r4 \ + postgresql-dev=13.4-r0 \ + tini=0.19.0-r0 \ + tzdata=2021a-r0 && \ + rm -rf /var/cache/apk/* && \ + mkdir -p $APP_PATH + +ENV RAILS_ENV=production + +EXPOSE ${RAILS_PORT} +ENV PORT ${RAILS_PORT} + +WORKDIR ${APP_PATH} + +COPY Gemfile* ./ + +RUN gem install bundler && \ + rm -rf ${GEM_HOME}/cache/* +RUN bundle config set without 'development test' +RUN bundle check || bundle install --jobs 20 --retry 5 + +ENTRYPOINT ["/sbin/tini", "--"] + +# Why should this go into `base` instead of `prod` stage? +# CMD ["rails", "server", "-b", "0.0.0.0", "-e", "production"] + +## +## Development +## + +FROM base as dev + +ENV RAILS_ENV=development + +# RUN bundle config list +RUN bundle config --delete without +RUN bundle config --delete with +RUN bundle check || bundle install --jobs 20 --retry 5 + +# uninstall our build dependencies +# RUN apk del build-dependencies + +# Add a script to be executed every time the container starts. +# COPY entrypoint.sh /usr/bin/ +# RUN chmod +x /usr/bin/entrypoint.sh +# ENTRYPOINT ["entrypoint.sh"] + +USER darnoc + +CMD ["rails", "server", "-b", "0.0.0.0"] + +## +## Test +## + +FROM dev as test + +COPY . . + +RUN bundle exec rspec + +## +## Pre-Production +## + +FROM test as pre-prod + +USER root + +RUN rm -rf ./spec + +## +## Production +## + +FROM base as prod + +COPY --from=pre-prod /app /app + +HEALTHCHECK CMD curl http://127.0.0.1/ || exit 1 + +USER darnoc + +CMD ["rails", "server", "-b", "0.0.0.0", "-e", "production"] diff --git a/PRODUCTION-DEPLOYMENT.md b/PRODUCTION-DEPLOYMENT.md new file mode 100644 index 0000000..c2bb641 --- /dev/null +++ b/PRODUCTION-DEPLOYMENT.md @@ -0,0 +1,7 @@ +# Production Deployment + +## References + +- https://hexdocs.pm/phoenix/releases.html#runtime-configuration + +- https://hexdocs.pm/phoenix/releases.html#containers diff --git a/README-CURL-EXAMPLE.md b/README-CURL-EXAMPLE.md new file mode 100644 index 0000000..674dfd7 --- /dev/null +++ b/README-CURL-EXAMPLE.md @@ -0,0 +1,6 @@ +curl \ + -i \ + --request POST \ + --url http://localhost:4000/graphql \ + -H "Content-Type: application/json" \ + --data '{"query":"query ExampleQuery($personId: ID!) {\n person(id: $personId) {\n email\n }\n}","variables":"{\n \"personId\": \"1\"\n}"}' diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml new file mode 100644 index 0000000..b475b10 --- /dev/null +++ b/docker-compose.debug.yml @@ -0,0 +1,10 @@ +version: '2.1' + +services: + zero-to-graphql-using-phoenix: + image: zero-to-graphql-using-phoenix + build: + context: . + dockerfile: Dockerfile + ports: + - 4000:4000 \ No newline at end of file diff --git a/docker-compose.yml.sample b/docker-compose.yml.sample new file mode 100644 index 0000000..1ab7779 --- /dev/null +++ b/docker-compose.yml.sample @@ -0,0 +1,60 @@ +# https://docs.docker.com/compose/rails/ + +services: + app: + build: + context: . + dockerfile: Dockerfile + target: dev + + container_name: zero_rails + + command: ['rails', 'server', '-p', '3000', '-b', '0.0.0.0'] + + environment: + - RAILS_ENV=development + + ports: + - 3000:3000 + + stdin_open: true + + tty: true + + env_file: .env.development + + entrypoint: dev-entrypoint.sh + + volumes: + - .:/app + - shared_data:/var/shared + - gem_cache:/usr/local/bundle/gems + + depends_on: + db: + condition: service_healthy + + db: + image: postgres:13.2-alpine + + hostname: localhost + + volumes: + - db_data:/var/lib/postgresql/data + - shared_data:/var/shared + + environment: + - POSTGRES_HOST_AUTH_METHOD=trust + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=password + + ports: + - 5432:5432 + + healthcheck: + test: pg_isready -U postgres -h 127.0.0.1 + +volumes: + db_data: {} + gem_cache: {} + shared_data: {} diff --git a/schema.graphql b/schema.graphql new file mode 100644 index 0000000..9ee783e --- /dev/null +++ b/schema.graphql @@ -0,0 +1,29 @@ +"Represents a schema" +schema { + query: RootQueryType +} + +"a person" +type Person { + "unique identifier for the person" + id: String! + + "first name of a person" + firstName: String! + + "last name of a person" + lastName: String! + + "username of a person" + username: String! + + "email of a person" + email: String! + + "a list of friends for our person" + friends: [Person] +} + +type RootQueryType { + person(id: ID!): Person +} diff --git a/test/zero_phoenix_web/schema/mutation/create_person_test.exs b/test/zero_phoenix_web/schema/mutation/create_person_test.exs index d7e5091..86be3ea 100644 --- a/test/zero_phoenix_web/schema/mutation/create_person_test.exs +++ b/test/zero_phoenix_web/schema/mutation/create_person_test.exs @@ -23,11 +23,11 @@ defmodule ZeroPhoenixWeb.Schema.Query.CreatePersonTest do """ variables = %{ - "firstName" => "Jane", - "lastName" => "Doe", - "email" => "jane@example.com", - "username" => "janed" - } + "firstName" => "Jane", + "lastName" => "Doe", + "email" => "jane@example.com", + "username" => "janed" + } response = post( From 02af2d8be84eb3b1816153849b2657c66e833a82 Mon Sep 17 00:00:00 2001 From: Conrad Taylor Date: Fri, 14 Jan 2022 01:19:33 -0800 Subject: [PATCH 3/3] Upgrade to Elixir 1.13.2. --- README.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c48508..e5d2a27 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The purpose of this example is to provide details as to how one would go about u ## Software requirements -- Elixir 1.13.1 or newer +- Elixir 1.13.2 or newer - Erlang 24.2 or newer diff --git a/mix.exs b/mix.exs index e3405ce..e01f5ff 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule ZeroPhoenix.Mixfile do [ app: :zero_phoenix, version: "3.3.4", - elixir: "~> 1.13.1", + elixir: "~> 1.13.2", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:gettext] ++ Mix.compilers(), start_permanent: Mix.env() == :prod,