diff --git a/.changeset/angry-pianos-boil.md b/.changeset/angry-pianos-boil.md new file mode 100644 index 00000000000..9bdf912afee --- /dev/null +++ b/.changeset/angry-pianos-boil.md @@ -0,0 +1,4 @@ +--- +--- + +chore: migrate `pr` + `next` package publishing to GitHub Packages diff --git a/.github/actions/ci-setup/action.yaml b/.github/actions/ci-setup/action.yaml index 54702c7939d..d7aff1c20e8 100644 --- a/.github/actions/ci-setup/action.yaml +++ b/.github/actions/ci-setup/action.yaml @@ -6,6 +6,9 @@ inputs: pnpm-version: description: "PNPM version" default: 9.4.0 + registry-url: + description: "Registry URL" + default: "https://registry.npmjs.org" runs: using: "composite" steps: @@ -19,7 +22,7 @@ runs: uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} - registry-url: "https://registry.npmjs.org" + registry-url: ${{ inputs.registry-url }} - name: Setup PNPM uses: pnpm/action-setup@v4 diff --git a/.github/actions/pr-release/action.yaml b/.github/actions/pr-release/action.yaml deleted file mode 100644 index 1e2bddb8e10..00000000000 --- a/.github/actions/pr-release/action.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Publish PR to NPM" -inputs: - npm-token: - description: "NPM token for authenticating to NPM registry" - required: true - - github-token: - description: "GitHub token for authenticating to GitHub" - required: true - - pr-number: - description: "PR number" - default: ${{ github.event.pull_request.number }} - -outputs: - published_version: - description: "Published version of the PR" - value: ${{ steps.release.outputs.published_version }} - -runs: - using: "composite" - steps: - - name: Ensure NPM access - shell: bash - run: npm whoami - env: - NODE_AUTH_TOKEN: ${{ inputs.npm-token }} - - - name: Release to @pr-${{ inputs.pr-number }} tag on npm - id: release - shell: bash - run: | - pnpm changeset:next - git add .changeset/fuel-labs-ci.md - pnpm changeset version --snapshot pr-${{ inputs.pr-number }} - changetsets=$(pnpm changeset publish --tag pr-${{ inputs.pr-number }}) - published_version=$(echo "$changetsets" | grep -oP '@\K([0-9]+\.){2}[0-9]+-pr-${{ inputs.pr-number }}-\d+' | head -1) - echo "published_version=$published_version" >> $GITHUB_OUTPUT - env: - NODE_AUTH_TOKEN: ${{ inputs.npm-token }} - GITHUB_TOKEN: ${{ inputs.github-token }} diff --git a/.github/workflows/pr-release.yaml b/.github/workflows/pr-release.yaml new file mode 100644 index 00000000000..26bce5e402d --- /dev/null +++ b/.github/workflows/pr-release.yaml @@ -0,0 +1,71 @@ +name: Release to @pr- tag on GitHub Packages +on: + pull_request: + workflow_dispatch: + +jobs: + release-pr: + name: "Release PR to GitHub Packages" + runs-on: ubuntu-latest + # comment out if:false to enable release PR to GitHub Packages + if: false + permissions: write-all + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.ref }} + + - name: CI Setup + uses: ./.github/actions/ci-setup + + - name: Create .npmrc + run: | + cat << EOF > "$HOME/.npmrc" + //npm.pkg.github.com/:_authToken=$GITHUB_TOKEN + @FuelLabs:registry=https://npm.pkg.github.com + EOF + env: + HOME: ${{ github.workspace }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Build + run: pnpm build + + - name: Release to @pr-${{ github.event.pull_REQUEST.NUMBER }} tag on GitHub Packages + id: release + shell: bash + run: | + pnpm changeset:next + pnpm changeset version --snapshot pr-${{ github.event.pull_REQUEST.NUMBER }} + changetsets=$(pnpm changeset publish --tag pr-${{ github.event.pull_REQUEST.NUMBER }}) + published_version=$(echo "$changetsets" | grep -oP '@\K([0-9]+\.){2}[0-9]+-pr-${{ github.event.pull_REQUEST.NUMBER }}-\d+' | head -1) + echo "published_version=$published_version" >> $GITHUB_OUTPUT + env: + NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HOME: ${{ github.workspace }} + npm_config_registry: "https://npm.pkg.github.com" + + - uses: mshick/add-pr-comment@v2 + with: + message: | + This PR is published in GitHub Packages with version **${{ steps.release.outputs.published_version }}** + + Install using the following command: + + ```bash + pnpm add @fuellabs/fuels@${{ steps.release.outputs.published_version }} + ``` + + Or update your package.json: + + ```json + "dependencies": { + "@fuellabs/fuels": "${{ steps.release.outputs.published_version }}" + } + ``` + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6bfc54d0261..2cd3cc4ad08 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -87,7 +87,18 @@ jobs: LATEST_RELEASE: ${{ env.LATEST_RELEASE }} RELEASE_VERSION_HIGHER_THAN_LATEST: ${{ env.RELEASE_VERSION_HIGHER_THAN_LATEST }} - - name: Release to @next tag on npm + - name: Create .npmrc + if: github.ref_name == 'master' && steps.changesets.outputs.published != 'true' + run: | + cat << EOF > "$HOME/.npmrc" + //npm.pkg.github.com/:_authToken=$GITHUB_TOKEN + @FuelLabs:registry=https://npm.pkg.github.com + EOF + env: + HOME: ${{ github.workspace }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Release to @next tag on GitHub Packages if: github.ref_name == 'master' && steps.changesets.outputs.published != 'true' run: | git checkout master @@ -105,12 +116,14 @@ jobs: fi pnpm changeset:next - git add .changeset/fuel-labs-ci.md pnpm changeset version --snapshot next pnpm changeset publish --tag next env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_DEPLOY_TOKEN }} + NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HOME: ${{ github.workspace }} + npm_config_registry: "https://npm.pkg.github.com" # ensure docs are always deployed after merge of changeset PR - name: Get the last commit message and set env vars diff --git a/package.json b/package.json index fc72e1793b6..03ec518ab62 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "prettier:format": "prettier --write packages --write apps/docs", "verify:package-exports": "tsx ./scripts/verify-package-exports", "changeset:publish": "tsx ./scripts/changeset/changeset-publish", - "changeset:next": "tsx ./scripts/changeset/changeset-next", + "changeset:next": "tsx ./scripts/changeset/changeset-next.mts", "changeset:version-with-docs": "tsx ./scripts/changeset/changeset-version-with-docs", "changeset:update-changelog": "tsx ./scripts/changeset/update-changelog.mts", "changeset:get-latest-release": "tsx ./scripts/changeset/get-latest-release.mts", diff --git a/scripts/changeset/changeset-next.mts b/scripts/changeset/changeset-next.mts new file mode 100644 index 00000000000..32e47fb527f --- /dev/null +++ b/scripts/changeset/changeset-next.mts @@ -0,0 +1,84 @@ +import { execSync } from "child_process"; +import { readFileSync, writeFileSync } from "fs"; +import { globSync } from "glob"; + +const CHANGESET_CONFIG_PATH = ".changeset/config.json"; +const GITHUB_ORGANIZATION_SCOPE = "@FuelLabs"; + +const formatPackageName = (name: string) => + `${GITHUB_ORGANIZATION_SCOPE}/${name.replace("@fuel-ts/", "")}`; + +const formatPackageJsonContents = (contents: { name: string }) => ({ + ...contents, + // We need to add the GitHub organization name to the scope to publish to GitHub + // We also need to strip off and prefixes (e.g. '@fuel-ts/' -> '') + name: formatPackageName(contents.name), + // We also need a repository field to publish to GitHub + repository: "https://github.com/FuelLabs/fuels-ts", +}); + +/** + * Gather all the package.json files to be published + */ +const packages = globSync("**/package.json") + // Read in the package.json file + .map((fileName) => { + const packageJson = JSON.parse(readFileSync(fileName, "utf-8")); + return { + path: fileName, + contents: packageJson, + }; + }) + // Filter out private packages + .filter((pkg) => !pkg.contents.private); + +// Format the package contents to be used to publish to GitHub +packages + .map((pkg) => ({ + path: pkg.path, + contents: formatPackageJsonContents(pkg.contents), + })) + .forEach((pkg) => { + // Write the formatted package.json files + writeFileSync(pkg.path, JSON.stringify(pkg.contents, null, 2)); + // Add the formatted package.json files to the git index + execSync(`git add ${pkg.path}`); + }); + +/** + * Update the changeset config to include the FuelLabs organization scope + */ +const changesetConfigContents = JSON.parse( + readFileSync(CHANGESET_CONFIG_PATH, "utf-8"), +); +const changesetConfig = { + ...changesetConfigContents, + fixed: [[`${GITHUB_ORGANIZATION_SCOPE}/*`]], +}; +writeFileSync(CHANGESET_CONFIG_PATH, JSON.stringify(changesetConfig, null, 2)); +execSync(`git add ${CHANGESET_CONFIG_PATH}`); + +/** + * Update all pre-existing changeset package scopes + */ +const packageNames = packages.map((pkg) => pkg.contents.name).join("|"); +const regex = new RegExp(packageNames, "g"); +globSync(".changeset/*.md") + .map((fileName) => { + const contents = readFileSync(fileName, "utf-8"); + return { + path: fileName, + contents, + }; + }) + .forEach((pkg) => { + writeFileSync(pkg.path, pkg.contents.replace(regex, formatPackageName)); + execSync(`git add ${pkg.path}`); + }); + +/** + * Add a changeset for the next `fuels` version + */ +const output = `---\n"${GITHUB_ORGANIZATION_SCOPE}/fuels": patch\n---\n\nincremental\n`; +writeFileSync(".changeset/fuel-labs-ci.md", output); +execSync(`git add .changeset/fuel-labs-ci.md`); diff --git a/scripts/changeset/changeset-next.ts b/scripts/changeset/changeset-next.ts deleted file mode 100644 index 91ce3b26a60..00000000000 --- a/scripts/changeset/changeset-next.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { writeFileSync } from 'node:fs'; - -const output = `---\n"fuels": patch\n---\n\nincremental\n`; -writeFileSync('.changeset/fuel-labs-ci.md', output);