diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 000000000..2149c7409 --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,60 @@ +name: Dev + +on: + push: + branches: [ develop ] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: standardnotes/web + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + tags: "latest,${{ github.sha }}" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Download task definition + run: | + aws ecs describe-task-definition --task-definition app-dev --query taskDefinition > task-definition.json + + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: task-definition.json + container-name: app-dev + image: "standardnotes/web:${{ github.sha }}" + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + service: app-dev + cluster: dev + wait-for-service-stability: true + + notify_slack: + needs: deploy + + runs-on: ubuntu-latest + + steps: + - name: Notify slack + uses: pullreminders/slack-action@master + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + args: '{ \"channel\": \"${{ secrets.SLACK_NOTIFICATION_CHANNEL }}\", \"blocks\": [{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Successfully deployed \"}}, {\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Changes: \"}, \"accessory\": {\"type\": \"image\", \"image_url\": \"https://website-dev.standardnotes.org/assets/icon.png\", \"alt_text\": \"Standard Notes\"}}, { \"type\": \"section\", \"fields\": [{\"type\": \"mrkdwn\", \"text\": \"\"}]}]}' diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml new file mode 100644 index 000000000..a5d24d67d --- /dev/null +++ b/.github/workflows/prod.yml @@ -0,0 +1,60 @@ +name: Prod + +on: + push: + branches: [ master ] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: standardnotes/web + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + tags: "stable,${{ github.sha }}" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Download task definition + run: | + aws ecs describe-task-definition --task-definition app-prod --query taskDefinition > task-definition.json + + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: task-definition.json + container-name: app-prod + image: "standardnotes/web:${{ github.sha }}" + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + service: app-prod + cluster: prod + wait-for-service-stability: true + + notify_slack: + needs: deploy + + runs-on: ubuntu-latest + + steps: + - name: Notify slack + uses: pullreminders/slack-action@master + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + args: '{ \"channel\": \"${{ secrets.SLACK_NOTIFICATION_CHANNEL }}\", \"blocks\": [{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Successfully deployed \"}}, {\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Changes: \"}, \"accessory\": {\"type\": \"image\", \"image_url\": \"https://website-dev.standardnotes.org/assets/icon.png\", \"alt_text\": \"Standard Notes\"}}, { \"type\": \"section\", \"fields\": [{\"type\": \"mrkdwn\", \"text\": \"\"}]}]}' diff --git a/Dockerfile b/Dockerfile index 3fa734d96..5b12e1d40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ # Set up Nginx to terminate SSL with LetsEncrypt and proxy_pass to http://localhost:3000/ ### -FROM ruby:alpine +FROM ruby:2.7.1-alpine RUN apk add --update --no-cache \ alpine-sdk \ @@ -34,15 +34,8 @@ COPY . /app/ # Leave RAILS_SERVE_STATIC_FILES commented if Nginx/Apache will serve static files instead of rails. ### -RUN bundle install - -RUN npm install - RUN npm run build -# Uncomment the line below for production: -# RUN bundle exec rake assets:precompile - EXPOSE 3000 ENTRYPOINT [ "./docker/entrypoint" ] diff --git a/Gemfile.lock b/Gemfile.lock index a8c492c40..7ea9d0c2d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,13 +96,13 @@ GEM net-ssh (>= 2.6.5, < 6.0.0) net-ssh (5.2.0) nio4r (2.5.2) - nokogiri (1.10.7) + nokogiri (1.10.8) mini_portile2 (~> 2.4.0) - nokogiri (1.10.7-x64-mingw32) + nokogiri (1.10.8-x64-mingw32) mini_portile2 (~> 2.4.0) non-stupid-digest-assets (1.0.9) sprockets (>= 2.0) - puma (4.3.1) + puma (4.3.5) nio4r (~> 2.0) rack (2.1.2) rack-cors (1.1.1) diff --git a/app/assets/stylesheets/_ionicons.scss b/app/assets/stylesheets/_ionicons.scss index bda8c265c..e217629e8 100644 --- a/app/assets/stylesheets/_ionicons.scss +++ b/app/assets/stylesheets/_ionicons.scss @@ -13,8 +13,8 @@ */ @font-face { font-family: "Ionicons"; - src: url("../fonts/ionicons.eot?v=2.0.0"); - src: url("../fonts/ionicons.eot?v=2.0.1#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=2.0.1") format("truetype"), url("../fonts/ionicons.woff?v=2.0.1") format("woff"), url("../fonts/ionicons.svg?v=2.0.1#Ionicons") format("svg"); + src: url("/assets/fonts/ionicons.eot?v=2.0.0"); + src: url("/assets/fonts/ionicons.eot?v=2.0.1#iefix") format("embedded-opentype"), url("/assets/fonts/ionicons.ttf?v=2.0.1") format("truetype"), url("/assets/fonts/ionicons.woff?v=2.0.1") format("woff"), url("/assets/fonts/ionicons.svg?v=2.0.1#Ionicons") format("svg"); font-weight: normal; font-style: normal; } diff --git a/app/assets/templates/directives/component-view.pug b/app/assets/templates/directives/component-view.pug index 59a8a388d..610e2ab02 100644 --- a/app/assets/templates/directives/component-view.pug +++ b/app/assets/templates/directives/component-view.pug @@ -89,7 +89,7 @@ iframe( ng-attr-id='component-iframe-{{ctrl.component.uuid}}', ng-if='ctrl.component && ctrl.componentValid', ng-src='{{ctrl.getUrl() | trusted}}', - sandbox='allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals allow-forms' + sandbox='allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals allow-forms allow-downloads' ) | Loading .loading-overlay(ng-if='ctrl.loading') diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb new file mode 100644 index 000000000..7fa247be2 --- /dev/null +++ b/app/controllers/health_check_controller.rb @@ -0,0 +1,5 @@ +class HealthCheckController < ApplicationController + def index + render :plain => "OK" + end +end diff --git a/config/application.rb b/config/application.rb index 754c27ab6..ebbcc7664 100644 --- a/config/application.rb +++ b/config/application.rb @@ -43,7 +43,7 @@ module StandardNotes base_uri: %w('self'), block_all_mixed_content: false, # see http://www.w3.org/TR/mixed-content/ child_src: ["*", "blob:"], - frame_src: ["*", "blob:"], + frame_src: ["*", "blob:", "data:"], connect_src: ["*"], font_src: %w(* 'self'), form_action: %w('self'), diff --git a/config/environments/production.rb b/config/environments/production.rb index 1a5ec07c5..946d60dcb 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -2,6 +2,7 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. config.force_ssl = true + config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } } # Code is not reloaded between requests. config.cache_classes = true diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 1d686d7e3..cac5fd170 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -9,7 +9,7 @@ Rails.application.config.assets.version = '1.0' Rails.application.config.assets.paths << Rails.root.join('vendor', 'assets') Rails.application.config.assets.paths << Rails.root.join('dist') -Rails.application.config.assets.precompile << ["*.svg", "*.eot", "*.woff", "*.ttf"] +Rails.application.config.assets.precompile += %w( fonts/ionicons.eot fonts/ionicons.svg fonts/ionicons.ttf fonts/ionicons.woff ) # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. diff --git a/config/routes.rb b/config/routes.rb index 1697cb1b1..a62838c23 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ Rails.application.routes.draw do + get "/healthcheck" => "health_check#index" + root 'application#app' end diff --git a/package-lock.json b/package-lock.json index 74066a37b..a4358407b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12123,9 +12123,9 @@ } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, "which": { diff --git a/package.json b/package.json index fd47140cc..8514b6256 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "start": "webpack-dev-server --progress", "bundle": "webpack --mode production", - "build": "bundle install && npm install && npm run bundle", + "build": "bundle install && npm ci && bundle exec rails assets:precompile && npm run bundle", "submodules": "git submodule update --init --force --remote", "test": "karma start karma.conf.js --single-run", "lint": "eslint --fix app/assets/javascripts/**/*.js" diff --git a/app/assets/fonts/ionicons.eot b/vendor/assets/fonts/ionicons/ionicons.eot similarity index 100% rename from app/assets/fonts/ionicons.eot rename to vendor/assets/fonts/ionicons/ionicons.eot diff --git a/app/assets/fonts/ionicons.svg b/vendor/assets/fonts/ionicons/ionicons.svg similarity index 100% rename from app/assets/fonts/ionicons.svg rename to vendor/assets/fonts/ionicons/ionicons.svg diff --git a/app/assets/fonts/ionicons.ttf b/vendor/assets/fonts/ionicons/ionicons.ttf similarity index 100% rename from app/assets/fonts/ionicons.ttf rename to vendor/assets/fonts/ionicons/ionicons.ttf diff --git a/app/assets/fonts/ionicons.woff b/vendor/assets/fonts/ionicons/ionicons.woff similarity index 100% rename from app/assets/fonts/ionicons.woff rename to vendor/assets/fonts/ionicons/ionicons.woff