diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..503fd4c8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. +# More: https://editorconfig.org/ + +root = true + +[*] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true +charset = utf-8 +end_of_line = lf + +[Makefile] +indent_style = tab diff --git a/.github/workflows/branch-deleted.yml b/.github/workflows/branch-deleted.yml new file mode 100644 index 00000000..6783aa4d --- /dev/null +++ b/.github/workflows/branch-deleted.yml @@ -0,0 +1,17 @@ +name: Branch Deleted + +on: delete + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + ref: hakyll + + - name: Remove deployment for deleted branch + run: | + ./.github/workflows/deployment/delete.sh ${{ github.event.ref }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..475b273a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,53 @@ +name: Build + +on: + push: + branches-ignore: + - gh-pages + pull_request: + branches-ignore: + - gh-pages + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + stack: ["2.7.3"] + ghc: ["8.10.7"] + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: haskell/actions/setup@v1 + name: Setup Haskell Stack + with: + ghc-version: ${{ matrix.ghc }} + stack-version: ${{ matrix.stack }} + + - uses: actions/cache@v1 + name: Cache ~/.stack + with: + path: ~/.stack + key: ${{ runner.os }}-${{ matrix.ghc }}-stack + + - name: Build dependencies + run: stack build --system-ghc --only-dependencies + + - name: Build site + run: | + stack build --system-ghc + stack exec --system-ghc site rebuild + + - name: Deploy site + run: | + if [[ ! -z $GITHUB_HEAD_REF ]]; then echo "Skip this step for pull request"; exit 0; fi; + ./.github/workflows/deployment/deploy.sh diff --git a/.github/workflows/deployment/commons.sh b/.github/workflows/deployment/commons.sh new file mode 100644 index 00000000..87bd8c76 --- /dev/null +++ b/.github/workflows/deployment/commons.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +export repo_root_dir=$(git rev-parse --show-toplevel) +export site_src="${repo_root_dir}/_site" +export gh_pages_dir="${repo_root_dir}/docs" +export deployments_dir="${gh_pages_dir}/branches" + +# Site built from the main branch will be available at 'https:///'. +# Sites built from other branchs will be available at 'https:///branches/'. +export main_git_branch="hakyll" + +# replace "/", "#", etc with "-". +slugify() { + echo "$1" | iconv -c -t ascii//TRANSLIT | sed -E 's/[~^]+/-/g' | sed -E 's/[^a-zA-Z0-9]+/-/g' | sed -E 's/^-+|-+$/-/g' | tr A-Z a-z +} +export -f slugify + +git config user.name github-actions +git config user.email github-actions@github.com + +update_deployments_list() { + github_project_url=$(git remote get-url origin) + if [[ $github_project_url == git@github.com:* ]]; then + github_repo=$(echo ${github_project_url#"git@github.com:"} | sed 's/\.git$//g') + elif [[ $github_project_url == https://github.com/* ]]; then + github_repo=$(echo ${github_project_url#"https://github.com/"} | sed 's/\.git$//g' | sed 's/^\/\///g') + fi + + github_repo_owner=$(echo "${github_repo}" | sed 's/\/.*$//g') + github_repo_name=$(echo "${github_repo}" | sed 's/^.*\///g') + + deployments_list="DEPLOYMENTS.md" + echo "Updating ${deployments_list}" + rm $deployments_list + + # Create a markdown table + touch $deployments_list + echo "# Deployments" >>$deployments_list + echo "" >>$deployments_list + echo "| Branch | Link |" >>$deployments_list + echo "| --- | --- |" >>$deployments_list + + main_deployment_url="https://${github_repo_owner}.github.io/${github_repo_name}/" + echo "| [${main_git_branch}](https://github.com/${github_repo_owner}/${github_repo_name}/tree/${branch}) | [Open](${main_deployment_url}) |" >>$deployments_list + + remote_branches=$(git ls-remote --heads origin | sed 's?.*refs/heads/??' | grep -v "gh-pages" | grep -v "${main_git_branch}") + echo "$remote_branches" | while IFS= read -r branch; do + branch_slug=$(slugify $branch) + deployment_url="https://${github_repo_owner}.github.io/${github_repo_name}/branches/${branch_slug}" + echo "| [${branch}](https://github.com/${github_repo_owner}/${github_repo_name}/tree/${branch}) | [Open](${deployment_url}) |" >>$deployments_list + done + + # Update gh-pages branch + git add --all + git commit --allow-empty -m "Update ${deployments_list} [ci skip]" + git push --force origin gh-pages +} + +export -f update_deployments_list diff --git a/.github/workflows/deployment/delete.sh b/.github/workflows/deployment/delete.sh new file mode 100755 index 00000000..98e1bff8 --- /dev/null +++ b/.github/workflows/deployment/delete.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Remove deployment by specified git branch name. + +set -eo pipefail + +script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +source $script_dir/commons.sh + +git checkout gh-pages +git pull origin gh-pages + +branch_slug=$(slugify $1) +rm -rf "$deployments_dir/$branch_slug" + +echo "Updating gh-pages branch." +git add --all +git commit --allow-empty -m "Delete '$1' branch deployment [ci skip]" +git push --force origin gh-pages +echo "Deployment for branch '$1' has been deleted." + +update_deployments_list diff --git a/.github/workflows/deployment/deploy.sh b/.github/workflows/deployment/deploy.sh new file mode 100755 index 00000000..041526e3 --- /dev/null +++ b/.github/workflows/deployment/deploy.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Deploy static site to the GitHub pages. + +set -eo pipefail + +script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +source $script_dir/commons.sh + +deploy() { + if [[ ! -z "$GITHUB_REF_NAME" ]]; then + # The GITHUB_REF_NAME env variable is available in github actions. + git_branch=$GITHUB_REF_NAME + else + git_branch=$(git branch --show-current) + fi + echo "Current git branch is '${git_branch}'." + + git checkout gh-pages + git pull origin gh-pages + + if [ "$git_branch" == "$main_git_branch" ]; then + site_dest="${gh_pages_dir}" + + # Create temporary backup for other branches content. + mv "${deployments_dir}" . + + # Replace site files. + rm -rf "${site_dest}" + mkdir -p "${site_dest}" + cp -a -v ${site_src}/* ${site_dest}/ + + # Restore temporary backup for other branches content. + mv ./branches "${gh_pages_dir}/" + else + # Patch html files to tell search engine bots like google-bot not to index this content. + # More info: https://developers.google.com/search/docs/advanced/crawling/block-indexing + find $site_src -name '*.html' -exec sed -i 's///g' {} \; + + branch_slug=$(slugify $git_branch) + site_dest="${gh_pages_dir}/branches/${branch_slug}" + + # Replace site files. + rm -rf "${site_dest}" + mkdir -p "${site_dest}" + cp -a -v ${site_src}/* ${site_dest}/ + fi + + echo "Updating gh-pages branch." + git add --all + git commit --allow-empty -m "Update '${git_branch}' branch deployment [ci skip]" + git push --force origin gh-pages + echo "Deployment finished." +} + +deploy +update_deployments_list diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 8cfc8c99..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,68 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the workflow will run -on: - # Triggers the workflow on push or pull request events but only for the hakyll branch - push: - branches: [ hakyll ] - pull_request: - branches: [ hakyll ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - - strategy: - matrix: - stack: ["2.7.3"] - ghc: ["8.10.7"] - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - ref: hakyll - - - uses: haskell/actions/setup@v1 - name: Setup Haskell Stack - with: - ghc-version: ${{ matrix.ghc }} - stack-version: ${{ matrix.stack }} - - - uses: actions/cache@v1 - name: Cache ~/.stack - with: - path: ~/.stack - key: ${{ runner.os }}-${{ matrix.ghc }}-stack - - - name: Build dependencies - run: stack build --system-ghc --only-dependencies - - - name: Build site executable - run: stack build --system-ghc - - # Runs a set of commands using the runners shell - - name: Deploy - run: | - git config user.name github-actions - git config user.email github-actions@github.com - stack exec --system-ghc site rebuild - git checkout main - git pull --rebase - # Overwrite existing files with new files - cp -a -v _site/. . - # Commit - git add --all - git commit -m "[`date '+%F %T %Z'`] New release [ci skip]" - # Push - git push origin main:main diff --git a/README.md b/README.md index c298cef9..38b8c9d8 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,10 @@ This repository is for the [haskell.foundation](https://haskell.foundation) webs - [Table Of Contents](#table-of-contents) - [Building](#building) - [CI](#ci) + - [Deployment](#deployment) + - [PRs deployment](#prs-deployment) - [License](#license) - ## Building To build the project: @@ -50,6 +51,26 @@ The general steps are: 7. Copy the `_site` directory over the `main` branch contents 8. Commit and push the site contents to the `main` branch. +## Deployment + +[Available Deployments](https://github.com/haskellfoundation/haskellfoundation.github.io/blob/gh-pages/DEPLOYMENTS.md) + +Deployment is automated for branches in the original repository. + +### PRs deployment + +When you are submitting a PR, it's a good practice to provide a link to a running website demo. + +First you should enable GitHub pages for you forked repository. + +Screen Shot 2021-12-29 at 10 28 32 PM + +Then you should manually trigger a build for your branch in your forker repository. + +Screen Shot 2021-12-29 at 10 25 19 PM + +At first time it can take a while because there is no cache for Hakyll dependencies at your GitHub actions runner yet. You can attach a link to running CI job to the PR and go drink coffee. + ## License This site is open source, and covered under the Apache 2.0 license. diff --git a/donations/sponsors/flipstone.markdown b/donations/sponsors/flipstone.markdown index f10e5357..44fd8a40 100644 --- a/donations/sponsors/flipstone.markdown +++ b/donations/sponsors/flipstone.markdown @@ -1,7 +1,7 @@ --- title: FlipStone -logo: /assets/images/sponsors/flipstone/flipstone-683.png -srcset: /assets/images/sponsors/flipstone/flipstone-200.png 200w, /assets/images/sponsors/flipstone/flipstone-400.png 400w, /assets/images/sponsors/flipstone/flipstone-683.png 683w +logo: ./assets/images/sponsors/flipstone/flipstone-683.png +srcset: ./assets/images/sponsors/flipstone/flipstone-200.png 200w, ./assets/images/sponsors/flipstone/flipstone-400.png 400w, ./assets/images/sponsors/flipstone/flipstone-683.png 683w externalUrl: https://flipstone.com/ level: Functor --- diff --git a/donations/sponsors/github.markdown b/donations/sponsors/github.markdown index b5e1a398..0d745d05 100644 --- a/donations/sponsors/github.markdown +++ b/donations/sponsors/github.markdown @@ -1,7 +1,7 @@ --- title: GitHub -logo: /assets/images/sponsors/github/github-683.png -srcset: /assets/images/sponsors/github/github-200.png 200w, /assets/images/sponsors/github/github-400.png 400w, /assets/images/sponsors/github/github-683.png 683w +logo: ./assets/images/sponsors/github/github-683.png +srcset: ./assets/images/sponsors/github/github-200.png 200w, ./assets/images/sponsors/github/github-400.png 400w, ./assets/images/sponsors/github/github-683.png 683w externalUrl: https://github.com/ level: Monad --- diff --git a/donations/sponsors/iohk.markdown b/donations/sponsors/iohk.markdown index 93b78a01..b7ecd369 100644 --- a/donations/sponsors/iohk.markdown +++ b/donations/sponsors/iohk.markdown @@ -1,7 +1,7 @@ --- title: IOHK -logo: /assets/images/sponsors/iohk/iohk-683.png -srcset: /assets/images/sponsors/iohk/iohk-200.png 200w, /assets/images/sponsors/iohk/iohk-400.png 400w, /assets/images/sponsors/iohk/iohk-683.png 683w +logo: ./assets/images/sponsors/iohk/iohk-683.png +srcset: ./assets/images/sponsors/iohk/iohk-200.png 200w, ./assets/images/sponsors/iohk/iohk-400.png 400w, ./assets/images/sponsors/iohk/iohk-683.png 683w externalUrl: https://iohk.io/ level: Monad --- diff --git a/donations/sponsors/obsidian.markdown b/donations/sponsors/obsidian.markdown index 35f5d267..4d6d33f9 100644 --- a/donations/sponsors/obsidian.markdown +++ b/donations/sponsors/obsidian.markdown @@ -1,7 +1,7 @@ --- title: Obsidian Systems -logo: /assets/images/sponsors/obsidian-systems/obsidian-systems-683.png -srcset: /assets/images/sponsors/obsidian-systems/obsidian-systems-200.png 200w, /assets/images/sponsors/obsidian-systems/obsidian-systems-400.png 400w, /assets/images/sponsors/obsidian-systems/obsidian-systems-683.png 683w +logo: ./assets/images/sponsors/obsidian-systems/obsidian-systems-683.png +srcset: ./assets/images/sponsors/obsidian-systems/obsidian-systems-200.png 200w, ./assets/images/sponsors/obsidian-systems/obsidian-systems-400.png 400w, ./assets/images/sponsors/obsidian-systems/obsidian-systems-683.png 683w externalUrl: https://obsidian.systems/ level: Applicative --- diff --git a/donations/sponsors/tweag.markdown b/donations/sponsors/tweag.markdown index c53d94c9..8b30591e 100644 --- a/donations/sponsors/tweag.markdown +++ b/donations/sponsors/tweag.markdown @@ -1,7 +1,7 @@ --- title: Tweag -logo: /assets/images/sponsors/tweag/tweag-683.png -srcset: /assets/images/sponsors/tweag/tweag-200.png 200w, /assets/images/sponsors/tweag/tweag-400.png 400w, /assets/images/sponsors/tweag/tweag-683.png 683w +logo: ./assets/images/sponsors/tweag/tweag-683.png +srcset: ./assets/images/sponsors/tweag/tweag-200.png 200w, ./assets/images/sponsors/tweag/tweag-400.png 400w, ./assets/images/sponsors/tweag/tweag-683.png 683w externalUrl: https://tweag.io/ level: Applicative --- diff --git a/donations/sponsors/welltyped.markdown b/donations/sponsors/welltyped.markdown index e06a4b62..c5e23613 100644 --- a/donations/sponsors/welltyped.markdown +++ b/donations/sponsors/welltyped.markdown @@ -1,7 +1,7 @@ --- title: Well-Typed -logo: /assets/images/sponsors/well-typed/well-typed-683.png -srcset: /assets/images/sponsors/well-typed/well-typed-200.png 200w, /assets/images/sponsors/well-typed/well-typed-400.png 400w, /assets/images/sponsors/well-typed/well-typed-683.png 683w +logo: ./assets/images/sponsors/well-typed/well-typed-683.png +srcset: ./assets/images/sponsors/well-typed/well-typed-200.png 200w, ./assets/images/sponsors/well-typed/well-typed-400.png 400w, ./assets/images/sponsors/well-typed/well-typed-683.png 683w externalUrl: https://well-typed.com/ level: Applicative ---