Skip to content
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
Empty file added .iex.exs
Empty file.
24 changes: 24 additions & 0 deletions ACTIONS.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions APOLLO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
APOLLO_KEY=service:Zero-Phoenix:RLA67gv0rVOE7cyq-H0zxA
APOLLO_GRAPH_VARIANT=current
APOLLO_SCHEMA_REPORTING=true
131 changes: 131 additions & 0 deletions Dockerfile.sample
Original file line number Diff line number Diff line change
@@ -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"]
7 changes: 7 additions & 0 deletions PRODUCTION-DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Production Deployment

## References

- https://hexdocs.pm/phoenix/releases.html#runtime-configuration

- https://hexdocs.pm/phoenix/releases.html#containers
6 changes: 6 additions & 0 deletions README-CURL-EXAMPLE.md
Original file line number Diff line number Diff line change
@@ -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}"}'
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 10 additions & 0 deletions docker-compose.debug.yml
Original file line number Diff line number Diff line change
@@ -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
60 changes: 60 additions & 0 deletions docker-compose.yml.sample
Original file line number Diff line number Diff line change
@@ -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: {}
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
@@ -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
}
51 changes: 51 additions & 0 deletions test/zero_phoenix_web/schema/mutation/create_person_test.exs
Original file line number Diff line number Diff line change
@@ -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