Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ci): add cron-based checks for upgrades and version pinning as given in the docs #2327

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions .github/actions/node-project-cleanup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: "Node.js project cleanup"
description: "The action removes the dependency on the particular package manager, compiler and/or engines from the package.json. It also removes all lockfiles and any installed dependencies in node_modules. But it does not setup Node.js nor installs dependencies."

inputs:
cwd:
description: "A directory with a Node.js project to clean up"
required: false
default: "." # i.e. present working directory

pj-remove-compiler:
description: "Whether to remove a dependency on the compiler from package.json"
required: false
default: "true" # any other string is considered `false`

pj-remove-pm:
description: "Whether to remove the packageManager field from package.json"
required: false
default: "true" # any other string is considered `false`

pj-remove-engines:
description: "Whether to remove the engines field from package.json"
required: false
default: "true" # any other string is considered `false`

remove-lockfiles:
description: "Whether to remove the lockfiles produced by popular Node.js package managers, such as: npm, bun, yarn and pnpm"
required: false
default: "true" # any other string is considered `false`

remove-node-modules:
description: "Whether to remove the node_modules folder"
required: false
default: "true" # any other string is considered `false`

runs:
using: "composite"
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: (Windows) Cleanup
if: runner.os == 'Windows'
shell: pwsh
working-directory: ${{ inputs.cwd }}
env:
PJ_REMOVE_COMPILER: ${{ inputs.pj-remove-compiler }}
PJ_REMOVE_PM: ${{ inputs.pj-remove-pm }}
PJ_REMOVE_ENGINES: ${{ inputs.pj-remove-engines }}
REMOVE_LOCKFILES: ${{ inputs.remove-lockfiles }}
REMOVE_NODE_MODULES: ${{ inputs.remove-node-modules }}
run: |
$ErrorActionPreference = 'Stop'

# Conditionally remove any lockfiles:
# yarn and bun (text), bun (binary), npm, pnpm
if ($env:REMOVE_LOCKFILES -eq "true") {
Remove-Item -Path "*.lock", "bun.lockb", "package-lock.json", "pnpm-lock.yaml" -Force
}

# Conditionally remove any installed dependencies
if ($env:REMOVE_NODE_MODULES -eq "true") {
Remove-Item -Path "node_modules" -Recurse -Force
}

##
# Conditionally remove certain fields from package.json
##

if ($env:PJ_REMOVE_COMPILER -eq "true") {
# Removes the "@tact-lang/compiler" field from every topmost object,
# which is handy to remove it from dependencies, devDependencies, etc.
# — all at once!
jq 'to_entries | map(if .value | type == "object" then .value |= del(."@tact-lang/compiler") else . end) | from_entries' package.json -M | Set-Content temp.json
Move-Item temp.json package.json -Force
}

if ($env:PJ_REMOVE_PM -eq "true") {
jq 'del(.packageManager)' package.json -M | Set-Content temp.json
Move-Item temp.json package.json -Force
}

if ($env:PJ_REMOVE_ENGINES -eq "true") {
jq 'del(.engines)' package.json -M | Set-Content temp.json
Move-Item temp.json package.json -Force
}

- name: (non-Windows) Cleanup
if: runner.os != 'Windows'
shell: bash
working-directory: ${{ inputs.cwd }}
env:
PJ_REMOVE_COMPILER: ${{ inputs.pj-remove-compiler }}
PJ_REMOVE_PM: ${{ inputs.pj-remove-pm }}
PJ_REMOVE_ENGINES: ${{ inputs.pj-remove-engines }}
REMOVE_LOCKFILES: ${{ inputs.remove-lockfiles }}
REMOVE_NODE_MODULES: ${{ inputs.remove-node-modules }}
run: |
# Conditionally remove any lockfiles:
# yarn and bun (text), bun (binary), npm, pnpm
if [ "$REMOVE_LOCKFILES" = "true" ]; then
rm -f *.lock bun.lockb package-lock.json pnpm-lock.yaml
fi

# Conditionally remove any installed dependencies
if [ "$REMOVE_NODE_MODULES" = "true" ]; then
rm -rf node_modules
fi

##
# Conditionally remove certain fields from package.json
##

if [ "$PJ_REMOVE_COMPILER" = "true" ]; then
# Removes the "@tact-lang/compiler" field from every topmost object,
# which is handy to remove it from dependencies, devDependencies, etc.
# — all at once!
jq 'to_entries | map(if .value | type == "object" then .value |= del(."@tact-lang/compiler") else . end) | from_entries' package.json -M > temp.json
mv -f temp.json package.json
fi

if [ "$PJ_REMOVE_PM" = "true" ]; then
jq 'del(.packageManager)' package.json -M > temp.json
mv -f temp.json package.json
fi

if [ "$PJ_REMOVE_ENGINES" = "true" ]; then
jq 'del(.engines)' package.json -M > temp.json
mv -f temp.json package.json
fi
265 changes: 265 additions & 0 deletions .github/workflows/compiler-upgrades.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
name: Compiler upgrades and dependencies check

on:
workflow_dispatch: # on demand launches, if needed
schedule:
- cron: "5 0 * * 2" # 00:05 on Tuesday, near the dependabot.yml

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# Get the latest and second-latest versions of Tact compiler published on NPM
# This job does not require checking out the repository
get-versions:
runs-on: ubuntu-latest
steps:
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

- name: Get versions
id: versions
run: |
latest="$(npm view @tact-lang/compiler version)"
second_latest="$(npm view @tact-lang/compiler versions --json | jq -r '.[-2]')"
echo "latest=$latest" >> $GITHUB_OUTPUT
echo "second_latest=$second_latest" >> $GITHUB_OUTPUT
outputs:
latest: ${{ steps.versions.outputs.latest }}
second_latest: ${{ steps.versions.outputs.second_latest }}

# Test updates with upgrade commands given in the Tact docs
test-upgrade:
needs: get-versions
env:
LATEST: ${{ needs.get-versions.outputs.latest }}
SECOND_LATEST: ${{ needs.get-versions.outputs.second_latest }}
strategy:
fail-fast: false
matrix:
node-version: [18, 22]
os: [ubuntu-latest, windows-latest, macos-latest]
package-manager: [npm, yarn, pnpm, bun]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
depth: 1 # the latest commit is enough

- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

- uses: oven-sh/setup-bun@v2
if: ${{ matrix.package-manager == 'bun' }}

- name: Clone tact-template
run: git clone --depth 1 https://github.com/tact-lang/tact-template

- name: Project cleanup
uses: ./.github/actions/node-project-cleanup
with:
cwd: tact-template

- name: Install missing package managers
working-directory: tact-template
run: |
# Yarn v1
# NOTE: consider also adding yarn v4 to the mix (through corepack & node 20+)
${{ matrix.package-manager == 'yarn' && 'npm i -g yarn' || 'echo noop' }}
# PNPM
${{ matrix.package-manager == 'pnpm' && 'npm i -g pnpm' || 'echo noop' }}

- name: (Windows-${{ matrix.package-manager }}) Override a version using installation commands
if: ${{ matrix.os == 'windows-latest' }}
env:
PM: ${{ matrix.package-manager }}
working-directory: tact-template
run: |
# Run the installation commands
switch ($PM) {
"npm" {
# Install the second-latest version
npm i --save-exact "@tact-lang/compiler@$env:SECOND_LATEST"
# Update to the latest version (using the command from the docs)
npm update --save "@tact-lang/compiler"
# Following cases do the similar, but with a different package manager
break
}
"yarn" {
yarn add --exact "@tact-lang/compiler@$env:SECOND_LATEST"
yarn upgrade "@tact-lang/compiler"
break
}
"bun" {
bun add --exact "@tact-lang/compiler@$env:SECOND_LATEST"
bun update --latest "@tact-lang/compiler"
break
}
"pnpm" {
pnpm add --save-exact "@tact-lang/compiler@$env:SECOND_LATEST"
pnpm upgrade "@tact-lang/compiler"
break
}
default {
Write-Host "Invalid input!"
exit 1
}
}
# Check that commands worked and the latest version is installed
if ($(jq -r '.dependencies."@tact-lang/compiler"' package.json) -ne $env:LATEST) { exit 1 }

- name: (non-Windows-${{ matrix.package-manager }}) Override a version using installation commands
if: ${{ matrix.os != 'windows-latest' }}
env:
PM: ${{ matrix.package-manager }}
working-directory: tact-template
run: |
# Run the installation commands
case "$PM" in
npm)
# Install the second-latest version
npm i --save-exact "@tact-lang/compiler@$SECOND_LATEST"
# Update to the latest version (using the command from the docs)
npm update --save "@tact-lang/compiler"
# Following cases do the similar, but with a different package manager
yarn)
yarn add --exact "@tact-lang/compiler@$SECOND_LATEST"
yarn upgrade "@tact-lang/compiler"
;;
bun)
bun add --exact "@tact-lang/compiler@$SECOND_LATEST"
bun update --latest "@tact-lang/compiler"
;;
pnpm)
pnpm add --save-exact "@tact-lang/compiler@$SECOND_LATEST"
pnpm upgrade "@tact-lang/compiler"
;;
*)
echo "Invalid input!"
exit 1
;;
esac
# Check that commands worked and the latest version is installed
test $(jq -r '.dependencies."@tact-lang/compiler"' package.json) = "$LATEST"

# Test overrides with install commands,
# i.e. version pinning, as described in the Tact docs
test-pin-version:
needs: get-versions
env:
LATEST: ${{ needs.get-versions.outputs.latest }}
SECOND_LATEST: ${{ needs.get-versions.outputs.second_latest }}
strategy:
fail-fast: false
matrix:
node-version: [18, 22]
os: [ubuntu-latest, windows-latest, macos-latest]
package-manager: [npm, yarn, pnpm, bun]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
depth: 1 # the latest commit is enough

- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

- uses: oven-sh/setup-bun@v2
if: ${{ matrix.package-manager == 'bun' }}

- name: Clone tact-template
run: git clone --depth 1 https://github.com/tact-lang/tact-template

- name: Project cleanup
uses: ./.github/actions/node-project-cleanup
with:
cwd: tact-template

- name: Install missing package managers
working-directory: tact-template
run: |
# Yarn v1
# NOTE: consider also adding yarn v4 to the mix (through corepack & node 20+)
${{ matrix.package-manager == 'yarn' && 'npm i -g yarn' || 'echo noop' }}
# PNPM
${{ matrix.package-manager == 'pnpm' && 'npm i -g pnpm' || 'echo noop' }}

# --- NOTE: up until this point everything should be almost identical to test-upgrade job ---

- name: (Windows-${{ matrix.package-manager }}) Override a version using installation commands
if: ${{ matrix.os == 'windows-latest' }}
env:
PM: ${{ matrix.package-manager }}
working-directory: tact-template
run: |
# Run the installation commands
switch ($PM) {
"npm" {
# Install the second-latest version
npm i --save-exact "@tact-lang/compiler@$env:SECOND_LATEST"
# Override it with the latest version (using the command from the docs)
npm i --save-exact "@tact-lang/compiler@$env:LATEST"
# Following cases do the similar, but with a different package manager
break
}
"yarn" {
yarn add --exact "@tact-lang/compiler@$env:SECOND_LATEST"
yarn add --exact "@tact-lang/compiler@$env:LATEST"
break
}
"bun" {
bun add --exact "@tact-lang/compiler@$env:SECOND_LATEST"
bun add --exact "@tact-lang/compiler@$env:LATEST"
break
}
"pnpm" {
pnpm add --save-exact "@tact-lang/compiler@$env:SECOND_LATEST"
pnpm add --save-exact "@tact-lang/compiler@$env:LATEST"
break
}
default {
Write-Host "Invalid input!"
exit 1
}
}
# Check that commands worked and the latest version is installed
if ($(jq -r '.dependencies."@tact-lang/compiler"' package.json) -ne $env:LATEST) { exit 1 }

- name: (non-Windows-${{ matrix.package-manager }}) Override a version using installation commands
if: ${{ matrix.os != 'windows-latest' }}
env:
PM: ${{ matrix.package-manager }}
working-directory: tact-template
run: |
# Run the installation commands
case "$PM" in
npm)
# Install the second-latest version
npm i --save-exact "@tact-lang/compiler@$SECOND_LATEST"
# Override it with the latest version (using the command from the docs)
npm i --save-exact "@tact-lang/compiler@$LATEST"
# Following cases do the similar, but with a different package manager
yarn)
yarn add --exact "@tact-lang/compiler@$SECOND_LATEST"
yarn add --exact "@tact-lang/compiler@$LATEST"
;;
bun)
bun add --exact "@tact-lang/compiler@$SECOND_LATEST"
bun add --exact "@tact-lang/compiler@$LATEST"
;;
pnpm)
pnpm add --save-exact "@tact-lang/compiler@$SECOND_LATEST"
pnpm add --save-exact "@tact-lang/compiler@$LATEST"
;;
*)
echo "Invalid input!"
exit 1
;;
esac
# Check that commands worked and the latest version is installed
test $(jq -r '.dependencies."@tact-lang/compiler"' package.json) = "$LATEST"
Loading
Loading