From a00be286c156357141f898c844ffde0090dd3bcb Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Wed, 26 Aug 2020 18:34:03 +0900 Subject: [PATCH 1/9] Add docker-compose.yml to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8497760c3f..4521391551 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,5 @@ /node_modules yarn-error.log + +docker-compose.yml From 16d888e48ce0673f34ae28baafe44cbda98ae627 Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Wed, 26 Aug 2020 18:36:19 +0900 Subject: [PATCH 2/9] Add development tools --- Gemfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Gemfile b/Gemfile index f9afd68bc3..2365ce1453 100644 --- a/Gemfile +++ b/Gemfile @@ -80,6 +80,10 @@ end group :development do gem "yard" + gem "guard" + gem "guard-minitest" + gem "pry", "<= 0.12.2" if RUBY_VERSION < '2.4' + gem "pry-byebug" end group :test do From c2d5a39fd42db5f21c0a62cf80b48a3776d07d1d Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Wed, 26 Aug 2020 18:42:54 +0900 Subject: [PATCH 3/9] Add Guardfile --- Guardfile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Guardfile diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000000..2ee21bd185 --- /dev/null +++ b/Guardfile @@ -0,0 +1,3 @@ +guard :minitest, all_on_start: false do + watch(%r{^test/(.*)test(.*)\.rb$}) +end From 2dbd20f73ad4313144b1f5a90b5c198d6b2784dc Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Fri, 28 Aug 2020 10:49:44 +0900 Subject: [PATCH 4/9] Add docker-compose and database.yml for mysql2 and postgresql --- config/database.mysql.yml | 18 ++++++++++++++++++ config/database.postgres.yml | 19 +++++++++++++++++++ docker-compose.mysql.yml | 14 ++++++++++++++ docker-compose.postgres.yml | 15 +++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 config/database.mysql.yml create mode 100644 config/database.postgres.yml create mode 100644 docker-compose.mysql.yml create mode 100644 docker-compose.postgres.yml diff --git a/config/database.mysql.yml b/config/database.mysql.yml new file mode 100644 index 0000000000..3a9ec22916 --- /dev/null +++ b/config/database.mysql.yml @@ -0,0 +1,18 @@ +default: &default + adapter: mysql2 + host: <%= ENV.fetch('DB_HOST', '127.0.0.1') %> + port: <%= ENV.fetch('DB_PORT', '3306') %> + username: root + password: password + +production: + <<: *default + database: redmine_production + +development: + <<: *default + database: redmine_development + +test: + <<: *default + database: redmine_test diff --git a/config/database.postgres.yml b/config/database.postgres.yml new file mode 100644 index 0000000000..20d7dd38e0 --- /dev/null +++ b/config/database.postgres.yml @@ -0,0 +1,19 @@ +default: &default + adapter: postgresql + encoding: utf8 + host: <%= ENV.fetch('DB_HOST', 'localhost') %> + port: <%= ENV.fetch('DB_PORT', '5432') %> + username: postgres + password: postgres + +production: + <<: *default + database: redmine_production + +development: + <<: *default + database: redmine_development + +test: + <<: *default + database: redmine_test diff --git a/docker-compose.mysql.yml b/docker-compose.mysql.yml new file mode 100644 index 0000000000..d6033fe553 --- /dev/null +++ b/docker-compose.mysql.yml @@ -0,0 +1,14 @@ +version: '3.4' +services: + db: + image: mysql:${DB_VERSION:-latest} + environment: + MYSQL_ROOT_PASSWORD: password + volumes: + - mysql_data:/var/lib/mysql + ports: + - "3306:3306" + + +volumes: + mysql_data: diff --git a/docker-compose.postgres.yml b/docker-compose.postgres.yml new file mode 100644 index 0000000000..ad21b712e7 --- /dev/null +++ b/docker-compose.postgres.yml @@ -0,0 +1,15 @@ +version: '3.4' +services: + db: + image: postgres:${DB_VERSION:-latest} + volumes: + - postgres_data:/var/lib/postgresql + ports: + - "5432:5432" + environment: + LANG: C.UTF-8 + POSTGRES_INITDB_ARGS: --locale=C.UTF-8 + POSTGRES_PASSWORD: postgres + +volumes: + postgres_data: From 7b2ff429c8401ef9bb9eefe0bfa46f31cb51b836 Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Sat, 5 Sep 2020 11:32:46 +0900 Subject: [PATCH 5/9] Add workflows for unit tests --- .github/actions/test-with-db.sh | 11 ++++ .github/workflows/test.yml | 93 +++++++++++++++++++++++++++++++++ config/database.sqlite.yml | 18 +++++++ 3 files changed, 122 insertions(+) create mode 100755 .github/actions/test-with-db.sh create mode 100644 .github/workflows/test.yml create mode 100644 config/database.sqlite.yml diff --git a/.github/actions/test-with-db.sh b/.github/actions/test-with-db.sh new file mode 100755 index 0000000000..2aac7b33a7 --- /dev/null +++ b/.github/actions/test-with-db.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -x + +database=$1 + +cp ./config/database.$database.yml ./config/database.yml +bundle install --path vendor/bundle --without minimagick +bundle update +bundle exec rake db:create db:migrate +bundle exec rake test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..2e29e08f57 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,93 @@ +name: Test + +on: + push: + branches-ignore: + - master + - development + +jobs: + test-with-mysql: + strategy: + fail-fast: false + matrix: + ruby: [2.3, 2.4, 2.5, 2.6] + db_version: [5.7] + runs-on: ubuntu-latest + container: + image: ruby:${{ matrix.ruby }} + services: + db: + image: mysql:${{ matrix.db_version }} + env: + MYSQL_ROOT_PASSWORD: password + ports: + - 3306:3306 + steps: + - uses: actions/checkout@v2 + - name: Cache gems + uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ matrix.ruby }}-mysql-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ matrix.ruby }}-mysql- + ${{ matrix.ruby }}- + - name: Install & run tests + run: ./.github/actions/test-with-db.sh mysql + env: + DB_HOST: db + test-with-postgres: + strategy: + fail-fast: false + matrix: + ruby: [2.3, 2.4, 2.5, 2.6] + db_version: [9.5] + runs-on: ubuntu-latest + container: + image: ruby:${{ matrix.ruby }} + services: + db: + image: postgres:${{ matrix.db_version }} + env: + LANG: C.UTF-8 + POSTGRES_INITDB_ARGS: --locale=C.UTF-8 + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + steps: + - uses: actions/checkout@v2 + - name: Cache gems + uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ matrix.ruby }}-postgres-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ matrix.ruby }}-postgres- + ${{ matrix.ruby }}- + - name: Install & run tests + run: ./.github/actions/test-with-db.sh postgres + env: + DB_HOST: db + test-with-sqlite: + strategy: + fail-fast: false + matrix: + ruby: [2.3, 2.4, 2.5, 2.6] + runs-on: ubuntu-latest + container: + image: ruby:${{ matrix.ruby }} + steps: + - uses: actions/checkout@v2 + - name: Cache gems + uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ matrix.ruby }}-sqlite-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ matrix.ruby }}-sqlite- + ${{ matrix.ruby }}- + - name: Install & run tests + run: ./.github/actions/test-with-db.sh sqlite diff --git a/config/database.sqlite.yml b/config/database.sqlite.yml new file mode 100644 index 0000000000..0d72b884a5 --- /dev/null +++ b/config/database.sqlite.yml @@ -0,0 +1,18 @@ +# Default setup is given for MySQL 5.7.7 or later. +# Examples for PostgreSQL, SQLite3 and SQL Server can be found at the end. +# Line indentation must be 2 spaces (no tabs). + +default: &default + adapter: sqlite3 + +production: + <<: *default + database: db/redmine_production.sqlite3 + +development: + <<: *default + database: db/redmine_development.sqlite3 + +test: + <<: *default + database: db/redmine_test.sqlite3 From cd2557311b692973826d297ba115c447cf322ac3 Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Mon, 14 Sep 2020 12:01:53 +0900 Subject: [PATCH 6/9] Create patch of current branch and store it as artifact --- .github/workflows/create-patch.yml | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/create-patch.yml diff --git a/.github/workflows/create-patch.yml b/.github/workflows/create-patch.yml new file mode 100644 index 0000000000..2b4ad36ac3 --- /dev/null +++ b/.github/workflows/create-patch.yml @@ -0,0 +1,32 @@ +name: Create Patch + +on: + push: + branches-ignore: + - master + - development + +jobs: + create-patch: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Create Patch + run: | + git rev-parse --abbrev-ref HEAD > .branch-name + git checkout development + git checkout -b patch + git merge --squash `cat .branch-name` + git config --global user.email "$AUTHOR_EMAIL" + git config --global user.name "$AUTHOR_NAME" + git commit -m "Patch for `cat .branch-name`" + git format-patch development..HEAD --stdout -k > patch.diff + env: + AUTHOR_EMAIL: ${{ github.event.head_commit.author.email }} + AUTHOR_NAME: ${{ github.event.head_commit.author.name }} + - uses: actions/upload-artifact@v2 + with: + name: patch + path: patch.diff From 50dfa34ba502780bdf84e9ea482167bc7ef27892 Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Tue, 15 Sep 2020 13:02:50 +0900 Subject: [PATCH 7/9] Comment link to patch as comment --- .github/actions/comment_patch_url.rb | 76 ++++++++++++++++++++++++++++ .github/workflows/comment-patch.yml | 24 +++++++++ 2 files changed, 100 insertions(+) create mode 100755 .github/actions/comment_patch_url.rb create mode 100644 .github/workflows/comment-patch.yml diff --git a/.github/actions/comment_patch_url.rb b/.github/actions/comment_patch_url.rb new file mode 100755 index 0000000000..944889b084 --- /dev/null +++ b/.github/actions/comment_patch_url.rb @@ -0,0 +1,76 @@ +#!/usr/bin/env ruby + +require 'json' + +require 'faraday' + +REPO = 'redmine-patch-meetup/redmine-dev-mirror' + +WORKFLOW_RUN = JSON.parse ENV['WORKFLOW_RUN_JSON'] + +CONNECTION = Faraday.new('https://api.github.com/') do |conn| + conn.response :raise_error + conn.adapter Faraday.default_adapter +end + +def repo_resource(resource) + "repos/#{REPO}/#{resource}" +end + +def get_repo_resource(resource) + response = CONNECTION.get repo_resource(resource) + JSON.parse response.body +end + +def post_to_repo_resource(resource, body) + response = CONNECTION.post repo_resource(resource), + body.to_json, + "Content-Type" => "application/json", + "Authorization" => "token #{ENV['GITHUB_TOKEN']}" + JSON.parse response.body +end + +def patch_artifact_id + response = JSON.parse CONNECTION.get(WORKFLOW_RUN['artifacts_url']).body + patch_artifact = response['artifacts'].find { |artifact| artifact['name'] == 'patch' } + patch_artifact['id'] +end + +def get_suite_id + suite_url = WORKFLOW_RUN['check_suite_url'] + id_start_index = suite_url.rindex('/') + 1 + suite_url[id_start_index..-1] +end + +def patch_artifact_download_url + "https://github.com/#{REPO}/suites/#{get_suite_id}/artifacts/#{patch_artifact_id}" +end + +def pull_request_number + WORKFLOW_RUN['pull_requests'][0]['number'] +end + +def post_pr_comment(pr_number, comment) + post_to_repo_resource "issues/#{pr_number}/comments", { body: comment } +end + +def find_previous_comment_id(pr_number) + comments = get_repo_resource "issues/#{pr_number}/comments" + previous_comment = comments.find { |comment| + comment['body'].include?('Patch can be downloaded [here]') && comment['user']['login'].include?('github-actions') + } + previous_comment['id'] if previous_comment +end + +def delete_comment(comment_id) + CONNECTION.delete "issues/comments/#{comment_id}", nil, "Authorization" => "token #{ENV['GITHUB_TOKEN']}" +end + +def main + existing_comment_id = find_previous_comment_id(pull_request_number) + delete_comment(existing_comment_id) if existing_comment_id + + post_pr_comment pull_request_number, "Patch can be downloaded [here](#{patch_artifact_download_url})" +end + +main if __FILE__ == $0 diff --git a/.github/workflows/comment-patch.yml b/.github/workflows/comment-patch.yml new file mode 100644 index 0000000000..121118ed25 --- /dev/null +++ b/.github/workflows/comment-patch.yml @@ -0,0 +1,24 @@ +name: Comment Patch + +on: + workflow_run: + workflows: + - Create Patch + types: + - completed + branches-ignore: + - master + - development + +jobs: + create-patch: + runs-on: ubuntu-latest + steps: + - name: Install gems + run: sudo gem install faraday + - uses: actions/checkout@v2 + - name: Comment Patch URL + run: ./.github/actions/comment_patch_url.rb + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_RUN_JSON: ${{ toJSON(github.event.workflow_run) }} From 22c6bbbb90a358ccf8a60e9042c7979354a2a495 Mon Sep 17 00:00:00 2001 From: Kevin Fischer Date: Tue, 15 Sep 2020 13:02:50 +0900 Subject: [PATCH 8/9] Comment link to patch as comment --- .github/actions/comment_patch_url.rb | 76 ++++++++++++++++++++++++++++ .github/workflows/comment-patch.yml | 24 +++++++++ 2 files changed, 100 insertions(+) create mode 100755 .github/actions/comment_patch_url.rb create mode 100644 .github/workflows/comment-patch.yml diff --git a/.github/actions/comment_patch_url.rb b/.github/actions/comment_patch_url.rb new file mode 100755 index 0000000000..9da290bdbb --- /dev/null +++ b/.github/actions/comment_patch_url.rb @@ -0,0 +1,76 @@ +#!/usr/bin/env ruby + +require 'json' + +require 'faraday' + +REPO = 'redmine-patch-meetup/redmine-dev-mirror' + +WORKFLOW_RUN = JSON.parse ENV['WORKFLOW_RUN_JSON'] + +CONNECTION = Faraday.new('https://api.github.com/') do |conn| + conn.response :raise_error + conn.adapter Faraday.default_adapter +end + +def repo_resource(resource) + "repos/#{REPO}/#{resource}" +end + +def get_repo_resource(resource) + response = CONNECTION.get repo_resource(resource) + JSON.parse response.body +end + +def post_to_repo_resource(resource, body) + response = CONNECTION.post repo_resource(resource), + body.to_json, + "Content-Type" => "application/json", + "Authorization" => "token #{ENV['GITHUB_TOKEN']}" + JSON.parse response.body +end + +def patch_artifact_id + response = JSON.parse CONNECTION.get(WORKFLOW_RUN['artifacts_url']).body + patch_artifact = response['artifacts'].find { |artifact| artifact['name'] == 'patch' } + patch_artifact['id'] +end + +def get_suite_id + suite_url = WORKFLOW_RUN['check_suite_url'] + id_start_index = suite_url.rindex('/') + 1 + suite_url[id_start_index..-1] +end + +def patch_artifact_download_url + "https://github.com/#{REPO}/suites/#{get_suite_id}/artifacts/#{patch_artifact_id}" +end + +def pull_request_number + WORKFLOW_RUN['pull_requests'][0]['number'] +end + +def post_pr_comment(pr_number, comment) + post_to_repo_resource "issues/#{pr_number}/comments", { body: comment } +end + +def find_previous_comment_id(pr_number) + comments = get_repo_resource "issues/#{pr_number}/comments" + previous_comment = comments.find { |comment| + comment['body'].include?('Patch can be downloaded [here]') && comment['user']['login'].include?('github-actions') + } + previous_comment['id'] if previous_comment +end + +def delete_comment(comment_id) + CONNECTION.delete repo_resource("issues/comments/#{comment_id}"), nil, "Authorization" => "token #{ENV['GITHUB_TOKEN']}" +end + +def main + existing_comment_id = find_previous_comment_id(pull_request_number) + delete_comment(existing_comment_id) if existing_comment_id + + post_pr_comment pull_request_number, "Patch can be downloaded [here](#{patch_artifact_download_url})" +end + +main if __FILE__ == $0 diff --git a/.github/workflows/comment-patch.yml b/.github/workflows/comment-patch.yml new file mode 100644 index 0000000000..121118ed25 --- /dev/null +++ b/.github/workflows/comment-patch.yml @@ -0,0 +1,24 @@ +name: Comment Patch + +on: + workflow_run: + workflows: + - Create Patch + types: + - completed + branches-ignore: + - master + - development + +jobs: + create-patch: + runs-on: ubuntu-latest + steps: + - name: Install gems + run: sudo gem install faraday + - uses: actions/checkout@v2 + - name: Comment Patch URL + run: ./.github/actions/comment_patch_url.rb + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_RUN_JSON: ${{ toJSON(github.event.workflow_run) }} From 1a806541bdddda1aab09a55d2d29133330e0bfc6 Mon Sep 17 00:00:00 2001 From: ishikawa999 Date: Mon, 21 Sep 2020 06:56:30 +0000 Subject: [PATCH 9/9] =?UTF-8?q?Change=20.next-prev-links=20span=E3=82=92?= =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/issues/show.html.erb | 12 ++++++++---- public/stylesheets/application.css | 19 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb index 5dcd833ac7..ec9f7167c1 100644 --- a/app/views/issues/show.html.erb +++ b/app/views/issues/show.html.erb @@ -6,23 +6,27 @@
<% if @prev_issue_id || @next_issue_id %> <% end %> diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 78857fcc3f..36a1a6b968 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -736,12 +736,15 @@ textarea#custom_field_default_value {width: 95%; resize:vertical} input#content_comments {width: 99%} span.pagination {margin-left:3px; color:#888; display:block;} -.pagination ul.pages { +.pagination ul.pages, .next-prev-links { margin: 0 5px 0 0; padding: 0; display: inline; } -.pagination ul.pages li { +div.next-prev-links.contextual span { + margin-left: -5px; +} +.pagination ul.pages li, .next-prev-links span { display: inline-block; padding: 0; border: 1px solid #ddd; @@ -752,14 +755,14 @@ span.pagination {margin-left:3px; color:#888; display:block;} text-align: center; } .pagination ul.pages li a, -.pagination ul.pages li span { +.pagination ul.pages li span, .next-prev-links span a { padding: 3px 8px; } -.pagination ul.pages li:first-child { +.pagination ul.pages li:first-child, .next-prev-links span:first-child { border-top-left-radius: 4px; border-bottom-left-radius: 4px; } -.pagination ul.pages li:last-child { +.pagination ul.pages li:last-child, .next-prev-links span:last-child { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } @@ -768,11 +771,13 @@ span.pagination {margin-left:3px; color:#888; display:block;} background-color: #628DB6; border-color: #628DB6; } -.pagination ul.pages li.page:hover { +.pagination ul.pages li.page:hover, .next-prev-links span:hover { background-color: #ddd; } .pagination ul.pages li.page a:hover, -.pagination ul.pages li.page a:active { +.pagination ul.pages li.page a:active, +.next-prev-links span a:hover, +.next-prev-links span a:active{ color: #169; text-decoration: inherit; }