├── .github ├── dependabot.yml └── workflows │ ├── jekyll-deploy.yml │ └── jekyll-test.yml ├── README.md ├── action.yml ├── deployer ├── Dockerfile └── entrypoint.rb └── tests ├── .gitignore ├── 404.html ├── CNAME ├── Gemfile ├── Gemfile.lock ├── _config.yml ├── _posts └── 2020-08-26-welcome-to-jekyll.markdown ├── about.markdown └── index.markdown /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/tests" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Jekyll Deploy 2 | 3 | # Controls when the action will run. Triggers the workflow on push or pull request 4 | # events but only for the master branch 5 | on: 6 | push: 7 | branches: 8 | # deploy on updates on main 9 | - main 10 | schedule: 11 | # redeploy every morning to update unpublished pages 12 | - cron: "0 2 * * *" 13 | 14 | jobs: 15 | deploy: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Cache gems 22 | uses: actions/cache@v1 23 | with: 24 | path: tests/vendor/gems 25 | key: ${{ runner.os }}-build-${{ hashFiles('**/Gemfile.lock') }} 26 | restore-keys: | 27 | ${{ runner.os }}-build- 28 | ${{ runner.os }}- 29 | 30 | - name: Build & Deploy to GitHub Pages 31 | uses: DavidS/jekyll-deploy@main 32 | with: 33 | source-dir: tests 34 | target-branch: deploy 35 | env: 36 | JEKYLL_ENV: production 37 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 38 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-test.yml: -------------------------------------------------------------------------------- 1 | name: Jekyll Test 2 | 3 | on: [ pull_request ] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | 12 | - name: Cache gems 13 | uses: actions/cache@v1 14 | with: 15 | path: tests/vendor/gems 16 | key: ${{ runner.os }}-build-${{ hashFiles('**/Gemfile.lock') }} 17 | restore-keys: | 18 | ${{ runner.os }}-build- 19 | ${{ runner.os }}- 20 | 21 | - name: Test using current SHA 22 | uses: ./ 23 | with: 24 | source-dir: tests 25 | build-only: true 26 | env: 27 | JEKYLL_ENV: production 28 | 29 | - name: Test deploy using current SHA 30 | uses: ./ 31 | with: 32 | source-dir: tests 33 | target-branch: deploy 34 | env: 35 | JEKYLL_ENV: production 36 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jekyll-deploy 2 | 3 | Builds and deploys a jekyll page to GitHub pages. 4 | 5 | Features: 6 | * build and test modes 7 | * record the site's source commit using a merge commit 8 | * build from any subdirectory in your repository 9 | * specify a target branch 10 | 11 | ## Usage 12 | 13 | To deploy every update to the `main` branch and regenerate the site once a day: 14 | 15 | ```yaml 16 | name: Jekyll Deploy 17 | 18 | on: 19 | push: 20 | branches: 21 | # deploy on updates on main 22 | - main 23 | schedule: 24 | # redeploy every morning to update unpublished pages 25 | - cron: "0 2 * * *" 26 | 27 | jobs: 28 | deploy: 29 | runs-on: ubuntu-latest 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - name: Cache gems 35 | uses: actions/cache@v1 36 | with: 37 | path: vendor/gems 38 | key: ${{ runner.os }}-build-${{ hashFiles('**/Gemfile.lock') }} 39 | restore-keys: | 40 | ${{ runner.os }}-build- 41 | ${{ runner.os }}- 42 | 43 | - name: Build & Deploy to GitHub Pages 44 | uses: DavidS/jekyll-deploy@main 45 | env: 46 | JEKYLL_ENV: production 47 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 48 | ``` 49 | 50 | To check PRs, set `build-only: true`: 51 | 52 | ```yaml 53 | name: Jekyll Test 54 | 55 | on: [ pull_request ] 56 | 57 | jobs: 58 | test: 59 | runs-on: ubuntu-latest 60 | 61 | steps: 62 | - uses: actions/checkout@v2 63 | 64 | - name: Cache gems 65 | uses: actions/cache@v1 66 | with: 67 | path: vendor/gems 68 | key: ${{ runner.os }}-build-${{ hashFiles('**/Gemfile.lock') }} 69 | restore-keys: | 70 | ${{ runner.os }}-build- 71 | ${{ runner.os }}- 72 | 73 | - name: Test 74 | uses: DavidS/jekyll-deploy@ 75 | with: 76 | build-only: true 77 | env: 78 | JEKYLL_ENV: production 79 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 80 | ``` 81 | 82 | The `GH_PAGES_TOKEN` needs the `public_repo` scope to be able to trigger deployments on a public repo or the full `repo` scope to deploy a private repository. Please note that this is circumventing GitHub's protection for infinitely recursive Actions invocations, so proceed with caution! 83 | 84 | ## Specifying a source directory 85 | 86 | If your site's source is not at the root of the repository, you can use the `source-dir` input to tell this action where the source can be found. For example, if your site is in a `docs/jekyll` subdirectory: 87 | 88 | ```yaml 89 | - name: Build & Deploy to custom branch 90 | uses: DavidS/jekyll-deploy@ 91 | with: 92 | source-dir: docs/jekyll 93 | env: 94 | JEKYLL_ENV: production 95 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 96 | ``` 97 | 98 | 99 | ## Specifying a target branch 100 | 101 | By default, this action deploys the compiled output to `gh-pages`, GitHub's default. If you want to use a different branch, you can use the `target-branch` input to do so. For example, to deploy to `docs`: 102 | 103 | ```yaml 104 | - name: Build & Deploy to custom branch 105 | uses: DavidS/jekyll-deploy@main 106 | with: 107 | target-branch: docs 108 | env: 109 | JEKYLL_ENV: production 110 | GH_PAGES_TOKEN: ${{ secrets.GH_PAGES_TOKEN }} 111 | ``` 112 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: jekyll-deploy 2 | description: "Builds and deploys a jekyll page to GitHub pages" 3 | branding: 4 | icon: "chevrons-right" 5 | color: "gray-dark" 6 | runs: 7 | using: "docker" 8 | image: "deployer/Dockerfile" 9 | inputs: 10 | build-only: 11 | description: Set to "true" to only build, but not deploy. This is useful for PR testing. 12 | required: false 13 | default: "false" 14 | adjust-last-modified: 15 | description: By default this action clamps last-modified times to the date of the last commit modifying it. This reduces the amount of churn of updating timestamps in the rendered files. Set this to "false" to use the build time instead. 16 | required: false 17 | default: "true" 18 | source-dir: 19 | description: Specify a subdirectory containing the jekyll site, relative to the root of the repository. If this is not specified, the site is expected to be in the root of the repository. 20 | required: false 21 | default: . 22 | target-branch: 23 | description: Specify the branch to deploy the site to. By default, this is "gh-pages", GitHub's default branch for doc sites. 24 | required: false 25 | default: "gh-pages" 26 | -------------------------------------------------------------------------------- /deployer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.6 2 | LABEL "com.github.actions.name"="Jekyll Deploy" 3 | LABEL "com.github.actions.description"="Builds and deploys a jekyll page to GitHub pages" 4 | LABEL "com.github.actions.icon"="chevrons-right" 5 | LABEL "com.github.actions.color"="gray-dark" 6 | 7 | RUN gem install bundler -v 2.1.4 \ 8 | && apt update \ 9 | && apt install -y git-restore-mtime \ 10 | && apt clean \ 11 | && rm -rf /var/lib/apt/lists/* 12 | 13 | ADD entrypoint.rb /entrypoint.rb 14 | ENTRYPOINT ["/entrypoint.rb"] 15 | -------------------------------------------------------------------------------- /deployer/entrypoint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'English' 5 | require 'fileutils' 6 | 7 | def system_or_fail(*cmd) 8 | puts "executing #{cmd.inspect}" 9 | if system(*cmd) 10 | puts "executed #{cmd.inspect} successfully" 11 | else 12 | puts "execution failed with '#{$CHILD_STATUS}'" 13 | exit $CHILD_STATUS.exitstatus 14 | end 15 | end 16 | 17 | basedir = Dir.pwd 18 | 19 | if ENV['INPUT_ADJUST-LAST-MODIFIED'] == "true" 20 | # help jekyll with stable last modified times to avoid churning timestamps 21 | puts "Adjusting mtime/last modified times" 22 | system_or_fail('git', 'restore-mtime', '--merge', ENV['INPUT_SOURCE-DIR']) 23 | else 24 | puts "Adjusting mtime/last modified times disabled in config" 25 | end 26 | 27 | Dir.chdir(ENV['INPUT_SOURCE-DIR']) 28 | sourcedir = Dir.pwd 29 | 30 | system_or_fail('bundle', 'config', 'set', 'path', 'vendor/gems') 31 | system_or_fail('bundle', 'config', 'set', 'deployment', 'true') 32 | system_or_fail('bundle', 'install', '--jobs=4', '--retry=3') 33 | 34 | if ENV['INPUT_BUILD-ONLY'] == "true" 35 | system_or_fail('bundle', 'exec', 'jekyll', 'build', '--future', '--verbose', '--trace') 36 | exit 37 | else 38 | system_or_fail('bundle', 'exec', 'jekyll', 'build', '--verbose', '--trace') 39 | end 40 | 41 | Dir.chdir('_site') 42 | File.open('.nojekyll', 'w') { |f| f.puts 'Skip Jekyll' } 43 | 44 | system_or_fail('git', 'init', '.') 45 | FileUtils.cp(File.join(basedir, '/.git/config'), '.git/config') 46 | system_or_fail('git', 'config', 'user.name', ENV['GITHUB_ACTOR']) 47 | system_or_fail('git', 'config', 'user.email', "#{ENV['GITHUB_ACTOR']}@users.noreply.github.com") 48 | system_or_fail('git', 'fetch', '--no-tags', '--no-recurse-submodules', 'origin', "+#{ENV['GITHUB_SHA']}:refs/remotes/origin/source") 49 | if %x(git ls-remote --heads origin) =~ %r{\trefs/heads/#{ENV['INPUT_TARGET-BRANCH']}\n} 50 | puts "Found target branch '#{ENV['INPUT_TARGET-BRANCH']}', using that as base" 51 | system_or_fail('git', 'fetch', '--no-tags', '--no-recurse-submodules', 'origin', "+#{ENV['INPUT_TARGET-BRANCH']}:refs/remotes/origin/#{ENV['INPUT_TARGET-BRANCH']}") 52 | system_or_fail('git', 'reset', '--soft', "origin/#{ENV['INPUT_TARGET-BRANCH']}") 53 | else 54 | puts "Didn't find target branch '#{ENV['INPUT_TARGET-BRANCH']}', using the source as a base" 55 | system_or_fail('git', 'reset', '--soft', "origin/source") 56 | end 57 | 58 | if File.exist?(File.join(sourcedir, 'CNAME')) && !File.exist?('CNAME') 59 | puts "Rendering github's CNAME file" 60 | FileUtils.cp(File.join(sourcedir, 'CNAME'), 'CNAME') 61 | end 62 | 63 | system_or_fail('git', 'add', '-A', '.') 64 | system_or_fail('git', 'commit', '-m', 'Update github pages') 65 | system_or_fail('git', 'merge', '-s', 'ours', 'origin/source') 66 | system_or_fail('git', 'push', 'origin', "HEAD:#{ENV['INPUT_TARGET-BRANCH']}") 67 | 68 | puts "triggering a github pages deploy" 69 | 70 | require 'net/http' 71 | result = Net::HTTP.post( 72 | URI("https://api.github.com/repos/#{ENV['GITHUB_REPOSITORY']}/pages/builds"), 73 | "", 74 | "Content-Type" => "application/json", 75 | "Authorization" => "token #{ENV['GH_PAGES_TOKEN']}", 76 | ) 77 | 78 | puts result.body 79 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-cache 4 | .jekyll-metadata 5 | vendor 6 | -------------------------------------------------------------------------------- /tests/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /404.html 3 | layout: default 4 | --- 5 | 6 | 19 | 20 |
21 |

404

22 | 23 |

Page not found :(

24 |

The requested page could not be found.

25 |
26 | -------------------------------------------------------------------------------- /tests/CNAME: -------------------------------------------------------------------------------- 1 | test.example.org 2 | -------------------------------------------------------------------------------- /tests/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | # Hello! This is where you manage which Jekyll version is used to run. 3 | # When you want to use a different version, change it below, save the 4 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 5 | # 6 | # bundle exec jekyll serve 7 | # 8 | # This will help ensure the proper Jekyll version is running. 9 | # Happy Jekylling! 10 | gem "jekyll", "~> 4.2.0" 11 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 12 | gem "minima", "~> 2.5" 13 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 14 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 15 | # gem "github-pages", group: :jekyll_plugins 16 | # If you have any plugins, put them here! 17 | group :jekyll_plugins do 18 | gem "jekyll-feed", "~> 0.15" 19 | end 20 | 21 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem 22 | # and associated library. 23 | platforms :mingw, :x64_mingw, :mswin, :jruby do 24 | gem "tzinfo", "~> 1.2" 25 | gem "tzinfo-data" 26 | end 27 | 28 | # Performance-booster for watching directories on Windows 29 | gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] 30 | 31 | -------------------------------------------------------------------------------- /tests/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.0) 5 | public_suffix (>= 2.0.2, < 5.0) 6 | colorator (1.1.0) 7 | concurrent-ruby (1.1.8) 8 | em-websocket (0.5.2) 9 | eventmachine (>= 0.12.9) 10 | http_parser.rb (~> 0.6.0) 11 | eventmachine (1.2.7) 12 | ffi (1.15.0) 13 | forwardable-extended (2.6.0) 14 | http_parser.rb (0.6.0) 15 | i18n (1.8.10) 16 | concurrent-ruby (~> 1.0) 17 | jekyll (4.2.0) 18 | addressable (~> 2.4) 19 | colorator (~> 1.0) 20 | em-websocket (~> 0.5) 21 | i18n (~> 1.0) 22 | jekyll-sass-converter (~> 2.0) 23 | jekyll-watch (~> 2.0) 24 | kramdown (~> 2.3) 25 | kramdown-parser-gfm (~> 1.0) 26 | liquid (~> 4.0) 27 | mercenary (~> 0.4.0) 28 | pathutil (~> 0.9) 29 | rouge (~> 3.0) 30 | safe_yaml (~> 1.0) 31 | terminal-table (~> 2.0) 32 | jekyll-feed (0.15.1) 33 | jekyll (>= 3.7, < 5.0) 34 | jekyll-sass-converter (2.1.0) 35 | sassc (> 2.0.1, < 3.0) 36 | jekyll-seo-tag (2.6.1) 37 | jekyll (>= 3.3, < 5.0) 38 | jekyll-watch (2.2.1) 39 | listen (~> 3.0) 40 | kramdown (2.3.1) 41 | rexml 42 | kramdown-parser-gfm (1.1.0) 43 | kramdown (~> 2.0) 44 | liquid (4.0.3) 45 | listen (3.5.1) 46 | rb-fsevent (~> 0.10, >= 0.10.3) 47 | rb-inotify (~> 0.9, >= 0.9.10) 48 | mercenary (0.4.0) 49 | minima (2.5.1) 50 | jekyll (>= 3.5, < 5.0) 51 | jekyll-feed (~> 0.9) 52 | jekyll-seo-tag (~> 2.1) 53 | pathutil (0.16.2) 54 | forwardable-extended (~> 2.6) 55 | public_suffix (4.0.6) 56 | rb-fsevent (0.10.4) 57 | rb-inotify (0.10.1) 58 | ffi (~> 1.0) 59 | rexml (3.2.5) 60 | rouge (3.26.0) 61 | safe_yaml (1.0.5) 62 | sassc (2.4.0) 63 | ffi (~> 1.9) 64 | terminal-table (2.0.0) 65 | unicode-display_width (~> 1.1, >= 1.1.1) 66 | unicode-display_width (1.7.0) 67 | 68 | PLATFORMS 69 | ruby 70 | 71 | DEPENDENCIES 72 | jekyll (~> 4.2.0) 73 | jekyll-feed (~> 0.15) 74 | minima (~> 2.5) 75 | tzinfo (~> 1.2) 76 | tzinfo-data 77 | wdm (~> 0.1.1) 78 | 79 | BUNDLED WITH 80 | 2.1.4 81 | -------------------------------------------------------------------------------- /tests/_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | # 11 | # If you need help with YAML syntax, here are some quick references for you: 12 | # https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml 13 | # https://learnxinyminutes.com/docs/yaml/ 14 | # 15 | # Site settings 16 | # These are used to personalize your new site. If you look in the HTML files, 17 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 18 | # You can create any custom variable you would like, and they will be accessible 19 | # in the templates via {{ site.myvariable }}. 20 | 21 | title: Your awesome title 22 | email: your-email@example.com 23 | description: >- # this means to ignore newlines until "baseurl:" 24 | Write an awesome description for your new site here. You can edit this 25 | line in _config.yml. It will appear in your document head meta (for 26 | Google search results) and in your feed.xml site description. 27 | baseurl: "" # the subpath of your site, e.g. /blog 28 | url: "" # the base hostname & protocol for your site, e.g. http://example.com 29 | twitter_username: jekyllrb 30 | github_username: jekyll 31 | 32 | # Build settings 33 | theme: minima 34 | plugins: 35 | - jekyll-feed 36 | 37 | # Exclude from processing. 38 | # The following items will not be processed, by default. 39 | # Any item listed under the `exclude:` key here will be automatically added to 40 | # the internal "default list". 41 | # 42 | # Excluded items can be processed by explicitly listing the directories or 43 | # their entries' file path in the `include:` list. 44 | # 45 | # exclude: 46 | # - .sass-cache/ 47 | # - .jekyll-cache/ 48 | # - gemfiles/ 49 | # - Gemfile 50 | # - Gemfile.lock 51 | # - node_modules/ 52 | # - vendor/bundle/ 53 | # - vendor/cache/ 54 | # - vendor/gems/ 55 | # - vendor/ruby/ 56 | -------------------------------------------------------------------------------- /tests/_posts/2020-08-26-welcome-to-jekyll.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Welcome to Jekyll!" 4 | date: 2020-08-26 14:52:19 +0100 5 | categories: jekyll update 6 | --- 7 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 8 | 9 | Jekyll requires blog post files to be named according to the following format: 10 | 11 | `YEAR-MONTH-DAY-title.MARKUP` 12 | 13 | Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. 14 | 15 | Jekyll also offers powerful support for code snippets: 16 | 17 | {% highlight ruby %} 18 | def print_hi(name) 19 | puts "Hi, #{name}" 20 | end 21 | print_hi('Tom') 22 | #=> prints 'Hi, Tom' to STDOUT. 23 | {% endhighlight %} 24 | 25 | Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk]. 26 | 27 | [jekyll-docs]: https://jekyllrb.com/docs/home 28 | [jekyll-gh]: https://github.com/jekyll/jekyll 29 | [jekyll-talk]: https://talk.jekyllrb.com/ 30 | -------------------------------------------------------------------------------- /tests/about.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: About 4 | permalink: /about/ 5 | --- 6 | 7 | This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/) 8 | 9 | You can find the source code for Minima at GitHub: 10 | [jekyll][jekyll-organization] / 11 | [minima](https://github.com/jekyll/minima) 12 | 13 | You can find the source code for Jekyll at GitHub: 14 | [jekyll][jekyll-organization] / 15 | [jekyll](https://github.com/jekyll/jekyll) 16 | 17 | 18 | [jekyll-organization]: https://github.com/jekyll 19 | -------------------------------------------------------------------------------- /tests/index.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | # Feel free to add content and custom Front Matter to this file. 3 | # To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults 4 | 5 | layout: home 6 | --- 7 | --------------------------------------------------------------------------------