diff --git a/.github/actions/release/action.yml b/.github/actions/release/action.yml index c1da256ea6f..ad9f980d751 100644 --- a/.github/actions/release/action.yml +++ b/.github/actions/release/action.yml @@ -1,6 +1,9 @@ -name: "tag version" -description: "Tag package" +name: "release action" +description: "Create git release tags, github releases, jira version and push release communication." inputs: + github_ref_name: + description: "Github ref name" + required: true jira_api_token: description: "Token to authenticate to Jira" required: true @@ -10,57 +13,182 @@ inputs: jira_project_id: description: "Jira project id to create release" required: true - jira_base_url: - description: "Jira base url" + jira_webhook_url: + description: "Jira release webhook" required: true runs: using: "composite" steps: - - name: Publish RPMS to Repositories + - name: Checkout sources + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Get released versions for components run: | - NEW_VERSION="" - MAJOR_VERSION=$(echo $GITHUB_REF_NAME | grep -oP '([0-9]{2}\.[0-9]{2})') - echo "Major version: $MAJOR_VERSION" - HOTFIX=$(echo $GITHUB_REF_NAME | grep -oP '(hotfix|)') - echo "Hotfix: $HOTFIX" - BETA=$(echo $GITHUB_REF_NAME | grep -oP '(beta|)') - echo "Beta: $BETA" - RELEASE_ID=$(git log -1 --pretty=%B | grep -oP '(#[0-9]{4,}#)' | grep -oP '([0-9]+)') - echo "Release Id: $RELEASE_ID" - - OLDV=$(git tag --sort=-v:refname --list "centreon-collect-$MAJOR_VERSION.*" | head -n 1) - echo "Old version: $OLDV" + set -eu + + # Variables + COMPONENTS_COLLECT=("centreon-collect") + CURRENT_STABLE_BRANCH_MAJOR_VERSION="" + declare -a NEW_STABLE_TAGS=() + declare -a PREVIOUS_STABLE_TAGS=() + SCOPE_VERSION="COLLECT" + MINOR_VERSION_FILE_PATH=".version" + + # Get current stable branch name + CURRENT_STABLE_BRANCH_MAJOR_VERSION=$(echo ${{ inputs.github_ref_name }} | cut -d '.' -f1,2) + echo "Current stable branch major version: $CURRENT_STABLE_BRANCH_MAJOR_VERSION" + + # Get previous and new version tags for components + for component in ${COMPONENTS_COLLECT[@]}; do + if [[ $component == "centreon-web" ]]; then + COMPONENT_DIR="centreon" + else + COMPONENT_DIR=$component + fi + MAJOR_VERSION=$(grep -E "MAJOR" .version | cut -d '=' -f2) + MINOR_VERSION=$(grep -E "MINOR" .version | cut -d '=' -f2) + # Previous stable tags array + PREVIOUS_STABLE_TAGS+=($(git tag -l --sort=-version:refname "$component-$CURRENT_STABLE_BRANCH_MAJOR_VERSION*" | head -n 1)) + # New stable tags array + NEW_STABLE_TAGS+=("$component-$MAJOR_VERSION.$MINOR_VERSION") + done + echo "Previous releases were: ${PREVIOUS_STABLE_TAGS[*]}" + echo "New releases are: ${NEW_STABLE_TAGS[*]}" + + # TODO: Check that NEW_STABLE_TAGS are fully different from PREVIOUS_STABLE_TAGS + # re use the part from check version ?? + # or use the check-version action after turning this release action into a real workflow ? + + # Make NEW_STABLE_TAGS available for other steps + echo "NEW_STABLE_TAGS=${NEW_STABLE_TAGS[*]}" >> "$GITHUB_ENV" + echo "CURRENT_STABLE_BRANCH_MAJOR_VERSION=$CURRENT_STABLE_BRANCH_MAJOR_VERSION" >> "$GITHUB_ENV" + echo "SCOPE_VERSION=$SCOPE_VERSION" >> "$GITHUB_ENV" + shell: bash + - name: Add new release tags to stable branch + run: | + # Add new stable tags to stable branch + echo "Configuring git." git config --global user.email "release@centreon.com" git config --global user.name "Centreon" - if [ -z "$OLDV" ]; then - echo "No existing version, starting at $MAJOR_VERSION.0" - NEW_VERSION="$MAJOR_VERSION.0" - git tag -a "centreon-collect-$NEW_VERSION" -m "version $NEW_VERSION" - git push --follow-tags - else - OLD_MINOR_VERSION=$(echo $OLDV | grep -oP '([0-9]+$)') - NEW_MINOR_VERSION=$(echo $((OLD_MINOR_VERSION + 1))) - NEW_VERSION=$MAJOR_VERSION.$NEW_MINOR_VERSION - git tag -a "centreon-collect-$NEW_VERSION" -m "version $NEW_VERSION" - git push --follow-tags - fi + # Create release tags on git for each release components + echo "Creating release tags." + for TAG in ${NEW_STABLE_TAGS[@]}; do + if [ -z $(git tag --list "$TAG" | head -n 1) ]; then + git tag -a "$TAG" -m "$TAG" + git push --follow-tags + echo "::notice::Tagging stable branch with $TAG." + else + echo "::error::Release tag $TAG already exists, exiting." + exit 1 + fi + done + shell: bash - if [ "$HOTFIX" == "hotfix" ]; then - TYPE=Hotfix + - name: Create GITHUB releases from new release tags + run: | + # Install gh cli + echo "Installing GH CLI." + if ! command -v gh &> /dev/null; then + echo "Installing GH CLI." + type -p curl >/dev/null || (sudo apt-get update && sudo apt-get install curl -y) + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg + sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null + sudo apt-get update + sudo apt-get install gh -y else - TYPE=Release + echo "GH CLI is already installed." fi - VERSION_DATA="{\"archived\":false,\"releaseDate\":\"$(date +%Y-%m-%d)\",\"name\":\"centreon-collect-$NEW_VERSION\",\"description\":\"$TYPE:$RELEASE_ID\",\"projectId\":${{ inputs.jira_project_id }},\"released\":false}" + # Create GITHUB release for each release components + echo "Creating GITHUB releases." + for TAG in ${NEW_STABLE_TAGS[@]}; do + echo "Creating GITHUB release with title $TAG for tag $TAG." + gh release create $TAG --target "${{ inputs.github_ref_name }} --title "$TAG" --verify-tag + done + shell: bash + + - name: Create stable JIRA versions from new release tags + run: | + set -eu + + # Call JIRA to provide new jira versions to create + # Webhook url + JIRA_INCOMING_WEBHOOK="${{ inputs.jira_webhook_url }}" + + # Rebuild NEW_STABLE_TAGS as an array + for i in ${NEW_STABLE_TAGS[@]}; do + NEW_RELEASE_TAGS+=("$i") + done + + # Create new JIRA versions (old way of doing it) + # TODO: add a future capacity to determine wether the release is hotfix or standard (using TYPE) + # OR: rely on jira automation to do it (less hassle on github side, and jira knows jira best) + + # Build JSON vars for JIRA_RELEASE_DATA + JIRA_RELEASE_ARCHIVED="false" + JIRA_RELEASE_DESCRIPTION="" + JIRA_RELEASE_DATE="$(date +%Y-%m-%d)" + JIRA_RELEASE_NAME="" + JIRA_PROJECT_ID="${{ inputs.jira_project_id }}" + JIRA_RELEASE_RELEASED="false" + + # Create JIRA version for each released component + echo "Creating JIRA releases." + for TAG in ${NEW_RELEASE_TAGS[@]}; do + echo "::notice::Creating JIRA release $TAG based on git release tag $TAG." + # Build JSON with release information for JIRA API + JIRA_RELEASE_DATA=$(jq -nc \ + --arg archived "$JIRA_RELEASE_ARCHIVED" \ + --arg description "$TAG" \ + --arg releaseDate "$JIRA_RELEASE_DATE" \ + --arg name "$TAG" \ + --arg projectId "$JIRA_PROJECT_ID" \ + --arg released "$JIRA_RELEASE_RELEASED" \ + '$ARGS.named' ) + # Send to JIRA API release + echo "Sending to JIRA API release: $JIRA_RELEASE_DATA" + curl --fail --request POST \ + --url 'https://centreon.atlassian.net/rest/api/3/version' \ + --user '${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --data "$JIRA_RELEASE_DATA" + done + shell: bash + + - name: Trigger release communication for new releases + run: | + set -eu + MAJOR_VERSION=$CURRENT_STABLE_BRANCH_MAJOR_VERSION + + # Webhook url + JIRA_INCOMING_WEBHOOK="${{ inputs.jira_webhook_url }}" + + # Rebuild NEW_STABLE_TAGS as an array + for i in ${NEW_STABLE_TAGS[@]}; do + NEW_RELEASE_TAGS+=("$i") + done + + # Build JSON structure with released versions + JSON_TAGS=$(jq -n '{componentList:$ARGS.positional}' --args "${NEW_RELEASE_TAGS[@]}") + JSON_VERSION_INFO=$(jq -n --arg majorVersion "$MAJOR_VERSION" --arg scopeVersion "$SCOPE_VERSION" '$ARGS.named' ) + RELEASE_JSON=$(echo "$JSON_VERSION_INFO" | jq -c --argjson json_tags "$JSON_TAGS" '. += $json_tags') + + # DEBUG + echo "JSON_TAGS: \r\n$JSON_TAGS" + echo "JSON_VERSION_INFO: $JSON_VERSION_INFO" + echo "Sending to JIRA automation: \r\n$RELEASE_JSON" - curl --fail --request POST \ - --url '${{ inputs.jira_base_url }}/rest/api/3/version' \ - --user '${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}' \ - --header 'Accept: application/json' \ - --header 'Content-Type: application/json' \ - --data ''$VERSION_DATA'' + # Call jira webhook to trigger the communication workflow + # and provide versions data for communication + curl \ + "$JIRA_INCOMING_WEBHOOK" \ + -X POST \ + -H 'Content-type: application/json' \ + --data "$RELEASE_JSON" shell: bash diff --git a/.github/workflows/release-collect.yml b/.github/workflows/release-collect.yml deleted file mode 100644 index ed2cecbf068..00000000000 --- a/.github/workflows/release-collect.yml +++ /dev/null @@ -1,37 +0,0 @@ ---- -name: Create collect jira version - -on: - pull_request_target: - types: - - closed - branches: - - master - - "[2-9][0-9].[0-9][0-9].x" - paths: - - "centreon-collect/**" - - "!centreon-collect/ci/**" - - "!centreon-collect/tests/**" - workflow_dispatch: - -env: - module: "collect" - -jobs: - release: - if: github.event.pull_request.merged == true - runs-on: ubuntu-22.04 - steps: - - name: Checkout sources - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 - - - name: Release - id: release - uses: ./.github/actions/release - with: - jira_user_email: ${{ secrets.XRAY_JIRA_USER_EMAIL }} - jira_api_token: ${{ secrets.XRAY_JIRA_TOKEN }} - jira_project_id: ${{ secrets.JIRA_PROJECT_ID }} - jira_base_url: ${{ secrets.JIRA_BASE_URL }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..3a02068db91 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,52 @@ +--- +name: Release + +on: + pull_request: + types: + - closed + branches: + - master + - "[2-9][0-9].[0-9][0-9].x" + paths-ignore: + - ".github/**" + - ".jira/**" + - "tests/**" + - ".deepsource.toml" + - ".veracode-exclusions" + - "README.md" + - "sonar-project.properties" + workflow_dispatch: + +jobs: + release: + if: ${{ github.event.pull_request.merged == true }} + runs-on: ubuntu-22.04 + steps: + - name: Check base_ref + run: | + set -eu + # Check if github.base_ref is either master or any of the supported version ones + # This must never run on any other than master and supported version base_ref + if [[ "${{ github.base_ref }}" == 'master' || "${{ github.base_ref }}" =~ ^[2-9][0-9].[0-9][0-9].x ]];then + echo "[DEBUG] base_ref is valid: ${{ github.base_ref }}" + else + echo "::error::base_ref is not valid (${{ github.base_ref }}), exiting." + exit 1 + fi + shell: bash + + - name: Checkout sources + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Release + id: release + uses: ./.github/actions/release + with: + github_ref_name: ${{ github.head_ref || github.ref_name }} + jira_project_id: ${{ secrets.JIRA_PROJECT_ID }} + jira_user_email: ${{ secrets.XRAY_JIRA_USER_EMAIL }} + jira_api_token: ${{ secrets.XRAY_JIRA_TOKEN }} + jira_webhook_url: ${{ secrets.JIRA_RELEASE_WEBHOOK }}