diff --git a/gpg-sign/action.yml b/gpg-sign/action.yml index 171451b..e4765fb 100644 --- a/gpg-sign/action.yml +++ b/gpg-sign/action.yml @@ -16,7 +16,7 @@ runs: id: filenames run: | set -eux - export FILENAMES=${{inputs.filenames}} + FILENAMES="${{inputs.filenames}}" if [[ $FILENAMES =~ '*' ]]; then FILENAMES=$(ls $FILENAMES | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g') fi diff --git a/node/generate_release.mjs b/node/generate_release.mjs new file mode 100644 index 0000000..f07ab1a --- /dev/null +++ b/node/generate_release.mjs @@ -0,0 +1,47 @@ +import { readFileSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const args = process.argv.slice(2); +if (!(args.length === 3 || args.length === 4)) { + console.error( + `usage: generate_release.js `, + ); + process.exit(1); +} + +const [npmPackage, branch, tag, assetGroup] = args; + +const isNative = + npmPackage === "kerberos" || npmPackage === "mongodb-client-encryption"; +const template = readFileSync( + join(__dirname, "./release_template.yml"), + "utf-8", +); + +const EVERGREEN_PROJECTS = { + mongodb: "mongo-node-driver-next", + bson: "js-bson", +}; + +const generated = template + .replaceAll("RELEASE_BRANCH", branch) + .replaceAll("RELEASE_PACKAGE", npmPackage) + .replaceAll("RELEASE_TAG", tag) + .replaceAll("EVERGREEN_PROJECT", EVERGREEN_PROJECTS[npmPackage] ?? "") + .replaceAll("IGNORE_INSTALL_SCRIPTS", isNative) + .replaceAll("SILK_ASSET_GROUP", assetGroup ? `'${assetGroup}'` : "''"); + +const project = EVERGREEN_PROJECTS[npmPackage]; +if (!project) { + const final = generated + .split("\n") + .filter((line) => !line.includes("evergreen")) + .join("\n"); + process.stdout.write(final); + process.exit(); +} + +process.stdout.write(generated); diff --git a/node/get_version_info/action.yml b/node/get_version_info/action.yml new file mode 100644 index 0000000..9d76e0f --- /dev/null +++ b/node/get_version_info/action.yml @@ -0,0 +1,18 @@ +name: Publish Release Asset to S3 +description: "Publish Asset to S3" +inputs: + npm_package_name: + description: the npm package name + required: true + +runs: + using: composite + steps: + - name: Get release version and release package file name + id: get_version + shell: bash + run: | + package_version=$(jq --raw-output '.version' package.json) + echo "package_version=${package_version}" >> "$GITHUB_ENV" + echo "package_file=${{ inputs.npm_package_name }}-${package_version}.tgz" >> "$GITHUB_ENV" + echo "commit=$(git rev-parse HEAD)" >> $GITHUB_ENV diff --git a/node/publish_asset_to_s3/action.yml b/node/publish_asset_to_s3/action.yml deleted file mode 100644 index 35533c4..0000000 --- a/node/publish_asset_to_s3/action.yml +++ /dev/null @@ -1,39 +0,0 @@ - -name: Publish Release Asset to S3 -description: "Publish Asset to S3" -inputs: - version: - description: "The published version" - required: true - product_name: - description: "The name of the product" - required: true - file: - description: file to upload - required: true - dry_run: - description: "Whether this is a dry run" - required: false - default: 'false' - -runs: - using: composite - steps: - - name: Run publish script - shell: bash - run: | - set -eux - if [ "$DRY_RUN" == "false" ]; then - echo "Uploading Release Reports" - TARGET=s3://${AWS_BUCKET}/${PRODUCT_NAME}/${VERSION}/${FILE} - aws s3 cp $FILE $TARGET - else - echo "Dry run, not uploading to S3 or creating GitHub Release" - echo "Would upload $FILE" - cat $FILE - fi - env: - VERSION: ${{ inputs.version }} - PRODUCT_NAME: ${{ inputs.product_name }} - DRY_RUN: ${{ inputs.dry_run }} - FILE: ${{ inputs.file }} diff --git a/node/release_template.yml b/node/release_template.yml new file mode 100644 index 0000000..ee5eb93 --- /dev/null +++ b/node/release_template.yml @@ -0,0 +1,105 @@ +on: + push: + branches: [RELEASE_BRANCH] + workflow_dispatch: {} + +permissions: + contents: write + pull-requests: write + id-token: write + +name: release-RELEASE_TAG + +jobs: + release_please: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + steps: + - id: release + uses: googleapis/release-please-action@v4 + with: + target-branch: RELEASE_BRANCH + + build: + needs: [release_please] + name: "Perform any build or bundling steps, as necessary." + uses: ./.github/workflows/build.yml + + ssdlc: + needs: [release_please, build] + permissions: + # required for all workflows + security-events: write + id-token: write + contents: write + environment: release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Node and dependencies + uses: mongodb-labs/drivers-github-tools/node/setup@v2 + with: + ignore_install_scripts: IGNORE_INSTALL_SCRIPTS + + - name: Load version and package info + uses: mongodb-labs/drivers-github-tools/node/get_version_info@v2 + with: + npm_package_name: RELEASE_PACKAGE + + - name: actions/compress_sign_and_upload + uses: mongodb-labs/drivers-github-tools/node/sign_node_package@v2 + with: + aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} + aws_region_name: us-east-1 + aws_secret_id: ${{ secrets.AWS_SECRET_ID }} + npm_package_name: RELEASE_PACKAGE + dry_run: ${{ needs.release_please.outputs.release_created == '' }} + + - name: Copy sbom file to release assets + shell: bash + if: ${{ SILK_ASSET_GROUP == '' }} + run: cp sbom.json ${{ env.S3_ASSETS }}/sbom.json + + # only used for mongodb-client-encryption + - name: Augment SBOM and copy to release assets + if: ${{ SILK_ASSET_GROUP != '' }} + uses: mongodb-labs/drivers-github-tools/sbom@v2 + with: + silk_asset_group: SILK_ASSET_GROUP + sbom_file_name: sbom.json + + - name: Generate authorized pub report + uses: mongodb-labs/drivers-github-tools/full-report@v2 + with: + release_version: ${{ env.package_version }} + product_name: RELEASE_PACKAGE + sarif_report_target_ref: RELEASE_BRANCH + third_party_dependency_tool: n/a + dist_filenames: artifacts/* + token: ${{ github.token }} + sbom_file_name: sbom.json + evergreen_project: EVERGREEN_PROJECT + evergreen_commit: ${{ env.commit }} + + - uses: mongodb-labs/drivers-github-tools/upload-s3-assets@v2 + with: + version: ${{ env.package_version }} + product_name: RELEASE_PACKAGE + dry_run: ${{ needs.release_please.outputs.release_created == '' }} + + publish: + needs: [release_please, ssdlc, build] + environment: release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Node and dependencies + uses: mongodb-labs/drivers-github-tools/node/setup@v2 + + - run: npm publish --provenance --tag=RELEASE_TAG + if: ${{ needs.release_please.outputs.release_created }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/node/setup/action.yml b/node/setup/action.yml new file mode 100644 index 0000000..90799d0 --- /dev/null +++ b/node/setup/action.yml @@ -0,0 +1,23 @@ +name: Setup +description: "Installs node, driver dependencies, and builds source" +inputs: + ignore_install_scripts: + description: Should we ignore postinstall scripts? + default: "false" + +runs: + using: composite + steps: + - uses: actions/setup-node@v4 + with: + node-version: "lts/*" + cache: "npm" + registry-url: "https://registry.npmjs.org" + - run: npm install -g npm@latest + shell: bash + - run: npm clean-install + if: ${{ inputs.ignore_install_scripts == 'false' }} + shell: bash + - run: npm clean-install --ignore-scripts + if: ${{ inputs.ignore_install_scripts == 'true' }} + shell: bash diff --git a/node/sign_node_package/action.yml b/node/sign_node_package/action.yml new file mode 100644 index 0000000..63b607a --- /dev/null +++ b/node/sign_node_package/action.yml @@ -0,0 +1,90 @@ +name: Compress, Sign and Upload to GH Release +description: "Compresses package and signs with garasign and uploads to GH release" + +inputs: + aws_role_arn: + description: "AWS role input for drivers-github-tools/gpg-sign@v2" + required: true + aws_region_name: + description: "AWS region name input for drivers-github-tools/gpg-sign@v2" + required: true + aws_secret_id: + description: "AWS secret id input for drivers-github-tools/gpg-sign@v2" + required: true + npm_package_name: + description: "The name for the npm package this repository represents" + required: true + dry_run: + description: "Should we upload files to the release?" + required: false + default: "false" + artifact_directory: + description: The directory in which to output signatures. + default: artifacts + sign_native: + description: Download and sign native packages + default: "false" + +runs: + using: composite + steps: + - uses: actions/download-artifact@v4 + if: ${{ inputs.sign_native == 'true' }} + + - run: npm pack + shell: bash + + - name: Make signatures directory + shell: bash + run: | + mkdir ${{ inputs.artifact_directory }} + + - name: Load version and package info + uses: mongodb-labs/drivers-github-tools/node/get_version_info@v2 + with: + npm_package_name: ${{ inputs.npm_package_name }} + + - name: Set up drivers-github-tools + uses: mongodb-labs/drivers-github-tools/setup@v2 + with: + aws_region_name: ${{ inputs.aws_region_name }} + aws_role_arn: ${{ inputs.aws_role_arn }} + aws_secret_id: ${{ inputs.aws_secret_id }} + + - name: Determine what files to sign (native packages, works with glob patterns of build artifacts) + if: ${{ inputs.sign_native == 'true' }} + shell: bash + run: | + FILENAMES="build-*/*.tar.gz" + if [[ $FILENAMES =~ '*' ]]; then + FILENAMES=$(ls $FILENAMES | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g') + fi + FILENAMES="$FILENAMES ${{ env.package_file }}" + echo "FILES_TO_SIGN=${FILENAMES}" >> "$GITHUB_ENV" + + - name: Determine what files to sign (non-native packages, with only the release tarball) + if: ${{ inputs.sign_native != 'true' }} + shell: bash + run: | + FILENAMES="${{ env.package_file }}" + echo "FILES_TO_SIGN=${FILENAMES}" >> "$GITHUB_ENV" + + - name: Create detached signature + uses: mongodb-labs/drivers-github-tools/gpg-sign@v2 + with: + filenames: ${{ env.FILES_TO_SIGN }} + env: + RELEASE_ASSETS: ${{ inputs.artifact_directory }} + + - name: Copy the tarballs to the artifacts directory + shell: bash + run: | + for filename in ${{ env.FILES_TO_SIGN }}; do cp ${filename} artifacts/; done + ls -la artifacts/ + + - name: "Upload release artifacts" + if: ${{ inputs.dry_run == false }} + run: gh release upload v${{ env.package_version }} artifacts/*.* + shell: bash + env: + GH_TOKEN: ${{ github.token }}