diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml new file mode 100644 index 0000000..33446ca --- /dev/null +++ b/.github/workflows/auto-tag.yml @@ -0,0 +1,12 @@ +name: Auto-tag +on: + push: + tags: + - '*.*.*' +jobs: + auto-tag: + name: Auto-tag + runs-on: ubuntu-latest + steps: + - name: Auto-tag + uses: silverstripe/gha-auto-tag@main diff --git a/README.md b/README.md index 8341a90..ebe5398 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ -# gha-update-js \ No newline at end of file +# GitHub Actions - Update JS + +Update JS dependencies in core Silverstripe modules, create new bundles and create pull-requests + +## Usage: + +This action has no inputs. It is intended to be [run on a schedule](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#scheduled-events). You can copy the below example verbatim, and just modify the schedule to suit your use case. + +**.github/workflows/update-js.yml** +```yml +name: Update JS +on: + # Run on a schedule of once per quarter + schedule: + - cron: '0 0 1 */3 *' + workflow_dispatch: +jobs: + update-js: + name: Update JS + runs-on: ubuntu-latest + steps: + - name: Update JS + uses: silverstripe/gha-update-js@main +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..3cf4831 --- /dev/null +++ b/action.yml @@ -0,0 +1,151 @@ +name: Update JS +description: Updates JS dependencies in Silverstripe core modules + +runs: + using: composite + steps: + + - name: Checkout code + uses: actions/checkout@7884fcad6b5d53d10323aee724dc68d8b9096a2e # v2.4.2 + + - name: Read .nvmrc + id: read-nvm + shell: bash + run: | + echo ::set-output name=version::$(cat .nvmrc) + + - name: Setup node + uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0 + with: + node-version: ${{ steps.read-nvm.outputs.version }} + + - name: Install admin JS + if: github.event.repository.name != 'silverstripe-admin' + shell: bash + run: | + # Install admin js in sibling directory so shared components are available + DIR=$(pwd) + cd .. + git clone https://github.com/silverstripe/silverstripe-admin.git admin + cd admin + git checkout 1 + # yarn comes preinstalled with actions/setup-node + yarn install + cd $DIR + + # Use `yarn install` rather than `yarn upgrade` to prevent the following error: + # "error Outdated lockfile. Please run `yarn install` and try again." + - name: Update yarn.lock + shell: bash + run: | + if [[ -f yarn.lock ]]; then + rm yarn.lock + fi + yarn install + + - name: Read package.json + id: package-json + shell: bash + run: | + # Read package.json to see if lint and test are runnable scripts + LINT="false" + TEST="false" + if [[ "$(jq .scripts.lint? package.json)" != "null" ]]; then LINT="true"; fi + if [[ "$(jq .scripts.test? package.json)" != "null" ]]; then TEST="true"; fi + echo "::set-output name=lint::$LINT" + echo "::set-output name=test::$TEST" + echo "LINT is $LINT" + echo "TEST is $TEST" + + # The following 3 steps make up `yarn build` + # Splitting apart to make it easier to see where any failures originate from + - name: Yarn lint + if: steps.package-json.outputs.lint == 'true' + shell: bash + run: | + yarn lint + + - name: Yarn test + if: steps.package-json.outputs.test == 'true' + shell: bash + run: | + yarn test + + - name: Build JS with webpack + # always run this and subsequent steps even if yarn.lint/yarn.test fails so that pull-request is + # created which will result in a red pull-request build so it's easy to see where things are at + if: always() + shell: bash + run: | + NODE_ENV=production node_modules/webpack/bin/webpack.js -p --bail --progress + + - name: Remove any old pull-requests + if: always() + shell: bash + env: + GITHUB_REPOSITORY: ${{ github.repository }} + run: | + # https://docs.github.com/en/rest/pulls/pulls#list-pull-requests + RESP_CODE=$(curl -w %{http_code} -s -o __response.json \ + -X GET https://api.github.com/repos/$GITHUB_REPOSITORY/pulls \ + -H "Accept: application/vnd.github.v3+json") + if [[ $RESP_CODE != "200" ]]; then + echo "Unable to list pull-requests" + exit 1 + fi + JSON=$(cat __response.json) + NUMBERS=$(echo $JSON | jq '.[] | select(.title=="DEP Update JS dependencies" and .user.login=="github-actions[bot]") | .number') + for NUMBER in $NUMBERS; do + # https://docs.github.com/en/rest/pulls/pulls#update-a-pull-request + RESP_CODE=$(curl -w %{http_code} -s -o /dev/null \ + -X PATCH https://api.github.com/repos/$GITHUB_REPOSITORY/pulls/$NUMBER \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: token ${{ github.token }}" \ + -d @- << EOF + { + "state": "closed" + } + EOF + ) + if [[ $RESP_CODE != "200" ]]; then + echo "Unable to close pull-request $NUMBER" + exit 1 + fi + echo "Closed old pull-request $NUMBER" + done + + - name: Remove any old branches + if: always() + shell: bash + env: + GITHUB_REPOSITORY: ${{ github.repository }} + run: | + JSON=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/branches) + BRANCHES=$(echo $JSON | jq -r '.[] | .name | select(.|test("^pulls\/[0-9]\/update-js-[0-9]{10}$"))') + for BRANCH in $BRANCHES; do + if [[ "$BRANCH" =~ ^pulls/[0-9\.]+/update\-js\-[0-9]+$ ]]; then + git push origin --delete "$BRANCH" + echo "Deleted old branch $BRANCH" + fi + done + + - name: Generate branch name + if: always() + id: generate-branch-name + shell: bash + env: + GITHUB_REF: ${{ github.ref }} + run: | + # Convert refs/heads/mybranch to mybranch + CUT=$(echo $GITHUB_REF | cut -c 12-) + # e.g. pulls/1/update-js-1647810133 + BRANCH=pulls/$CUT/update-js-$(date +%s) + echo ::set-output name=branch::$BRANCH + + - name: Git + if: always() + uses: silverstripe/gha-pull-request@main + with: + branch: ${{ steps.generate-branch-name.outputs.branch }} + title: DEP Update JS dependencies + description: Automated yarn upgrade and yarn build