I use GitHub for source control my HTML, CSS and JS. I use Netlify / Cloudflare Pages to host my website (which is trigger off of a GitHub commit).
I work with static files (.html, .js and .css) and do not use programming frameworks like Ruby on Rails, Django, etc.
I’d like to create a GitHub Action that triggers on a git commit, to do the following:
a. Purge unused CSS.
b. Minify the HTML, CSS and JS
c. In-line the CSS & JS into the HTML file.
That way my site is minified, merged and purged of unused elements before it is automatically hosted by Netlify / Cloudflare Pages.
How would I go about doing this with GitHub Actions? I’ve looked into esbuild, webpack etc but all seem to come up short of being able to do all I need.
My approach to this is a Github action that:
checks out the main branch
performs the minification/purging etc
pushes the changes to a build branch
Then you just need to point Github Pages (or Netlify in your case) at the build branch rather than the main branch.
You'd need to choose appropriate CLI tools to perform the minifying/purging in the virtual machine that the action spins up. There are lots of options here. I'd suggest using packages that can be installed through node so that you only have to install that on the VM. For example:
PurgeCSS: Removes unneeded CSS
terser: Minifies JS
csso-cli: Minifies CSS
html-minifier: Minifies HTML
I'm not aware of any tools that you could use to inline your JS/CSS (and don't know why you'd want to), but I suspect they exist.
This is relatively straightforward with a Github action that looks a bit like this:
# A Github Action that minifies html/css/js and pushes it to a new branch
name: purge-and-minify
on:
push:
branches:
- 'main'
jobs:
checkout-minify-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
# Install CLI tools
- uses: actions/setup-node#v3
with:
node-version: '16'
- run: npm install -g terser
- run: npm install -g csso-cli
- run: npm install -g html-minifier
# Use CLI tools to minify, overwriting existing files
- run: for i in ./js/*.js; do terser $i --compress -o $i; done
- run: for i in ./css/*.css; do csso $i -o $i; done
- run: for i in ./html/*.html; do html-minifier [--your-options-here] $i -o $i; done
# Push changes to `build` branch
- run: |
git config user.name github-username
git config user.email github-username#user.noreply.github.com
git commit -am 'Automated minify of ${{ github.sha }}'
git push --force -u origin main:build
Related
I'm trying to build a repository which allows me to build Docker images for different versions of a project I'm forking.
The repo should have the following layout:
main branch where the workflow is defined, with a trigger such as:
on:
push:
branches-ignore:
- main
The workflow builds the software from any branch (basically a mvn clean package, docker build and docker push that applies to all versions of the software)
many software-1.2.3 branches which don't contain any .github/workflow files (it would be cumbersome to copy this file into each branch, and maintain it there)
From my research so far, it seems that GitHub Actions only runs when a workflow definition is present. However, I wonder if there's a way using webhooks or something to trick the system into doing what I want.
My next best option would probably be using workflow_dispatch,
on: push !main wouldn't work, because that !main branch would need to have this workflow in it.
Running the workflow manually is the easiest solution to implement.
on:
workflow_dispatch:
inputs:
BRANCH_OF_FORK:
description: 'branch name, on which this pipeline should run'
required: true
jobs:
doSomething:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
ref: ${{ github.event.inputs.BRANCH_OF_FORK }}
- run: docker build something something
There's a on:fork event, that could be used to trigger a run, but it could only trigger a fork event of this specific branch, that has the on:fork code in it's workflow.
It's possible to run the workflow on a cron job without on-fork event, but you would have to pick the correct branch programmatically.
steps:
- id: branch-selector
run: |
git clone ${{ github.event.repo.url }} .
all_branches=`git branch --all | grep -v " main\$" | grep -v "/main\$"`
correct_branch=`pick_correct_branch.py $all_branches`
git checkout -b $correct_branch
- run: docker build something something
pick_correct_branch.py is left as an exercise for the reader to implement.
I want to automate the build and publishing of the docs of an open source typescript project hosted on Github.
I tried TypeDoc and the generated docs folder is 23Mo. I don't want to commit it in the project's repo.
Ideally, on each release, I would like to use github actions to:
generate the docs
push that generated docs folder to its own github repo.
Currently I added a npm script to generate the docs: docs: typedoc --out docs src and here is the starting point of my github action file:
name: Docs
on:
release:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v1
- name: Use Node.js
uses: actions/setup-node#v1
with:
node-version: 12
- name: Generate docs
run: |
npm ci
npm run docs
From this action, how can I commit and push this generated directory to its own repo on github?
(Maybe there is a more conventional way to do that. Let me know)
If you want to commit and push changes, you can refer to some actions in the Github's marketplace like github-push or push changes to see if they are fitting your situation. Also, you can write your own script to call Github's API, e.g. I use Pygithub to call Github's APT to help me generate changelog and update the file in the repo.
You can use the github-action-push-to-another-repository action for this purpose:
- name: Pushes to another repository
uses: cpina/github-action-push-to-another-repository#main
env:
API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
with:
source-directory: <directory-where-the-dist-is-generated>
destination-github-username: <github-username>
destination-repository-name: <github-repository-name>
user-email: <github-email>
target-branch: <main/master>
I use Gitlab pages and Jekyll to generate a website, and a python script to generate the images and data files (JSON) used by Jekyll. As I need to update these files daily, I commit and push dozens of images to update the website, which is not really convenient.
I also use Github Actions to generate and store these files as artifacts on Github:
- name: Main script
run: |
python generate_images.py --reload # saves in folder saved_images
# I manually commit and push these images in jekyll/assets/img to update the site
- name: Upload images artifacts
uses: actions/upload-artifact#v1
with:
name: saved_images
path: saved_images
I would find it better to tell Jekyll to use the artifacts, instead of the committed files, so that I can update the site by just re-launching the github action (hopefully without extra commit or branch change). Actually that's what I've seen on Gitlab on another project:
pages:
stage: Web_page
before_script:
- python generate_images.py --reload
- cp -r saved_images/*.png jekyll/assets/img
- cd jekyll
- bundle install --path vendor
script:
- bundle exec jekyll build -d ../public
...
So I wonder if it is possible to use artifacts as Jekyll assets and data files in Github pages?
I've been trying for a while to get a Jekyll website running on Github Pages, but it doesn't seem to work. I've been getting the error
Your site is having problems building: The symbolic link
/vendor/bundle/ruby/2.3.0/gems/ffi-1.9.18/ext/ffi_c/libffi-x86_64-linux-gnu/include/ffitarget.h
targets a file which does not exist within your site's repository. For
more information, see
https://help.github.com/articles/page-build-failed-symlink-does-not-exist-within-your-site-s-repository/.
I have already tried it with 9 different Jekyll themes, but none of them seem to work, so I'm clearly doing something wrong. Here are the steps that I am taking
1) Create a new repo and put the files from a Jekyll Theme there, OR fork it from another repo (e.g. https://github.com/iwiedenm/jekyll-theme-massively-src)
2) Git pull it into my computer and make sure I'm on the gh-pages branch
3) Run bundle install --path vendor/bundle
4) Make sure it was built with bundle exec jekyll serve
5) Once it looks good, upload it into Github
git add *
git commit -m 'Test'
git push
Then I go to the repo in the browser and I see the error above, and I can't see the website because of that missing "ffitarget.h" file. When I go look for it in that directory, I am able to find it, but Github doesn't seem to be able to find it.
Nick Shu
PS: Feel free to mark this as a duplicate. I have seen other pages, such as this and I tried it, but it didn't work.
Github page will use local gems in vendor. If you commit them, you will have errors each time github pages tries to resolve symbolic links.
From a fresh repository
Add vendor/** in your .gitignore file before you do a git add . *.
The dot in git add . * forces git to stage dotfiles (.gitignore, ...).
From an already existing repository containing gems in a vendor folder
Add vendor/** in your .gitignore file,
Remove vendor/ files from versioning, git rm --cached -r vendor/
You can now stage, commit and push
git add . *
git commit -m 'remove vendor from versioning'
git push origin master`
Notes :
you can publish master branch content, as gh-pages branch is no more mandatory. See documentation.
unless you have special needs like debuging, it's not necessary to download gems for each of your project. You can just do a bundle install.
Ensure the vendor/bundle/ directory has been excluded..
By default, Jekyll excludes that directory and therefore, it would not care about the contents in your vendor directory..
When you fork/clone a repo, there's a possibility that the exclude: list has been customized (therefore overriding the default setting). You can ensure vendor/bundle/ is ignored by Jekyll by adding it to your custom exclude list:
# Exclude list
exclude:
- README.md
- Gemfile
- Gemfile.lock
- node_modules
- gulpfile.js
- package.json
- _site
- src
- vendor
- CNAME
- LICENSE
- Rakefile
- old
- vendor/bundle/
To locally emulate how the site is built on GitHub Pages, you can build using the --safe switch:
bundle exec jekyll serve --safe
My ultimate goal is to be able to schedule posts on my Jekyll blog. I am using Travis-CI to deploy the contents of /_site/ to an S3 bucket whenever I commit to my master branch in Github.
The Travis-CI flow works as expected but for the fact that new pages that are not built and addd to the /_site/ directory unless I build my site locally and push the new /_site/ folder directly to master. The posts are present in /_posts/ but do not get build and added to /_site/ automatically as they should when the site is rebuilt daily.
My travis.yml file is below.
language: ruby
rvm:
- 2.3.3
# before_script:
# - chmod +x ./script/cibuild # or do this locally and commit
# Assume bundler is being used, therefore
# the `install` step will run `bundle install` by default.
install: gem install jekyll html-proofer jekyll-twitter-plugin
script: jekyll build && htmlproofer ./_site
# branch whitelist, only for GitHub Pages
branches:
only:
- master
env:
global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer
exclude: [vendor]
sudo: false # route your build to the container-based infrastructure for a faster build
deploy:
provider: s3
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
bucket: $S3_BUCKET
local_dir: _site
I figured this out: the Travis-CI deploy gem doesn't include a build step. It just pushes the contents of the repo to S3. I updated my build script to push as part of the build and validation step.
You must set the option skip_cleanup as true on deploy directive