# Release GCToolkit to Maven Central
#
# Builds and tests the binaries.
# Signs the artifacts and generates SHA checksums.
# Publishes the artifacts to Maven Central.
# This pipeline is triggered manually.
trigger: none
pr: none
parameters:
- name: release_tag
type: string
displayName: Release Tag
- name: release_type
type: string
displayName: Release Type
default: dry-run
values:
- dry-run
- release
variables:
JAVA_HOME_11_X64: /usr/lib/jvm/msopenjdk-11
GCTOOLKIT_TAG: ${{ parameters.release_tag }}
resources:
repositories:
- repository: gctoolkit
type: github
endpoint: Github-Java-Engineering
name: microsoft/gctoolkit
ref: refs/tags/$(GCTOOLKIT_TAG)
- repository: 1esPipelines
type: git
name: 1ESPipelineTemplates/1ESPipelineTemplates
ref: refs/tags/release
extends:
template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines
parameters:
pool:
name: JEG-test-pool-x64
os: linux
sdl:
sourceAnalysisPool:
name: JEG-windows2022-x64-release
os: windows
sourceRepositoriesToScan:
exclude:
- repository: gctoolkit
credscan:
suppressionsFile: $(Build.SourcesDirectory)/.devops/credscan/suppressions.json
stages:
- stage: Release_GCToolkit
jobs:
- job: build_gctoolkit
workspace:
clean: all
displayName: Build GCToolkit with Maven
templateContext:
# Disable Defender for Linux since it is not supported by Azure Linux.
# More info here: https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/sdlanalysis/antimalware
sdl:
antimalwareScan:
enabled: false
justificationForDisabling: Disabling Defender for Linux as its not supported in Azure Linux 3
outputs:
- output: pipelineArtifact
targetPath: $(Build.ArtifactStagingDirectory)/staging
artifactName: staged-artifacts
steps:
- checkout: gctoolkit
path: gctoolkit
clean: true
# Find out what is installed on the agents...
- bash: |
echo "Installed Tools and versions:"
find /opt/hostedtoolcache -mindepth 1 -type d | while read dir; do
if [[ "$dir" == *jdk* ]]; then
echo "👉 $dir"
else
echo "$dir"
fi
done
displayName: 'Show installed tools'
# Use modern Java to build
- task: JavaToolInstaller@0
inputs:
versionSpec: '11'
jdkArchitectureOption: 'x64'
jdkSourceOption: 'PreInstalled'
env:
JAVA_HOME_11_X64: $(JAVA_HOME_11_X64)
displayName: 'Set Java to v11'
# download signing keys from Azure Key Vault
- task: AzureKeyVault@2
displayName: Download GPG signing keys
inputs:
azureSubscription: 'JEG-Infrastructure'
KeyVaultName: 'juniper-keyvault'
SecretsFilter: 'javask-gpg-passphrase,javask-gpg-private,javask-gpg-public,javask-gpg-trust'
RunAsPreJob: false
# base64 decode signing keys
- bash: |
echo "Base64 decoding keys..."
echo "$(javask-gpg-private)" | base64 -d > private.asc
echo "$(javask-gpg-public)" | base64 -d > public.asc
echo "$(javask-gpg-trust)" | base64 -d > trust.gpg
workingDirectory: $(Agent.BuildDirectory)
displayName: Base64 decode secret
# import signing keys into GPG
- bash: |
echo "GPG importing keys..."
echo $(javask-gpg-passphrase) | gpg --batch --passphrase-fd 0 --import $(Agent.BuildDirectory)/private.asc
echo $(javask-gpg-passphrase) | gpg --batch --passphrase-fd 0 --import $(Agent.BuildDirectory)/public.asc
displayName: GPG import keys
# restore owner trust
- bash: |
echo "GPG restore owner trust..."
gpg --import-ownertrust $(Agent.BuildDirectory)/trust.gpg
displayName: GPG restore owner trust
# Now that all the keys and whatnot are setup, do the build...
- bash: |
mkdir ~/.m2 \|| true
cp $(Build.SourcesDirectory)/.devops/feed-settings.xml ~/.m2/settings.xml
displayName: 'Copy feed-settings to .m2'
# Ensure authentication is in place for our use of internal DevDiv feeds
- task: MavenAuthenticate@0
inputs:
artifactsFeeds: 'java-engineering-feed'
displayName: 'Maven auth for DevDiv'
- bash: |
RELEASE_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout | cut -d'-' -f1)
echo "##vso[task.setvariable variable=RELEASE_VERSION]$RELEASE_VERSION"
displayName: 'Set RELEASE_VERSION'
- bash: |
./mvnw \
-B -Prelease \
-DaltDeploymentRepository=local::file:$(Build.ArtifactStagingDirectory)/staging \
deploy
displayName: 'Build and deploy to local staging directory'
# Remove .sha1 and .md5 files.
# Generate .sha256 after signing.
- bash: |
find staging \
-type f \
-name "*.sha1" \
-delete -o \
-name "*.md5" \
-delete
displayName: 'Remove .sha1 and .md5 files'
workingDirectory: $(Build.ArtifactStagingDirectory)
# ESRP Sign all jars in the gctoolkit staging directory
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: ESRP Java JAR Signing
inputs:
ConnectedServiceName: 'JEG-Tooling-Prod'
AppRegistrationClientId: '516af6d8-6ab4-4069-8f64-b18c64d16688'
AppRegistrationTenantId: '33e01921-4d64-4f8c-a055-5bdaffd5e33d'
AuthAKVName: 'JEG-tooling-kv'
AuthCertName: 'JEG-Tooling-auth'
AuthSignCertName: 'GCToolKit-ESRP'
FolderPath: '$(Build.ArtifactStagingDirectory)/staging'
Pattern: '**/*-$(RELEASE_VERSION)*.jar'
UseMinimatch: true
signConfigType: 'inlineSignParams'
inlineOperation: |
[
{
"KeyCode": "CP-447347-Java",
"OperationCode": "JavaSign",
"ToolName": "sign",
"ToolVersion": "1.0",
"Parameters": {
"SigAlg": "SHA256withRSA",
"Timestamp": "-tsa http://sha256timestamp.ws.digicert.com/sha256/timestamp"
}
},
{
"KeyCode": "CP-447347-Java",
"OperationCode": "JavaVerify",
"ToolName": "sign",
"ToolVersion": "1.0",
"Parameters": {}
}
]
SessionTimeout: '120'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
VerboseLogin: true
# gpg sign all artifacts in the gctoolkit staging directory
# this will create a .asc file for each file in the directory. This is a detached signature
# required to publish into Maven Central.
- bash: |
for file in `find staging -type f -name *-$(RELEASE_VERSION)*.jar -o -name *-$(RELEASE_VERSION)*.pom`; do
echo $(javask-gpg-passphrase) | gpg --pinentry-mode loopback --passphrase-fd 0 -ab $file
done
workingDirectory: $(Build.ArtifactStagingDirectory)
displayName: GPG Signing
# generate sha256sums for all files in the staging directory
- bash: |
for file in `find staging -type f`; do
sha256sum $file > $file.sha256
done
workingDirectory: $(Build.ArtifactStagingDirectory)
displayName: Create sha256sums
# Release jobs have to be separated from build jobs for our internal release service to be compliant
- job: release_gctoolkit_to_maven_central
dependsOn: build_gctoolkit
workspace:
clean: all
displayName: Release GCToolkit to Maven Central
templateContext:
type: releaseJob
isProduction: true
inputs: # Pull the staged artifacts from the build job.
- input: pipelineArtifact
artifactName: staged-artifacts
targetPath: '$(Build.ArtifactStagingDirectory)/staging'
steps:
# ESRP Release task docs at aka.ms/esrp under 'ESRP Portal Help'
- task: EsrpRelease@8
inputs:
connectedservicename: 'JEG-Tooling-Prod'
keyvaultname: 'JEG-tooling-kv'
authcertname: 'JEG-Tooling-auth'
signcertname: 'GCToolKit-ESRP'
clientid: '516af6d8-6ab4-4069-8f64-b18c64d16688'
intent: 'PackageDistribution'
# Test with contentype PyPI to avoid publishing to Maven Central
# NOTE: This is the guidance given in ESRP portal for testing
# the flow during dry-runs, see aka.ms/esrp.
${{ if eq(parameters.release_type, 'release') }}:
contenttype: 'Maven'
${{ else }}:
contenttype: 'PyPI'
contentsource: 'Folder'
folderlocation: '$(Build.ArtifactStagingDirectory)/staging/com/microsoft/gctoolkit'
waitforreleasecompletion: true
owners: 'dekeeler@microsoft.com'
approvers: 'maverbur@microsoft.com,john.oliver@microsoft.com'
serviceendpointurl: 'https://api.esrp.microsoft.com'
mainpublisher: 'ESRPRELPACMAN'
domaintenantid: '33e01921-4d64-4f8c-a055-5bdaffd5e33d'
displayName: 'Publish to Maven Central'
# For non-release runs, allow this task to fail (it should!) so the
# pipeline does not appear to fail when it doesn't.
continueOnError: ${{ ne(parameters.release_type, 'release') }}microsoft/gctoolkit
Publicmirrored fromhttps://github.com/microsoft/gctoolkitAvailable
.devops/gctoolkit-release.yml
271lines · modepreview