parent
497f494ef3
commit
12e37330c7
6 changed files with 356 additions and 0 deletions
92
.github/workflows/uffizzi-build.yml
vendored
Normal file
92
.github/workflows/uffizzi-build.yml
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
name: Build PR Image
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
|
||||
jobs:
|
||||
build-application:
|
||||
name: Build and Push `Forem`
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||
outputs:
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
steps:
|
||||
- name: Checkout git repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Generate UUID image name
|
||||
id: uuid
|
||||
run: echo "UUID_TAG_APP=$(uuidgen)" >> $GITHUB_ENV
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
|
||||
tags: type=raw,value=60d
|
||||
- uses: actions/checkout@master
|
||||
- name: Create the .env file
|
||||
run: |
|
||||
cp .env.test .env
|
||||
- name: Build and Push Image to registry.uffizzi.com ephemeral registry
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
context: .
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
file: ./uffizzi/Dockerfile
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
render-compose-file:
|
||||
name: Render Docker Compose File
|
||||
# Pass output of this workflow to another triggered by `workflow_run` event.
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-application
|
||||
outputs:
|
||||
compose-file-cache-key: ${{ steps.hash.outputs.hash }}
|
||||
steps:
|
||||
- name: Checkout git repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Render Compose File
|
||||
run: |
|
||||
APP_IMAGE=$(echo ${{ needs.build-application.outputs.tags }})
|
||||
export APP_IMAGE
|
||||
# Render simple template from environment variables.
|
||||
envsubst < ./uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml
|
||||
cat docker-compose.rendered.yml
|
||||
- name: Upload Rendered Compose File as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: docker-compose.rendered.yml
|
||||
retention-days: 2
|
||||
- name: Serialize PR Event to File
|
||||
run: |
|
||||
cat << EOF > event.json
|
||||
${{ toJSON(github.event) }}
|
||||
|
||||
EOF
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: event.json
|
||||
retention-days: 2
|
||||
|
||||
delete-preview:
|
||||
name: Call for Preview Deletion
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.action == 'closed' }}
|
||||
steps:
|
||||
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
|
||||
- name: Serialize PR Event to File
|
||||
run: echo '${{ toJSON(github.event) }}' > event.json
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: event.json
|
||||
retention-days: 2
|
||||
84
.github/workflows/uffizzi-preview.yml
vendored
Normal file
84
.github/workflows/uffizzi-preview.yml
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
name: Deploy Uffizzi Preview
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows:
|
||||
- "Build PR Image"
|
||||
types:
|
||||
- completed
|
||||
|
||||
|
||||
jobs:
|
||||
cache-compose-file:
|
||||
name: Cache Compose File
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
compose-file-cache-key: ${{ env.COMPOSE_FILE_HASH }}
|
||||
pr-number: ${{ env.PR_NUMBER }}
|
||||
steps:
|
||||
- name: 'Download artifacts'
|
||||
# Fetch output (zip archive) from the workflow run that triggered this workflow.
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "preview-spec"
|
||||
})[0];
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
let fs = require('fs');
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
|
||||
- name: 'Unzip artifact'
|
||||
run: unzip preview-spec.zip
|
||||
- name: Read Event into ENV
|
||||
run: |
|
||||
echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
|
||||
cat event.json >> $GITHUB_ENV
|
||||
echo 'EOF' >> $GITHUB_ENV
|
||||
- name: Hash Rendered Compose File
|
||||
id: hash
|
||||
# If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
|
||||
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
|
||||
run: echo "COMPOSE_FILE_HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||
- name: Cache Rendered Compose File
|
||||
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: docker-compose.rendered.yml
|
||||
key: ${{ env.COMPOSE_FILE_HASH }}
|
||||
|
||||
- name: Read PR Number From Event Object
|
||||
id: pr
|
||||
run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
|
||||
|
||||
- name: DEBUG - Print Job Outputs
|
||||
if: ${{ runner.debug }}
|
||||
run: |
|
||||
echo "PR number: ${{ env.PR_NUMBER }}"
|
||||
echo "Compose file hash: ${{ env.COMPOSE_FILE_HASH }}"
|
||||
cat event.json
|
||||
deploy-uffizzi-preview:
|
||||
name: Use Remote Workflow to Preview on Uffizzi
|
||||
needs:
|
||||
- cache-compose-file
|
||||
uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2.6.1
|
||||
with:
|
||||
# If this workflow was triggered by a PR close event, cache-key will be an empty string
|
||||
# and this reusable workflow will delete the preview deployment.
|
||||
compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
|
||||
compose-file-cache-path: docker-compose.rendered.yml
|
||||
server: https://app.uffizzi.com
|
||||
pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
|
|
@ -87,6 +87,9 @@ Rails.application.configure do
|
|||
if (gitpod_workspace_url = ENV.fetch("GITPOD_WORKSPACE_URL", nil))
|
||||
config.hosts << /.*#{URI.parse(gitpod_workspace_url).host}/
|
||||
end
|
||||
if (uffizzi_url = ENV.fetch("UFFIZZI_URL", nil))
|
||||
config.hosts << /.*#{URI.parse(uffizzi_url).host}/
|
||||
end
|
||||
config.app_domain = ENV.fetch("APP_DOMAIN", "localhost:3000")
|
||||
|
||||
config.action_mailer.delivery_method = :smtp
|
||||
|
|
|
|||
83
uffizzi/Dockerfile
Normal file
83
uffizzi/Dockerfile
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
FROM quay.io/forem/ruby:3.0.2 as base
|
||||
|
||||
FROM base as builder
|
||||
|
||||
USER root
|
||||
|
||||
RUN curl -sL https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo && \
|
||||
dnf install --setopt install_weak_deps=false -y \
|
||||
ImageMagick iproute jemalloc less libcurl libcurl-devel \
|
||||
libffi-devel libxml2-devel libxslt-devel nodejs pcre-devel \
|
||||
postgresql postgresql-devel tzdata yarn && \
|
||||
dnf -y clean all && \
|
||||
rm -rf /var/cache/yum
|
||||
|
||||
ENV BUNDLER_VERSION=2.2.22 BUNDLE_SILENCE_ROOT_WARNING=true BUNDLE_SILENCE_DEPRECATIONS=true
|
||||
RUN gem install -N bundler:"${BUNDLER_VERSION}"
|
||||
|
||||
ENV APP_USER=forem APP_UID=1000 APP_GID=1000 APP_HOME=/opt/apps/forem \
|
||||
LD_PRELOAD=/usr/lib64/libjemalloc.so.2
|
||||
RUN mkdir -p ${APP_HOME} && chown "${APP_UID}":"${APP_GID}" "${APP_HOME}" && \
|
||||
groupadd -g "${APP_GID}" "${APP_USER}" && \
|
||||
adduser -u "${APP_UID}" -g "${APP_GID}" -d "${APP_HOME}" "${APP_USER}"
|
||||
|
||||
ENV DOCKERIZE_VERSION=v0.6.1
|
||||
RUN wget https://github.com/jwilder/dockerize/releases/download/"${DOCKERIZE_VERSION}"/dockerize-linux-amd64-"${DOCKERIZE_VERSION}".tar.gz \
|
||||
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-"${DOCKERIZE_VERSION}".tar.gz \
|
||||
&& rm dockerize-linux-amd64-"${DOCKERIZE_VERSION}".tar.gz \
|
||||
&& chown root:root /usr/local/bin/dockerize
|
||||
|
||||
WORKDIR "${APP_HOME}"
|
||||
|
||||
COPY ./.ruby-version "${APP_HOME}"/
|
||||
COPY ./Gemfile ./Gemfile.lock "${APP_HOME}"/
|
||||
COPY ./vendor/cache "${APP_HOME}"/vendor/cache
|
||||
|
||||
RUN bundle config --local build.sassc --disable-march-tune-native && \
|
||||
BUNDLE_WITHOUT="development:test" bundle install --deployment --jobs 4 --retry 5 && \
|
||||
find "${APP_HOME}"/vendor/bundle -name "*.c" -delete && \
|
||||
find "${APP_HOME}"/vendor/bundle -name "*.o" -delete
|
||||
|
||||
COPY . "${APP_HOME}"
|
||||
|
||||
RUN mkdir -p "${APP_HOME}"/public/{assets,images,packs,podcasts,uploads}
|
||||
|
||||
RUN NODE_ENV=production yarn install
|
||||
|
||||
RUN RAILS_ENV=production NODE_ENV=production bundle exec rake assets:precompile
|
||||
|
||||
RUN echo $(date -u +'%Y-%m-%dT%H:%M:%SZ') >> "${APP_HOME}"/FOREM_BUILD_DATE && \
|
||||
echo $(git rev-parse --short HEAD) >> "${APP_HOME}"/FOREM_BUILD_SHA && \
|
||||
rm -rf "${APP_HOME}"/.git/
|
||||
|
||||
RUN rm -rf node_modules vendor/assets spec
|
||||
|
||||
## Development
|
||||
FROM builder AS development
|
||||
|
||||
COPY --chown="${APP_USER}":"${APP_USER}" ./spec "${APP_HOME}"/spec
|
||||
COPY --from=builder /usr/local/bin/dockerize /usr/local/bin/dockerize
|
||||
|
||||
RUN chown "${APP_USER}":"${APP_USER}" -R "${APP_HOME}"
|
||||
|
||||
USER "${APP_USER}"
|
||||
|
||||
RUN bundle config --local build.sassc --disable-march-tune-native && \
|
||||
bundle config --delete without && \
|
||||
bundle install --deployment --jobs 4 --retry 5 && \
|
||||
find "${APP_HOME}"/vendor/bundle -name "*.c" -delete && \
|
||||
find "${APP_HOME}"/vendor/bundle -name "*.o" -delete
|
||||
|
||||
# Replcament for volume
|
||||
COPY --from=builder --chown="${APP_USER}":"${APP_USER}" ${APP_HOME} ${APP_HOME}
|
||||
# husky install / fatal: not a git repository (or any of the parent directories): .git
|
||||
COPY --chown="${APP_USER}":"${APP_USER}" .git/ "${APP_HOME}/.git/"
|
||||
## Bund install
|
||||
RUN ./scripts/bundle.sh
|
||||
## Yarn install
|
||||
RUN bash -c yarn install --dev
|
||||
|
||||
|
||||
ENTRYPOINT ["./scripts/entrypoint.sh"]
|
||||
|
||||
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "3000"]
|
||||
5
uffizzi/db_seed.sh
Executable file
5
uffizzi/db_seed.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
bundle exec rake db:seed
|
||||
|
||||
tail -f /dev/null
|
||||
89
uffizzi/docker-compose.uffizzi.yml
Normal file
89
uffizzi/docker-compose.uffizzi.yml
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
version: "3"
|
||||
|
||||
x-uffizzi:
|
||||
ingress:
|
||||
service: rails
|
||||
port: 3000
|
||||
|
||||
services:
|
||||
rails:
|
||||
image: "${APP_IMAGE}"
|
||||
container_name: forem_rails
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
DATABASE_URL: postgresql://forem:forem@localhost:5432/PracticalDeveloper_development
|
||||
REDIS_SESSIONS_URL: redis://localhost:6379
|
||||
REDIS_SIDEKIQ_URL: redis://localhost:6379
|
||||
REDIS_URL: redis://localhost:6379
|
||||
RACK_TIMEOUT_WAIT_TIMEOUT: 10000
|
||||
RACK_TIMEOUT_SERVICE_TIMEOUT: 10000
|
||||
STATEMENT_TIMEOUT: 10000
|
||||
APP_DOMAIN: localhost:3000
|
||||
APP_PROTOCOL: https://
|
||||
entrypoint: ["dockerize", "-wait", "tcp://localhost:5432", "-wait", "tcp://localhost:6379", "-wait", "file:///opt/apps/forem/vendor/bundle/.bundle_finished", "-timeout", "5400s"]
|
||||
command: [ "bash", "-c", "./scripts/entrypoint.sh bootstrap && bundle exec rails server -b 0.0.0.0 -p 3000"]
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 4000M
|
||||
|
||||
seed:
|
||||
image: "${APP_IMAGE}"
|
||||
container_name: forem_seed
|
||||
depends_on:
|
||||
- rails
|
||||
- redis
|
||||
- db
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
REDIS_SESSIONS_URL: redis://localhost:6379
|
||||
REDIS_SIDEKIQ_URL: redis://localhost:6379
|
||||
REDIS_URL: redis://localhost:6379
|
||||
DATABASE_URL: postgresql://forem:forem@localhost:5432/PracticalDeveloper_development
|
||||
entrypoint: ["dockerize", "-wait", "tcp://localhost:5432", "-wait", "tcp://localhost:6379", "-wait", "http://localhost:3000", "-timeout", "5400s"]
|
||||
command: ["./uffizzi/db_seed.sh"]
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 500M
|
||||
|
||||
sidekiq:
|
||||
image: "${APP_IMAGE}"
|
||||
container_name: forem_sidekiq
|
||||
depends_on:
|
||||
- rails
|
||||
- redis
|
||||
- db
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
REDIS_SESSIONS_URL: redis://localhost:6379
|
||||
REDIS_SIDEKIQ_URL: redis://localhost:6379
|
||||
REDIS_URL: redis://localhost:6379
|
||||
DATABASE_URL: postgresql://forem:forem@localhost:5432/PracticalDeveloper_development
|
||||
entrypoint: ["dockerize", "-wait", "tcp://localhost:5432", "-wait", "tcp://localhost:6379", "-wait", "http://localhost:3000", "-timeout", "5400s"]
|
||||
command: ["bundle", "exec", "sidekiq","-c","2"]
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 500M
|
||||
|
||||
db:
|
||||
image: postgres:11-alpine
|
||||
container_name: forem_postgresql
|
||||
environment:
|
||||
POSTGRES_USER: forem
|
||||
POSTGRES_PASSWORD: forem
|
||||
POSTGRES_DB: PracticalDeveloper_development
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:6.0.9-alpine
|
||||
container_name: forem_redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
Loading…
Add table
Reference in a new issue