diff --git a/.github/workflows/dotnet-build-jfrog.yml b/.github/workflows/dotnet-build-jfrog.yml index 25dd187..cb16467 100755 --- a/.github/workflows/dotnet-build-jfrog.yml +++ b/.github/workflows/dotnet-build-jfrog.yml @@ -86,8 +86,8 @@ on: dotnet_version: value: ${{ inputs.dotnet_version }} - jfrog_build_name_build: - description: The JFrog build name for the 'build' step is suffixed with '-build'. + jfrog_build_name: + description: The JFrog build name for the 'dotnet-build' step is suffixed with '-dotnet-build'. value: ${{ jobs.build.outputs.jfrog_build_name }} persisted_workspace_artifact_name: @@ -107,8 +107,8 @@ jobs: working-directory: ${{ inputs.project_directory }} outputs: - persisted_workspace_artifact_name: ${{ steps.persist-workspace.outputs.artifact_name }} jfrog_build_name: ${{ env.JFROG_CLI_BUILD_NAME }} + persisted_workspace_artifact_name: ${{ steps.persist-workspace.outputs.artifact_name }} env: CONFIGURATION: ${{ inputs.configuration }} @@ -116,7 +116,7 @@ jobs: NUGETHASHFILES: "${{ inputs.project_directory }}**/*.csproj" PROJECTDIRECTORY: ${{ inputs.project_directory }} JFROG_API_BASE_URL: ${{ inputs.jfrog_api_base_url }} - JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}-build" + JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}-dotnet-build" JFROG_CLI_BUILD_NUMBER: ${{ inputs.jfrog_build_number }} JFROG_CLI_LOG_LEVEL: ${{ inputs.jfrog_cli_log_level }} JFROG_NUGET_FEED_REPO: ${{ inputs.jfrog_nuget_feed_repo }} @@ -131,6 +131,12 @@ jobs: regex_pattern: "^debug|release$" value: ${{ env.CONFIGURATION }} + - name: Validate inputs.jfrog_build_name + uses: ritterim/public-github-actions/actions/regex-validator@v1.10.0 + with: # This regex pattern is a bit of a guess + regex_pattern: '^[A-Za-z0-9\-]{5,55}$' + value: ${{ inputs.jfrog_build_name }} + - name: Validate inputs.jfrog_nuget_feed_repo uses: ritterim/public-github-actions/actions/jfrog-artifactory-repository-name-validator@v1.14.1 with: diff --git a/.github/workflows/dotnet-pack-jfrog.yml b/.github/workflows/dotnet-pack-jfrog.yml index 1cc014b..c088e55 100644 --- a/.github/workflows/dotnet-pack-jfrog.yml +++ b/.github/workflows/dotnet-pack-jfrog.yml @@ -38,7 +38,7 @@ on: type: string jfrog_artifactory_repository: - description: 'JFrog Artifactory repository identifier.' + description: 'JFrog Artifactory repository identifier where artifacts will be uploaded to.' required: true type: string @@ -47,11 +47,6 @@ on: required: true type: string - jfrog_build_name_build: - description: 'JFrog build name from the build step. We append that build to the pack step build-info.' - required: true - type: string - jfrog_build_number: description: 'JFrog build number. Can be an integer, a semantic version, or a string.' required: true @@ -96,6 +91,10 @@ on: artifact_name: value: ${{ inputs.artifact_name }} + jfrog_build_name: + description: The JFrog build name for the 'dotnet-pack' step is suffixed with '-dotnet-pack'. + value: ${{ jobs.pack.outputs.jfrog_build_name }} + jobs: pack: @@ -105,6 +104,9 @@ jobs: run: working-directory: ${{ inputs.project_directory }} + outputs: + jfrog_build_name: ${{ env.JFROG_CLI_BUILD_NAME }} + env: ARTIFACTNAME: ${{ inputs.artifact_name }} ARTIFACTPATHSPEC: "${{ inputs.project_directory }}artifacts/*.*nupkg" @@ -113,8 +115,7 @@ jobs: JFROG_SERVER_ID: setup-jfrog-cli-server JFROG_API_BASE_URL: ${{ inputs.jfrog_api_base_url }} JFROG_ARTIFACTORY_REPOSITORY: ${{ inputs.jfrog_artifactory_repository }} - JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}" - JFROG_CLI_BUILD_NAME_BUILD: "${{ inputs.jfrog_build_name_build }}" + JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}-dotnet-pack" JFROG_CLI_BUILD_NUMBER: ${{ inputs.jfrog_build_number }} JFROG_CLI_LOG_LEVEL: ${{ inputs.jfrog_cli_log_level }} JFROG_NUGET_FEED_REPO: ${{ inputs.jfrog_nuget_feed_repo }} @@ -138,6 +139,12 @@ jobs: regex_pattern: "^debug|release$" value: ${{ env.CONFIGURATION }} + - name: Validate inputs.jfrog_build_name + uses: ritterim/public-github-actions/actions/regex-validator@v1.10.0 + with: # This regex pattern is a bit of a guess + regex_pattern: '^[A-Za-z0-9\-]{5,55}$' + value: ${{ inputs.jfrog_build_name }} + - name: Validate inputs.project_directory uses: ritterim/public-github-actions/actions/path-name-validator@v1.9.2 with: @@ -254,8 +261,5 @@ jobs: working-directory: ${{ env.ARTIFACTRELATIVEFOLDER }} continue-on-error: true - - name: Append the JFrog "-build" build-info to this build-info - run: jf rt build-append "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" "${JFROG_CLI_BUILD_NAME_BUILD}" "${JFROG_CLI_BUILD_NUMBER}" - - name: Push JFrog Build Information run: jf rt build-publish "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" diff --git a/.github/workflows/dotnet-publish-jfrog.yml b/.github/workflows/dotnet-publish-jfrog.yml new file mode 100644 index 0000000..072e5c2 --- /dev/null +++ b/.github/workflows/dotnet-publish-jfrog.yml @@ -0,0 +1,315 @@ +name: Publish (.NET) + +# The "jfrog/setup-jfrog-cli" action requires "id-token: write" or else you will get +# an error about: "Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable". + +# Performs only the 'dotnet publish'. + +permissions: + contents: read + id-token: write + packages: read + +on: + + workflow_call: + + inputs: + + artifact_name: + required: true + type: string + + artifact_retention_days: + required: false + type: number + default: 90 + + configuration: + required: false + type: string + default: "Release" + + dotnet_version: + required: false + type: string + default: "6.0" + + jfrog_api_base_url: + description: 'JFrog platform url (for example: https://rimdev.jfrog.io/)' + required: true + type: string + + jfrog_artifactory_repository: + description: 'JFrog Artifactory repository identifier where artifacts will be uploaded to.' + required: true + type: string + + jfrog_build_name: + description: 'JFrog build name.' + required: true + type: string + + jfrog_build_number: + description: 'JFrog build number. Can be an integer, a semantic version, or a string.' + required: true + type: string + + jfrog_cli_log_level: + description: 'Set the log level for the JFrog CLI. Default is ERROR. Values are: (DEBUG, INFO, WARN, ERROR).' + required: false + default: ERROR + type: string + + jfrog_nuget_feed_repo: + description: The 'virtual' JFrog Artifactory repository identifier for NuGet package retrieval. + required: true + type: string + + jfrog_oidc_provider_name: + description: The OIDC Integration Provider Name to use for authentication from the GitHub Action to the JFrog instance. + required: true + type: string + + persisted_workspace_artifact_name: + description: Name of the artifact which contains the persisted workspace directory. + required: true + type: string + + project_directory: + required: false + type: string + default: "./" + + publish_working_directory: + description: The directory where the 'dotnet publish' command should be run. This is going to be the folder containing the Host/API main project. + required: true + type: string + + informational_version: + required: true + type: string + + version: + required: true + type: string + + outputs: + + artifact_name: + value: ${{ jobs.publish.outputs.artifact_name }} + + artifact_filename: + value: ${{ jobs.publish.outputs.artifact_filename }} + + jfrog_build_name: + description: The JFrog build name for the 'dotnet-publish' step is suffixed with '-dotnet-publish'. + value: ${{ jobs.publish.outputs.jfrog_build_name }} + +jobs: + + publish: + name: Publish (.NET) + runs-on: ubuntu-latest + defaults: + run: + working-directory: ${{ inputs.project_directory }} + + outputs: + artifact_name: ${{ inputs.artifact_name }} + artifact_filename: ${{ env.ZIPFILENAME }} + jfrog_build_name: ${{ env.JFROG_CLI_BUILD_NAME }} + + env: + ARTIFACTNAME: ${{ inputs.artifact_name }} + CONFIGURATION: ${{ inputs.configuration }} + JFROG_SERVER_ID: setup-jfrog-cli-server + JFROG_API_BASE_URL: ${{ inputs.jfrog_api_base_url }} + JFROG_ARTIFACTORY_REPOSITORY: ${{ inputs.jfrog_artifactory_repository }} + JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}-dotnet-publish" + JFROG_CLI_BUILD_NUMBER: ${{ inputs.jfrog_build_number }} + JFROG_CLI_LOG_LEVEL: ${{ inputs.jfrog_cli_log_level }} + JFROG_NUGET_FEED_REPO: ${{ inputs.jfrog_nuget_feed_repo }} + JFROG_OIDC_PROVIDER_NAME: ${{ inputs.jfrog_oidc_provider_name }} + NUGETHASHFILES: "${{ inputs.project_directory }}**/*.csproj" + PROJECTDIRECTORY: ${{ inputs.project_directory }} + PUBLISH_WORKING_DIRECTORY: ${{ inputs.publish_working_directory }} + INFORMATIONALVERSION: ${{ inputs.informational_version }} + VERSION: ${{ inputs.version }} + ZIPFILENAME: "${{ inputs.artifact_name }}.zip" + + steps: + + - name: Validate inputs.artifact_name + uses: ritterim/public-github-actions/actions/file-name-validator@v1.9.2 + with: + file_name: ${{ env.ARTIFACTNAME }} + + - name: Validate inputs.configuration + uses: ritterim/public-github-actions/actions/regex-validator@v1.9.2 + with: + case_sensitive: false + regex_pattern: "^debug|release$" + value: ${{ env.CONFIGURATION }} + + - name: Validate inputs.jfrog_build_name + uses: ritterim/public-github-actions/actions/regex-validator@v1.10.0 + with: # This regex pattern is a bit of a guess + regex_pattern: '^[A-Za-z0-9\-]{5,55}$' + value: ${{ inputs.jfrog_build_name }} + + - name: Validate inputs.project_directory + uses: ritterim/public-github-actions/actions/path-name-validator@v1.9.2 + with: + path_name: ${{ env.PROJECTDIRECTORY }} + + - name: Validate inputs.publish_working_directory + uses: ritterim/public-github-actions/actions/path-name-validator@v1.9.2 + with: + path_name: ${{ env.PUBLISH_WORKING_DIRECTORY }} + + - name: Validate inputs.informational_version + uses: ritterim/public-github-actions/actions/version-number-validator@v1.9.2 + with: + version: ${{ env.INFORMATIONALVERSION }} + + - name: Validate inputs.version + uses: ritterim/public-github-actions/actions/version-number-validator@v1.9.2 + with: + version: ${{ env.VERSION }} + + - name: Validate ZIPFILENAME + uses: ritterim/public-github-actions/actions/file-name-validator@v1.9.2 + with: + file_name: ${{ env.ZIPFILENAME }} + + - name: github context debug information + working-directory: ./ + run: | + echo "github.base_ref=${{ github.base_ref }}" + echo "github.head_ref=${{ github.head_ref }}" + echo "github.ref=${{ github.ref }}" + echo "github.ref_name=${{ github.ref_name }}" + echo "github.repository=${{ github.repository }}" + echo "github.repository_owner=${{ github.repository_owner }}" + echo "github.run_id=${{ github.run_id }}" + echo "github.run_number=${{ github.run_number }}" + echo "github.run_attempt=${{ github.run_attempt }}" + echo "github.sha=${{ github.sha }}" + + - name: Checkout Project + uses: actions/checkout@v3 + with: + ref: ${{ github.ref }} + + - name: Restore Workspace + uses: ritterim/public-github-actions/forks/persist-workspace@v1.9.2 + with: + action: retrieve + artifact_name: ${{ inputs.persisted_workspace_artifact_name }} + + # This creates the setup-jfrog-cli-server server ID + - name: Install JFrog CLI + uses: jfrog/setup-jfrog-cli@v4 + env: + JF_URL: ${{ env.JFROG_API_BASE_URL }} + with: + oidc-provider-name: ${{ env.JFROG_OIDC_PROVIDER_NAME }} + + - name: jf config show + run: jf config show + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ inputs.dotnet_version }} + source-url: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json + env: + NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} + + - name: Setup ~/.nuget/packages cache + uses: actions/cache@v3 + with: + key: nuget-packages-${{ runner.os }}-${{ hashFiles(env.NUGETHASHFILES) }} + path: | + ~/.nuget/packages + + - run: dotnet nuget list source + + - name: Remove any pre-defined NuGet sources + run: | + sources=$(dotnet nuget list source | grep '\[Enabled\]' | awk '{print $2}') + echo "$sources" + echo "$sources" | xargs -I % dotnet nuget remove source % + + - run: dotnet nuget list source + + - name: Configure .NET / NuGet using JFrog CLI + run: jf dotnet-config --global --server-id-resolve setup-jfrog-cli-server --repo-resolve "${JFROG_NUGET_FEED_REPO}" + + - run: dotnet nuget list source + + - run: mkdir -p 'app' + working-directory: ${{ inputs.publish_working_directory }} + + - name: dotnet publish + working-directory: ${{ inputs.publish_working_directory }} + run: | + dotnet publish \ + --no-build \ + --configuration "${CONFIGURATION}" \ + -p:Version="${VERSION}" \ + -p:InformationalVersion="${INFORMATIONALVERSION}" \ + --property:PublishDir=app + + - name: Create githash.txt file + working-directory: ${{ inputs.publish_working_directory }} + run: | + PULL_REQUEST_HEAD_SHA=${{ github.event.pull_request.head.sha }} + GH_SHA="${PULL_REQUEST_HEAD_SHA:-${GITHUB_SHA:-ERROR}}" + echo $GH_SHA > app/githash.txt + + - run: cat app/githash.txt + working-directory: ${{ inputs.publish_working_directory }} + + - run: ls -lR 'app' + working-directory: ${{ inputs.publish_working_directory }} + + - run: mkdir -p 'output' + working-directory: ${{ inputs.publish_working_directory }} + + - name: Create Release Zip File + working-directory: "${{ inputs.publish_working_directory }}app" + run: | + zip -v -r \ + "../output/${ZIPFILENAME}" \ + . + + - run: ls -lt output/*.zip + working-directory: ${{ inputs.publish_working_directory }} + + - name: Test Release Zip File + working-directory: ${{ inputs.publish_working_directory }} + run: zip -T "output/${ZIPFILENAME}" + + - name: Upload Artifact for Deployment + id: upload-artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ inputs.artifact_name }} + path: "${{ inputs.publish_working_directory }}output/${{ env.ZIPFILENAME }}" + retention-days: ${{ inputs.artifact_retention_days }} + if-no-files-found: error + + - name: Collect JFrog Build Information + run: jf rt build-collect-env "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" + + - name: Collect JFrog 'git' Information + run: jf rt build-add-git "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" + + - name: Upload Artifact to JFrog Artifactory + run: jf rt upload "${ZIPFILENAME}" "${JFROG_ARTIFACTORY_REPOSITORY}" --fail-no-op --server-id="${JFROG_SERVER_ID}" --build-name="${JFROG_CLI_BUILD_NAME}" --build-number="${JFROG_CLI_BUILD_NUMBER}" + working-directory: "${{ inputs.publish_working_directory }}output/" + + - name: Push JFrog Build Information + run: jf rt build-publish "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" diff --git a/.github/workflows/dotnet-test-jfrog.yml b/.github/workflows/dotnet-test-jfrog.yml index 9ebde39..78965cf 100644 --- a/.github/workflows/dotnet-test-jfrog.yml +++ b/.github/workflows/dotnet-test-jfrog.yml @@ -88,6 +88,22 @@ on: required: true type: string + jfrog_build_name: + description: 'JFrog build name.' + required: true + type: string + + jfrog_build_number: + description: 'JFrog build number. Can be an integer, a semantic version, or a string.' + required: true + type: string + + jfrog_cli_log_level: + description: 'Set the log level for the JFrog CLI. Default is ERROR. Values are: (DEBUG, INFO, WARN, ERROR).' + required: false + default: ERROR + type: string + jfrog_nuget_feed_repo: description: The 'virtual' JFrog Artifactory repository identifier for NuGet package retrieval. required: true @@ -114,6 +130,12 @@ on: type: boolean default: true + outputs: + + jfrog_build_name: + description: The JFrog build name for the 'dotnet-test' step is suffixed with '-dotnet-test'. + value: ${{ jobs.tests.outputs.jfrog_build_name }} + jobs: tests: @@ -123,6 +145,9 @@ jobs: run: working-directory: ${{ inputs.project_directory }} + outputs: + jfrog_build_name: ${{ env.JFROG_CLI_BUILD_NAME }} + env: ARTIFACTNAME: ${{ inputs.artifact_name }} CONFIGURATION: ${{ inputs.configuration }} @@ -139,9 +164,10 @@ jobs: ES_JAVA_OPTS: -Xms256m -Xmx256m # JFrog JFROG_API_BASE_URL: ${{ inputs.jfrog_api_base_url }} - JFROG_NUGET_FEED_NAME: jfrog-${{ inputs.jfrog_nuget_feed_repo }} + JFROG_CLI_BUILD_NAME: "${{ inputs.jfrog_build_name }}-dotnet-test" + JFROG_CLI_BUILD_NUMBER: ${{ inputs.jfrog_build_number }} + JFROG_CLI_LOG_LEVEL: ${{ inputs.jfrog_cli_log_level }} JFROG_NUGET_FEED_REPO: ${{ inputs.jfrog_nuget_feed_repo }} - JFROG_NUGET_FEED_REPO_URL: "${{ inputs.jfrog_api_base_url }}artifactory/api/nuget/v3/${{ inputs.jfrog_nuget_feed_repo }}/index.json" JFROG_OIDC_PROVIDER_NAME: ${{ inputs.jfrog_oidc_provider_name }} services: @@ -186,6 +212,12 @@ jobs: regex_pattern: "^debug|release$" value: ${{ env.CONFIGURATION }} + - name: Validate inputs.jfrog_build_name + uses: ritterim/public-github-actions/actions/regex-validator@v1.10.0 + with: # This regex pattern is a bit of a guess + regex_pattern: '^[A-Za-z0-9\-]{5,55}$' + value: ${{ inputs.jfrog_build_name }} + - name: Validate inputs.jfrog_nuget_feed_repo uses: ritterim/public-github-actions/actions/jfrog-artifactory-repository-name-validator@v1.14.1 with: @@ -303,3 +335,17 @@ jobs: path: "${{ inputs.project_directory }}**/*.trx" retention-days: ${{ inputs.artifact_retention_days }} if-no-files-found: error + + - name: Collect JFrog Build Information + run: jf rt build-collect-env "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" + + - name: Collect JFrog 'git' Information + run: jf rt build-add-git "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}" + + # TODO: Upload the TRX files to an Artifactory repo? + # - name: Upload Artifact to JFrog Artifactory + # run: jf rt upload "${ZIPFILENAME}" "${JFROG_ARTIFACTORY_REPOSITORY}" --fail-no-op --server-id="${JFROG_SERVER_ID}" --build-name="${JFROG_CLI_BUILD_NAME}" --build-number="${JFROG_CLI_BUILD_NUMBER}" + # working-directory: "${{ inputs.project_directory }}output/" + + - name: Push JFrog Build Information + run: jf rt build-publish "${JFROG_CLI_BUILD_NAME}" "${JFROG_CLI_BUILD_NUMBER}"