diff --git a/001_workshop_Prerequisites.md b/001_workshop_Prerequisites.md index d41f484..02ba001 100644 --- a/001_workshop_Prerequisites.md +++ b/001_workshop_Prerequisites.md @@ -22,7 +22,9 @@ Make sure the following are installed on your laptop: - This workshop requires a GitHub account that can run GitHub actions. - You should be able to to fork and clone a git repo from GitHub - PRO TIP : Signing into GitHub via VS Code before the workshop to save a little time. - - Also feel free to fork and clone this repo. + - Also feel free to fork and clone these repos: + - https://github.com/bbenz/devopsforjavashops-TestABAzureDevOPs + - https://github.com/bbenz/devopsforjavashops-TestFeatureFlags diff --git a/ADODemo/.gitignore b/ADODemo/.gitignore deleted file mode 100644 index 549e00a..0000000 --- a/ADODemo/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/ADODemo/.mvn/wrapper/MavenWrapperDownloader.java b/ADODemo/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f3..0000000 --- a/ADODemo/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/ADODemo/.mvn/wrapper/maven-wrapper.jar b/ADODemo/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a..0000000 Binary files a/ADODemo/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/ADODemo/.mvn/wrapper/maven-wrapper.properties b/ADODemo/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572..0000000 --- a/ADODemo/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/ADODemo/mvnw b/ADODemo/mvnw deleted file mode 100644 index a16b543..0000000 --- a/ADODemo/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/ADODemo/mvnw.cmd b/ADODemo/mvnw.cmd deleted file mode 100644 index c8d4337..0000000 --- a/ADODemo/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/ADODemo/pom.xml b/ADODemo/pom.xml deleted file mode 100644 index 06039c9..0000000 --- a/ADODemo/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.3.RELEASE - - - com.example - demo - 0.0.1-SNAPSHOT - demo - Azure Feature Management with Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - com.microsoft.azure - spring-cloud-azure-appconfiguration-config-web - 1.1.5 - - - com.microsoft.azure - spring-cloud-azure-feature-management-web - 1.1.5 - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/ADODemo/src/main/java/com/example/demo/DemoApplication.java b/ADODemo/src/main/java/com/example/demo/DemoApplication.java deleted file mode 100644 index fbddd8d..0000000 --- a/ADODemo/src/main/java/com/example/demo/DemoApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -//@EnableConfigurationProperties(MessageProperties.class) -public class DemoApplication { - - public static void main(String[] args) { - SpringApplication.run(DemoApplication.class, args); - } -} \ No newline at end of file diff --git a/ADODemo/src/main/java/com/example/demo/HelloController.java b/ADODemo/src/main/java/com/example/demo/HelloController.java deleted file mode 100644 index f956f97..0000000 --- a/ADODemo/src/main/java/com/example/demo/HelloController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; - -import com.microsoft.azure.spring.cloud.feature.manager.FeatureManager; -import org.springframework.web.bind.annotation.GetMapping; - - -@Controller -@ConfigurationProperties("controller") -public class HelloController { - - private FeatureManager featureManager; - - public HelloController(FeatureManager featureManager) { - this.featureManager = featureManager; - } - - @GetMapping("/welcome") - public String mainWithParam(Model model) { - model.addAttribute("Beta", featureManager.isEnabledAsync("featureManagement.Beta").block()); - return "welcome"; - } -} \ No newline at end of file diff --git a/ADODemo/src/main/java/com/example/demo/MessageProperties.java b/ADODemo/src/main/java/com/example/demo/MessageProperties.java deleted file mode 100644 index a46c52d..0000000 --- a/ADODemo/src/main/java/com/example/demo/MessageProperties.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "config") -public class MessageProperties { - private String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} \ No newline at end of file diff --git a/ADODemo/src/main/resources/application.properties b/ADODemo/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/ADODemo/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ADODemo/src/main/resources/bootstrap.properties b/ADODemo/src/main/resources/bootstrap.properties deleted file mode 100644 index 83311e7..0000000 --- a/ADODemo/src/main/resources/bootstrap.properties +++ /dev/null @@ -1 +0,0 @@ -spring.cloud.azure.appconfiguration.stores[0].connection-string= ${APP_CONFIGURATION_CONNECTION_STRING} diff --git a/ADODemo/src/main/resources/favicon.ico b/ADODemo/src/main/resources/favicon.ico deleted file mode 100644 index 92264f3..0000000 Binary files a/ADODemo/src/main/resources/favicon.ico and /dev/null differ diff --git a/ADODemo/src/main/resources/package/HelloController.java b/ADODemo/src/main/resources/package/HelloController.java deleted file mode 100644 index f956f97..0000000 --- a/ADODemo/src/main/resources/package/HelloController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; - -import com.microsoft.azure.spring.cloud.feature.manager.FeatureManager; -import org.springframework.web.bind.annotation.GetMapping; - - -@Controller -@ConfigurationProperties("controller") -public class HelloController { - - private FeatureManager featureManager; - - public HelloController(FeatureManager featureManager) { - this.featureManager = featureManager; - } - - @GetMapping("/welcome") - public String mainWithParam(Model model) { - model.addAttribute("Beta", featureManager.isEnabledAsync("featureManagement.Beta").block()); - return "welcome"; - } -} \ No newline at end of file diff --git a/ADODemo/src/main/resources/package/MessageProperties.java b/ADODemo/src/main/resources/package/MessageProperties.java deleted file mode 100644 index a46c52d..0000000 --- a/ADODemo/src/main/resources/package/MessageProperties.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "config") -public class MessageProperties { - private String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} \ No newline at end of file diff --git a/ADODemo/src/main/resources/static/CSS/main.css b/ADODemo/src/main/resources/static/CSS/main.css deleted file mode 100644 index 26fc9d5..0000000 --- a/ADODemo/src/main/resources/static/CSS/main.css +++ /dev/null @@ -1,28 +0,0 @@ -html { - position: relative; - min-height: 100%; -} -body { - margin-bottom: 60px; -} -.footer { - position: absolute; - bottom: 0; - width: 100%; - height: 60px; - line-height: 60px; - background-color: #f5f5f5; -} - -body > .container { - padding: 60px 15px 0; -} - -.footer > .container { - padding-right: 15px; - padding-left: 15px; -} - -code { - font-size: 80%; -} \ No newline at end of file diff --git a/ADODemo/src/main/resources/static/images/bit.png b/ADODemo/src/main/resources/static/images/bit.png deleted file mode 100644 index df92cb5..0000000 Binary files a/ADODemo/src/main/resources/static/images/bit.png and /dev/null differ diff --git a/ADODemo/src/main/resources/templates/welcome.html b/ADODemo/src/main/resources/templates/welcome.html deleted file mode 100644 index e6e28e8..0000000 --- a/ADODemo/src/main/resources/templates/welcome.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - Feature Management with Spring Cloud Azure - - - - - - - - - - -
- - -
-
-

Welcome

-

Learn more about Feature Management with Spring Cloud Azure

- BIT! -
- - - \ No newline at end of file diff --git a/ADODemo/src/test/java/com/example/demo/DemoApplicationTests.java b/ADODemo/src/test/java/com/example/demo/DemoApplicationTests.java deleted file mode 100644 index 2778a6a..0000000 --- a/ADODemo/src/test/java/com/example/demo/DemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/Exercise1.md b/Exercise1.md new file mode 100644 index 0000000..dad54f8 --- /dev/null +++ b/Exercise1.md @@ -0,0 +1,92 @@ + +[Return to Agenda](README.md) +
+ + +## Workshop: DevOps for Java Shops + +### Exercise 1 – Fork and Clone GitHub repositories for this workshop + + [Related Microsoft Learn Materials](https://cda.ms/1Xz) + +[Related GitHub Lab Materials](https://lab.github.com/githubtraining/introduction-to-github) + + [Instructions on forking and cloning a repo on Microsoft Docs](https://cda.ms/1XC) + +Sample Apps: + +https://github.com/bbenz/devopsforjavashops-TestABAzureDevOPs +https://github.com/bbenz/devopsforjavashops-TestFeatureFlags + + - Fork and clone a main branch + - Making changes to the local repo + - Staging + - Committing + +## Build and run the sample App + + +### Prepare Visual Studio Code + +First you'll set up Visual Studio Code so you can build the website locally and work with source files. + +Visual Studio Code comes with an integrated terminal, so you can edit files and work from the command line all from one place. + +Start Visual Studio Code. + +On the View menu, select Terminal. + +In the drop-down list, select command: + +The terminal window lets you choose any shell that's installed on your system, like Bash, Zsh, and PowerShell. + +### Authenticate with GitHub + +You'll need to run a few commands to authenticate with GitHub. + +Now you'll get the source code from GitHub and set up Visual Studio Code so that you can run the app and work with source code files. + +### Create a fork + +Create a fork of these Sample Apps so you can work with and modify the source files: + +https://github.com/bbenz/devopsforjavashops-TestABAzureDevOPs + +https://github.com/bbenz/devopsforjavashops-TestFeatureFlags + +> A fork is a copy of a GitHub repository. The copy exists in your account and enables you to make any changes you want without affecting the original project. + +To fork the Sample App into your GitHub account: + +In a web browser, go to GitHub and sign in. + +- Go to the Space Game web project. + +- Select Fork + + - Follow the instructions to fork the repository into your account. + +### Clone your fork locally +You now have a copy of the Sample App in your GitHub account. Now you'll download, or clone, a copy to your computer so you can work with it. + +> A clone, just like a fork, is a copy of a repository. When you clone a repository, you can make changes, verify they work as you expect, and then upload those changes back to GitHub. You can also synchronize your local copy with changes other authenticated users have made to GitHub's copy of your repository. + +To clone the Sample App to your computer: + + - Go to your fork of the Sample App on GitHub. + + - Select Clone or download. Then select the button next to the URL that's shown to copy the URL to your clipboard: + + - In Visual Studio Code, go to the terminal window and run the git clone command. Replace the URL that's shown here with the contents of your clipboard. + +> [!NOTE] +> You can also run this command via a terminal + +Navigate to the root directory of the Sample App. + +You should see the directory and file tree in the file explorer. + + + + + diff --git a/Exercise2.md b/Exercise2.md new file mode 100644 index 0000000..9536406 --- /dev/null +++ b/Exercise2.md @@ -0,0 +1,117 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + +### Exercise 2 - Set up Azure for this workshop + - Create a resource group + - Create a staging server + - Create a GitHub Actions server + - Create a production server + - Create a deployment slot on the production server + - Set the deployment slot to 50% traffic + + +### Create a resource group using the Azure portal + + +For this workshop we are using the [Azure portal](https://portal.azure.com) with Azure Resource Manager to manage your Azure resource groups. + + +> A resource group is a container that holds related resources for an Azure solution. The resource group can include all the resources for the solution, or only those resources that you want to manage as a group. You decide how you want to allocate resources to resource groups based on what makes the most sense for your organization. Generally, add resources that share the same lifecycle to the same resource group so you can easily deploy, update, and delete them as a group. The resource group stores metadata about the resources. Therefore, when you specify a location for the resource group, you are specifying where that metadata is stored. For compliance reasons, you may need to ensure that your data is stored in a particular region. + +1. Sign in to the [Azure portal](https://portal.azure.com). +2. Select **Resource groups** + + ![add resource group](./media/manage-resource-groups-add-group.png) +3. Select **Add**. +4. Enter the following values: + + - **Subscription**: Select your Azure subscription. + - **Resource group**: Enter a new resource group name. + - **Region**: Select an Azure location, such as **Central US**. + + +> [!NOTE] + > You should use the same resource group and location for all the resources we are creating today + + +![create resource group](./media/manage-resource-groups-create-group.png) + +5. Select **Review + Create** +6. Select **Create**. It takes a few seconds to create a resource group. + +7. Select **Refresh** from the top menu to refresh the resource group list, and then select the newly created resource group to open it. Or select **Notification**(the bell icon) from the top, and then select **Go to resource group** to open the newly created resource group + + ![go to resource group](./media/manage-resource-groups-add-group-go-to-resource-group.png) + +### Create a Staging Azure Web app + +1. In the [Azure portal](https://portal.azure.com), select **Create a resource**. + + ![Create a resource in the Azure portal.](./media/create-a-resource.png) + +1. Select **New** > **Web App**. + + ![Create an app in the Azure portal.](./media/create-a-resource.png) + +2. Configure the **Instance Details** section before configuring the App Service plan. + 1. Choose **Java 11** for the Runtime Stack + 1. Choose **Java SE** for the Java Web Server Stack + 1. Choose **Linux** for the Operating System + +This will be our **Staging** Web App Server. + +> [!NOTE] + > You should use the same resource group and location for all the resources we are creating today + + +3. In the **App Service Plan** section, select **Create new**. + +4. When creating a plan, you can select the pricing tier of the new plan. In **Sku and size**, choose the default. + +### Create a GitHub Actions Azure Web app + +5. Repeat the steps to create the **Production** server: + +- In the **App Service Plan** section, use the same app service plan that you used for the staging server, instead of creating a new one. +- Include the word **github** in this Web App name. +- Use the same location and resource group. + +### Create a Production Azure Web app + +5. Repeat the steps to create the **Production** server, with the following changes: + +- In the **App Service Plan** section, use the same app service plan that you used for the staging server, instead of creating a new one. +- Include the word **Production** in this Web App name. +- Use the same location and resource group. + +## Add a deployment slot to the production server + +>Deployment slots are live apps with their own host names. App content and configurations elements can be swapped between two deployment slots, including the production slot. + + +1. In the left pane, select **Deployment slots** > **Add Slot**. + + ![Add a new deployment slot](./media/QGAddNewDeploymentSlot.png) + + > [!NOTE] + > If the app isn't already in the **Standard**, **Premium**, or **Isolated** tier, you receive a message that indicates the supported tiers for enabling staged publishing. At this point, you have the option to select **Upgrade** and go to the **Scale** tab of your app before continuing. + > + +1. In the **Add a slot** dialog box, give the slot the name "Canary", and select whether to clone an app configuration from another deployment slot. Select **Add** to continue. + + ![Configuration source](./media/ConfigurationSource1.png) + + 1. After the slot is added, select **Close** to close the dialog box. The new slot is now shown on the **Deployment slots** page. By default, **Traffic %** is set to 0 for the new slot, with all customer traffic routed to the production slot. + +1. Select the new deployment slot to 50%, + +1. Open that slot's resource page. + + ![Deployment slot title](./media/StagingTitle.png) + + >The staging slot has a management page just like any other App Service app. You can change the slot's configuration. To remind you that you're viewing the deployment slot, the app name is shown as **\/\**, and the app type is **App Service (Slot)**. You can also see the slot as a separate app in your resource group, with the same designations. + +1. Select the app URL on the slot's resource page. The deployment slot has its own host name and is also a live app. diff --git a/Exercise3.md b/Exercise3.md new file mode 100644 index 0000000..adf5f08 --- /dev/null +++ b/Exercise3.md @@ -0,0 +1,110 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + +### Exercise 3 - Setting up feature flags and configuring App Servers + +[Related Microsoft Docs](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core?tabs=core3x) + - Create an App Configuration Store + - Add a feature Manager + - Set the percentage filter + - Set up Connection Strings in your Azure Web Apps + - Set up Java start commands in General settings in Web Apps + +### Add a feature Manager + +1. To create a new App Configuration store, sign in to the [Azure portal](https://portal.azure.com). In the upper-left corner of the home page, select **Create a resource**. In the **Search the Marketplace** box, enter *App Configuration* and select Enter. + + ![Search for App Configuration](media/azure-portal-search.png) + +1. Select **App Configuration** from the search results, and then select **Create**. + + ![Select Create](media/azure-portal-app-configuration-create.png) + +1. On the **Create App Configuration** pane, enter the following settings: + + | Setting | Suggested value | Description | + |---|---|---| + | **Subscription** | Your subscription | Select the Azure subscription that you used for the rest of the workshop. | + | **Resource group** | *Workshop resource Group* | Use the same workshop resource group for your App Configuration store resource. | + | **Resource name** | Globally unique name | Enter a unique resource name to use for the App Configuration store resource. The name must be a string between 5 and 50 characters and contain only numbers, letters, and the `-` character. The name can't start or end with the `-` character. | + | **Location** | *Workshop location* | Use the same workshop location as the other components of your application. | + | **Pricing tier** | *Free* | Select the desired pricing tier. For more information, see the [App Configuration pricing page](https://azure.microsoft.com/pricing/details/app-configuration). | + +1. Select **Review + create** to validate your settings. + +1. Select **Create**. The deployment might take a few minutes. + +1. After the deployment finishes, navigate to the App Configuration resource. Select **Settings** > **Access keys**. Find the primary read-only key connection string. You'll use this connection string later to configure your application to communicate with the App Configuration store that you created. + +1. Select **Operations** > **Feature manager** > **Add** to add a feature flag called *Beta*. + + > ![Enable feature flag named Beta](media/add-beta-feature-flag.png) + + Leave **Label** empty for now. Select **Apply** to save the new feature flag. + +1. Click on the ellipsis on the right, and select **Advanced Edit**. Paste this in to the dialog and Select **Apply** to save the new feature flag: + +```dotnetcli +{ + "id": "Beta", + "description": "", + "enabled": true, + "conditions": { + "client_filters": [ + { + "name": "Microsoft.Percentage", + "parameters": { + "Value": 50 + } + } + ] + } +} +``` + +This sets up a feature flag with the percentage filter, meaning 50% of users will see a new feature and 50% of users will not. + + +### Retrieve the Access Key for the Azure App Configuration + +In App Configuration, navigate to Settings > Access Keys> Read-Only Key > Primary Key, and copy the connection String. + +**Save this connection string locally, as you will be reusing it serveral times during this workshop** + +### Set up Application Settings and Java startup commands in your Azure Web Apps + +In the Azure portal, search for and select App Services, and then select your staging app. In the app's left menu, select Configuration > Application settings. + +Select your Web app. In the app's left menu, select **Configuration** > **Application settings**. + +![Application Settings](./media/open-ui.png) + +> Application Settings and Connection strings are always encrypted when stored (encrypted-at-rest). + +To add a new Application Setting, click **New Application Setting**. + +The name should be **APP_CONFIGURATION_CONNECTION_STRING** and the value should be the connection string from your App Configuration, starting with **Endpoint=** + +#### +In the app's left menu, select **Configuration** > **General settings**. + +In **Startup Command**, add: + +**java -jar /home/site/wwwroot/demo-0.0.1-SNAPSHOT.jar --server.port=80** + +When finished, click **Update**. Don't forget to click **Save** back in the **Configuration** page. + +The application should restart at this time. Open the Web Site Address from the overview, and you should see the Web site. Refresh the app a few times and see if you notice any differences in the menu. + +Repeat these steps to add the Application settings to your Production App. + + +FOr the GitHub App, use the same application setting, but use this startup command: + +**java -jar /home/site/wwwroot/app.jar --server.port=80** + +![Application General Settings](./media/javacommandforwebapp.png) + diff --git a/Exercise4.md b/Exercise4.md new file mode 100644 index 0000000..7780171 --- /dev/null +++ b/Exercise4.md @@ -0,0 +1,100 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + + +### Exercise – 4 - Azure DevOps for CI + +[Related Microsoft Learn Materials](https://docs.microsoft.com/en-us/learn/modules/create-a-build-pipeline/) + + - Connect a repo to an Azure DevOps project using the Azure Pipelines extension in the GitHub marketplace + - Choose the default build template + - Replace the default template with a provided template + - Add and run the customized build template + - Review hosted agents + - Review the build log + +[Azure Pipelines](https://azure.microsoft.com/services/devops/pipelines/) enable you to continuously build, test, and deploy to any platform or cloud. It has cloud-hosted agents for Linux, macOS, and Windows; powerful workflows with native container support; and flexible deployments to Kubernetes, VMs, and serverless environments. + + ![](media/overview.png) + + +### Setting up Azure Pipelines + +1. On GitHub, navigate to your fork of the **devopsforjavashops-TestABAzureDevOPs** repository. +1. If you’re not already signed in to GitHub, sign in now. + + +### Exercise 1: Setting up automated CI/CD pipelines with Azure Pipelines + +The first thing we need to do is to connect GitHub with Azure DevOps, which we can do via the **Azure Pipelines** extension in the GitHub Marketplace. + +### Task 1: Installing Azure Pipelines from GitHub Marketplace + +**Azure Pipelines** is available in GitHub Marketplace which makes it even easier for teams to configure a CI/CD pipeline for any application using your preferred language and framework as part of your GitHub workflow in just a few simple steps + +1. Switch to the browser tab open to the root of your GitHub fork. + +1. Navigate to the **GitHub Marketplace**. + + ![](media/marketplace-github.png) + +1. Search for "**pipelines**" and click **Azure Pipelines**. + + ![](media/azurepipelines-extension.png) + +1. Scroll to the bottom and click **Install it for free**. If you previously installed Azure Pipelines, select **Configure access** instead to skip steps 6-8. + + ![](media/install-azurepipelines.png) + + > Azure Pipelines is free to use for both public and private repos. You get unlimited build minutes and 10 free parallel jobs for public repositories. For private repos, you get 1 free parallel job and 1800 minutes per month. If you have a need to scale your builds, you can add parallel job support for a nominal fee. + +1. If you have multiple **GitHub** accounts, select the one you forked the project to from the **Switch billing account** dropdown. + + ![](media/switch-account.png) + +1. Click **Complete order and begin installation**. + + ![](media/complete-order.png) + +1. Select the repositories you want to include (or **All repositories**) and click Install. + + > If you've previously installed Azure Pipelines, you may need to toggle between the **All** and **Select** radio buttons to enable the wizard in Task 2. You can always create the pipeline directly from Azure Pipelines if the wizard does not appear. + + ![](media/install.png) + +## Task 2: Configuring a Continuous Integration Pipeline + +Now that Azure Pipelines has been installed and configured, we can start building the pipelines but we will need to select a project where the pipeline will be saved. You may select an existing or create a new Azure DevOps project to hold and run the pipelines we need for continuous integration and continuous delivery. The first thing we'll do is to create a CI pipeline. + +1. Select the organization and Azure DevOps project that you want to use. If you do not have one, you can create both for free. + + ![](media/setup-azurepipelines.png) + +1. Select the forked repo. + + ![](media/select-forkedrepo.png) + + Every build pipeline is simply a set of tasks. Whether it's copying files, compiling the source, or publishing artifacts, the existing library of tasks covers the vast majority of scenarios. You can even create your own if you have specialized needs not already covered. We're going to use YAML, a markup syntax that lends itself well to describing the build pipeline. Note that the Node.js pipeline as a starting point based on an analysis of our source project. We'll replace the contents with the final YAML required for our project. + +1. Select **Maven** as the recommended template if prompted. + +1. Replace the default template YAML with the contents of the **provided-azure-pipeline.yml** file in your fork of the **devopsforjavashops-TestABAzureDevOPs** repository. + +#### Add a variable + +Click **Variables** on the right, then **New Variable**. + +The name should be **APP_CONFIGURATION_CONNECTION_STRING** and the value should be the connection string from your App Configuration, starting with **Endpoint=** + + ![](media/devopsvariable.png) + +1. Click **Save and run**. + +1. Confirm the **Save and run** to commit the YAML definition directly to the master branch of the repo. + +1. Follow the build through to completion. +1. Review the build logs + \ No newline at end of file diff --git a/Exercise5.md b/Exercise5.md new file mode 100644 index 0000000..4badf64 --- /dev/null +++ b/Exercise5.md @@ -0,0 +1,127 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + + +### Exercise 5 – Azure DevOps for CD +[Related Microsoft Learn Materials](https://docs.microsoft.com/en-us/learn/paths/deploy-applications-with-azure-devops/) + + - Create a new Release pipeline + Staging + Production + Deployment Slot + - Set up pre-and post deployment approvals + - Review automated options + - Set up CD trigger + - Run the release pipeline + - Review the release + + Now that the build pipeline is complete, we can turn our attention to creating a release pipeline. + + >Like the build templates, there are many packaged options available that cover common deployment scenarios, such as publishing to Azure. + +1. From the left hand menu, under **Pipelines** click **Releases**. Click **New Pipeline** to create a new CD pipeline to deploy the artifacts produced by the build. + + ![](media/image13.png) + +1. Add an artifact as shown here - Change source alias to **drop** + + ![](media/addartifact.png) + + The first item to define in a release pipeline is exactly what will be released and when. In our case, it's the output + generated from the build pipeline. Note that we could also assign a + schedule, such as if we wanted to release the latest build every + night. + +1. Select the associated artifact. + + ![](media/image15-1.png) + +1. Set **Source** to the build pipeline created earlier and **Default + version** to **Latest** and click **Add**. + + ![](media/image16.png) + + As we did with continuous integration starting on a source commit, we also want to have this pipeline automatically start when the build pipeline completes. It's just as easy. + +1. Click the **Triggers** button on the artifact. + + ![](media/image17.png) + +1. **Enable** continuous deployment, if it is not already enabled. + + ![](media/image18.png) + + + > Just like the build pipeline, the release pipeline is really just a set of tasks. There are many out-of-the-box tasks available, and you can build your own if needed. The first task our release requires is to set up the Azure deployment environment if it doesn't yet exist. After we add the task, I can authorize access to the Azure account I want to deploy + to and instruct it to use the variable name we just specified for the resource group name. + +### Configure the release pipeline stages + +1. Click the **Add task** button. + + Search for **"app service"** and **Add** an **Deploy a Java App to Azure App Service** task. + + 1. Select the newly created task. + 1. Click on the Stage at the top + 1. Select your subscription, and authorize. + 1. Select options as shown in this image + 1. Use this as the startup command: + + **java -jar /home/site/wwwroot/demo-0.0.1-SNAPSHOT.jar --server.port=80** + + + + > ![The release pipeline](media/devopsrelease2.png) + +1. Select the same subscription as earlier. + + +1. Enter the **App Service name** of your **Staging Server**. +1. Rename this task from **Stage 1** to **Staging** +1. Clone this task using the **Clone** button below the task +1. Rename the new task **Production** +1. Change the **App Service name** to your **Production Server** +1. Clone the **Production** task using the **Clone** button +1. Rename the task in the middle **Canary** +1. Click on the middle **Canary** task, then on the **Deploy Azure App Service** subtask. +1. Inside the subtask, choose **Deployment Slot**. Set the deployment slot to **Canary** inside your **Production Server**. + +1. ### Add Pre-deployment approvals + +> The release pipeline deploys to Staging, Canary and production. If the deployment to Staging fails, then deployment to the Canary deployment slot won't trigger. +It is recommended to always verify if your app is working properly in Staging before deploying to production. Adding approvals will ensure all the criteria are met before deploying to the next stage. To add approvals to your pipeline follow the steps below: + +1. Select the **Production** stage, **Pre-deployment conditions** icon then **Pre-deployment approvers**. + + > [!div class="mx-imgBorder"] + > ![pre-deployment approvers panel](media/open-approvers.png) + +1. In the **Approvers** text box, enter the user(s) that will be responsible for approving the deployment. + + > [!div class="mx-imgBorder"] + > ![Adding pre-deployment approvers](media/select-approvers.png) + + You can add as many approvers as you need, both individual users and organization groups. It's also possible to set up post-deployment approvals by selecting the "user" icon at the right side of the stage in the pipeline diagram. + +1. Select **Save**. + + > [!div class="mx-imgBorder"] + > ![Saving the release pipeline](media/save-definition.png) + +1. **Save** the pipeline. + +### Create a new release + +1. Select **+ Release** and then select **Create a Release** + +1. Select **Create** to start a new release. + +1. Navigate to the release summary by clicking on the **Release-1** link that appears. Click **In progress** to follow the release process. + +1. Note that it will take a few minutes for the app to finish deploying due to heavy first-time operations. + + +1. Select the **App Service Deploy** task to view the detailed log. You should find the URL to the published website here. **Ctrl+Click** the link to open it in a separate tab. diff --git a/Exercise6.md b/Exercise6.md new file mode 100644 index 0000000..88ffdc2 --- /dev/null +++ b/Exercise6.md @@ -0,0 +1,59 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + + +### Exercise 6 - A/B testing + +[Related Microsoft Learn Materials](https://docs.microsoft.com/en-us/learn/paths/deploy-applications-with-azure-devops/) + + - Make a change in GitHub + - Submit and accept a PR + - Review the change + Build + Release + Staging + Deployment slot + - Review the changes and function of deployment slots + - Approve the change – post-deployment approval + - Approve the change – pre-deployment approval + + +### Make a change to the sample application +In Visual Studio Code, Make a change to your local copy of the Sample App: + +In the file Views\Home\Index.cshtml + +Remove the comments in the following code: + +```HTML + +``` +It should look like this when you're done: + +```HTML +
+

Also

+

Check out this awesome workshop DevOps for Java shops!.

+
+``` + +### Push the changes to GitHub: + +1. Save the file. +1. Stage and commit the changes +1. Push to GitHub +1. Open your Azure DevOps project and follow the reelase and build. +1. The deployment should stop at the Canary deployment slot if approvals were set up correctly. +1. Select the **Canary App Service Deploy** task to view the detailed log. You should find the URL to the published website in the deployment slot. **Ctrl+Click** the link to open it in a separate tab. +1. Select the **Production App Service Deploy** task from the previous job to view the detailed log. You should find the URL to the published website in the production website. **Ctrl+Click** the link to open it in a separate tab. +1. Note the changes between the Canary deployment slot and the Production Website. +1. If you're happy with the changes, approve the deployment of the latest release to production. + + diff --git a/Exercise7.md b/Exercise7.md new file mode 100644 index 0000000..565bec2 --- /dev/null +++ b/Exercise7.md @@ -0,0 +1,72 @@ + +[Return to Agenda](README.md) +
+ +## Workshop: DevOps for Java shops + +### Exercise 7 - Generating a template with deployment manager + +[Related Materials on Microsoft Docs](https://cda.ms/1XJ) + +[Related Microsoft Learn Materials](https://cda.ms/1XK) + + - Deploy to an Azure Web App using the Web App Deployment Center using GitHub Actions + + - Review the workflow results + + - Set up an App Config connection string in GitHub Secrets + + - Rerun the deployment + + - Review the results + + + ## Deploy to an Azure Web App using the Web App Deployment Center + +You can quickly get started with GitHub Actions by using the App Service Deployment Center. This will automatically generate a workflow file based on your application stack and commit it to your GitHub repository in the correct directory. + +1. Navigate to the webapp that you just created in the Azure portal +1. On the left side, click **Deployment Center** +1. Under **Continuous Deployment (CI / CD)**, select **GitHub** +1. Next, select **GitHub Actions** +1. Use the dropdowns to select your GitHub repository, branch, and application stack + +1. On the final screen, you can review your selections and preview the workflow file that will be committed to the repository. If the selections are correct, click **Finish** + +This will commit the workflow file to the repository. The workflow to build and deploy your app will start immediately. + +## Review the workflow results +Note that the workflow fails, as we have not yet set up a connection string to the Application Configuration store. + +### Add an App Configuration connection string as a repository secret + +A GitHub tool called Secret Manager stores sensitive data for development work outside of your project tree. This approach helps prevent the accidental sharing of app secrets within source code. Complete the following steps to enable the use of Secret Manager in the ASP.NET Core project: + +Open the repo and navigate to settings > secrets > repository secret + + +![Application Settings](./media/githubsecret.png) + +Secrets are always encrypted when stored (encrypted-at-rest). + +Click **New secret**. + +The name should be **APP_CONFIGURATION_CONNECTION_STRING** and the value should be the connection string from your App Configuration, starting with **Endpoint=** + +When finished, click **Update**. + +Then edit the generated workflow in the repo, edit this workflow file and add this under name: + +env: + APP_CONFIGURATION_CONNECTION_STRING: ${{ secrets.APP_CONFIGURATION_CONNECTION_STRING }} + + +Commit The code. +The Action workflow should should restart at this time, and deploy correctly. + +Open the Web Site Address from the overview, and you should see the Web site. + + + + + diff --git a/GADemo/.gitignore b/GADemo/.gitignore deleted file mode 100644 index 549e00a..0000000 --- a/GADemo/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/GADemo/.mvn/wrapper/MavenWrapperDownloader.java b/GADemo/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index e76d1f3..0000000 --- a/GADemo/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/GADemo/.mvn/wrapper/maven-wrapper.jar b/GADemo/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a..0000000 Binary files a/GADemo/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/GADemo/.mvn/wrapper/maven-wrapper.properties b/GADemo/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572..0000000 --- a/GADemo/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/GADemo/mvnw b/GADemo/mvnw deleted file mode 100644 index a16b543..0000000 --- a/GADemo/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/GADemo/mvnw.cmd b/GADemo/mvnw.cmd deleted file mode 100644 index c8d4337..0000000 --- a/GADemo/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/GADemo/pom.xml b/GADemo/pom.xml deleted file mode 100644 index 06039c9..0000000 --- a/GADemo/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.3.RELEASE - - - com.example - demo - 0.0.1-SNAPSHOT - demo - Azure Feature Management with Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - com.microsoft.azure - spring-cloud-azure-appconfiguration-config-web - 1.1.5 - - - com.microsoft.azure - spring-cloud-azure-feature-management-web - 1.1.5 - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/GADemo/src/main/java/com/example/demo/DemoApplication.java b/GADemo/src/main/java/com/example/demo/DemoApplication.java deleted file mode 100644 index 9a3ca1d..0000000 --- a/GADemo/src/main/java/com/example/demo/DemoApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableConfigurationProperties(MessageProperties.class) -public class DemoApplication { - - public static void main(String[] args) { - SpringApplication.run(DemoApplication.class, args); - } -} \ No newline at end of file diff --git a/GADemo/src/main/java/com/example/demo/HelloController.java b/GADemo/src/main/java/com/example/demo/HelloController.java deleted file mode 100644 index f956f97..0000000 --- a/GADemo/src/main/java/com/example/demo/HelloController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; - -import com.microsoft.azure.spring.cloud.feature.manager.FeatureManager; -import org.springframework.web.bind.annotation.GetMapping; - - -@Controller -@ConfigurationProperties("controller") -public class HelloController { - - private FeatureManager featureManager; - - public HelloController(FeatureManager featureManager) { - this.featureManager = featureManager; - } - - @GetMapping("/welcome") - public String mainWithParam(Model model) { - model.addAttribute("Beta", featureManager.isEnabledAsync("featureManagement.Beta").block()); - return "welcome"; - } -} \ No newline at end of file diff --git a/GADemo/src/main/java/com/example/demo/MessageProperties.java b/GADemo/src/main/java/com/example/demo/MessageProperties.java deleted file mode 100644 index a46c52d..0000000 --- a/GADemo/src/main/java/com/example/demo/MessageProperties.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "config") -public class MessageProperties { - private String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} \ No newline at end of file diff --git a/GADemo/src/main/resources/application.properties b/GADemo/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/GADemo/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/GADemo/src/main/resources/bootstrap.properties b/GADemo/src/main/resources/bootstrap.properties deleted file mode 100644 index 83311e7..0000000 --- a/GADemo/src/main/resources/bootstrap.properties +++ /dev/null @@ -1 +0,0 @@ -spring.cloud.azure.appconfiguration.stores[0].connection-string= ${APP_CONFIGURATION_CONNECTION_STRING} diff --git a/GADemo/src/main/resources/favicon.ico b/GADemo/src/main/resources/favicon.ico deleted file mode 100644 index 92264f3..0000000 Binary files a/GADemo/src/main/resources/favicon.ico and /dev/null differ diff --git a/GADemo/src/main/resources/package/HelloController.java b/GADemo/src/main/resources/package/HelloController.java deleted file mode 100644 index f956f97..0000000 --- a/GADemo/src/main/resources/package/HelloController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; - -import com.microsoft.azure.spring.cloud.feature.manager.FeatureManager; -import org.springframework.web.bind.annotation.GetMapping; - - -@Controller -@ConfigurationProperties("controller") -public class HelloController { - - private FeatureManager featureManager; - - public HelloController(FeatureManager featureManager) { - this.featureManager = featureManager; - } - - @GetMapping("/welcome") - public String mainWithParam(Model model) { - model.addAttribute("Beta", featureManager.isEnabledAsync("featureManagement.Beta").block()); - return "welcome"; - } -} \ No newline at end of file diff --git a/GADemo/src/main/resources/package/MessageProperties.java b/GADemo/src/main/resources/package/MessageProperties.java deleted file mode 100644 index a46c52d..0000000 --- a/GADemo/src/main/resources/package/MessageProperties.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.demo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "config") -public class MessageProperties { - private String message; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} \ No newline at end of file diff --git a/GADemo/src/main/resources/static/CSS/main.css b/GADemo/src/main/resources/static/CSS/main.css deleted file mode 100644 index 26fc9d5..0000000 --- a/GADemo/src/main/resources/static/CSS/main.css +++ /dev/null @@ -1,28 +0,0 @@ -html { - position: relative; - min-height: 100%; -} -body { - margin-bottom: 60px; -} -.footer { - position: absolute; - bottom: 0; - width: 100%; - height: 60px; - line-height: 60px; - background-color: #f5f5f5; -} - -body > .container { - padding: 60px 15px 0; -} - -.footer > .container { - padding-right: 15px; - padding-left: 15px; -} - -code { - font-size: 80%; -} \ No newline at end of file diff --git a/GADemo/src/main/resources/static/images/bit.png b/GADemo/src/main/resources/static/images/bit.png deleted file mode 100644 index df92cb5..0000000 Binary files a/GADemo/src/main/resources/static/images/bit.png and /dev/null differ diff --git a/GADemo/src/main/resources/templates/welcome.html b/GADemo/src/main/resources/templates/welcome.html deleted file mode 100644 index e6e28e8..0000000 --- a/GADemo/src/main/resources/templates/welcome.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - Feature Management with Spring Cloud Azure - - - - - - - - - - -
- - -
-
-

Welcome

-

Learn more about Feature Management with Spring Cloud Azure

- BIT! -
- - - \ No newline at end of file diff --git a/GADemo/src/test/java/com/example/demo/DemoApplicationTests.java b/GADemo/src/test/java/com/example/demo/DemoApplicationTests.java deleted file mode 100644 index 2778a6a..0000000 --- a/GADemo/src/test/java/com/example/demo/DemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/README.md b/README.md index 4ef7f8e..0663043 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,11 @@ ## Workshop delivery -I'm happy to deliver this workshop virtually at destinations worldwide, and also to support anyone else who wants to deliver this, especially in local languages. - -### Next workshop: -[DevNexus 2021](https://devnexus.com/), February 18, Time TBD - - - -### Past deliveries: - October 12 - JDD Conference Europe. - - [JDD Conference Europe, Virtually (CET) October 12, 2020](https://jdd.org.pl/) +I'm happy to deliver this as a workshop or presentation at destinations worldwide, and also to support anyone else who wants to deliver this, especially in local languages. ## Prerequisites Here are list of free and open source [prerequisites](001_workshop_Prerequisites.md) - # Agenda ## DevOps with Azure @@ -26,32 +16,39 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites ### Introduction ### Exercise 1 – Fork and Clone GitHub repositories for this workshop - +[Go To Exercise](Exercise1.md) - Fork and clone a main branch - Making changes to the local repo - Staging - Committing -### Exercise 2 – Run and test the local code in VS Code - - - Opening the local folder - - Reviewing the code - - Running and testing the code - - Reviewing VS Code Git/GitHub - - Pushing to GitHub - ### Azure Basics - Resource Groups - Target environments - VMs, App Service, ACI, Kubernetes -### Exercise 3 - Set up Azure for this workshop - +### Exercise 2 - Set up Azure for this workshop +[Go To Exercise](Exercise2.md) - Create a resource group - Create a staging server - Create a production server - Create a deployment slot on the production server - Set the deployment slot to 50% traffic + + ### Feature Flags + - Azure App configuration Manager + - Options for filters + - Connecting apps to Feature Manager + - Feature flags in action + +### Exercise 3 - Setting up feature flags +[Go To Exercise](Exercise3.md) + + [Related Materials on Microsoft Docs](https://cda.ms/1XD) + - Create an App Configuration Store + - Add a feature Manager + - Set the percentage filter + ### DevOps Introduction - People, process and products - Builds @@ -70,6 +67,8 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites - GitHub Extensions ### Exercise – 4 - Azure DevOps for CI +[Go To Exercise](Exercise4.md) + - Connect a repo to an Azure DevOps project using the Azure Pipelines extension in the GitHub marketplace - Choose the default build template - Replace the default template with a provided template @@ -78,6 +77,7 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites - Review the build log ### Exercise 5 – Azure DevOps for CD +[Go To Exercise](Exercise5.md) - Create a new Release pipeline  Staging  Production @@ -89,6 +89,7 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites - Review the release ### Exercise 6 - A/B testing +[Go To Exercise](Exercise6.md) - Make a change in GitHub - Commit and Push - Review the change @@ -103,9 +104,9 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites ## DevOps with GitHub ### GitHub Actions Introduction -[Related materials on Microsoft Learn ](https://docs.microsoft.com/en-us/learn/modules/github-actions-automate-tasks/) +[Related materials on Microsoft Learn ](https://cda.ms/1XF) -[Related Materials on Microsoft Docs](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core?tabs=core3x) +[Related Materials on Microsoft Docs](https://cda.ms/1XG) - Workflows - Action blocks - Triggers @@ -114,26 +115,16 @@ Here are list of free and open source [prerequisites](001_workshop_Prerequisites - Logs ### GitHub Actions for CI and CD - [Related materials on Microsoft Learn ](https://docs.microsoft.com/en-us/learn/modules/github-actions-ci/) + [Related materials on Microsoft Learn ](https://cda.ms/1XH) - Using a Template - Building - Working with Artifacts - Testing - Automating Reviews - - ### Feature Flags - - Azure App configuration Manager - - Options for filters - - Connecting apps to Feature Manager - - Feature flags in action - -### Exercise 7 - Setting up feature flags in Azure app Configuration Manager - [Related Materials on Microsoft Docs](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core?tabs=core3x) - - Create an App Configuration Store - - Add a feature Manager - - Set the percentage filter + +### Exercise 7 - Generating a template with deployment manager +[Go To Exercise](Exercise7.md) -### Exercise 8 - Generating a template with deployment manager - Deploy to an Azure Web App - Review the workflow results - Set up a connection string to the App Configuration store diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 67e244e..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Maven -# Build your Java project and run tests with Apache Maven. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/java - -trigger: -- main - -pool: - vmImage: 'windows-latest' - -steps: -- task: Maven@3 - inputs: - mavenPomFile: 'demo/pom.xml' - mavenOptions: '-Xmx3072m' - javaHomeOption: 'JDKVersion' - jdkVersionOption: '1.8' - jdkArchitectureOption: 'x64' - publishJUnitResults: true - testResultsFiles: '**/surefire-reports/TEST-*.xml' - goals: 'package' diff --git a/media/add-beta-feature-flag.png b/media/add-beta-feature-flag.png new file mode 100644 index 0000000..c3c3ec7 Binary files /dev/null and b/media/add-beta-feature-flag.png differ diff --git a/media/addartifact.png b/media/addartifact.png new file mode 100644 index 0000000..1ff2b99 Binary files /dev/null and b/media/addartifact.png differ diff --git a/media/azure-portal-app-configuration-create.png b/media/azure-portal-app-configuration-create.png new file mode 100644 index 0000000..cec9c96 Binary files /dev/null and b/media/azure-portal-app-configuration-create.png differ diff --git a/media/azure-portal-search.png b/media/azure-portal-search.png new file mode 100644 index 0000000..af2ff2a Binary files /dev/null and b/media/azure-portal-search.png differ diff --git a/media/azuredevopsrelease.png b/media/azuredevopsrelease.png new file mode 100644 index 0000000..16e2120 Binary files /dev/null and b/media/azuredevopsrelease.png differ diff --git a/media/azurepipelines-extension.png b/media/azurepipelines-extension.png new file mode 100644 index 0000000..c631e0a Binary files /dev/null and b/media/azurepipelines-extension.png differ diff --git a/media/complete-order.png b/media/complete-order.png new file mode 100644 index 0000000..13a23ef Binary files /dev/null and b/media/complete-order.png differ diff --git a/media/configurationsource1.png b/media/configurationsource1.png new file mode 100644 index 0000000..8eb4cfd Binary files /dev/null and b/media/configurationsource1.png differ diff --git a/media/create-a-resource.png b/media/create-a-resource.png new file mode 100644 index 0000000..5addfc4 Binary files /dev/null and b/media/create-a-resource.png differ diff --git a/media/create-appserviceplan.png b/media/create-appserviceplan.png new file mode 100644 index 0000000..b6ad752 Binary files /dev/null and b/media/create-appserviceplan.png differ diff --git a/media/create-web-app.png b/media/create-web-app.png new file mode 100644 index 0000000..9afbcb6 Binary files /dev/null and b/media/create-web-app.png differ diff --git a/media/devopsrelease2.png b/media/devopsrelease2.png new file mode 100644 index 0000000..dca2a6f Binary files /dev/null and b/media/devopsrelease2.png differ diff --git a/media/devopsvariable.png b/media/devopsvariable.png new file mode 100644 index 0000000..ea6f4e7 Binary files /dev/null and b/media/devopsvariable.png differ diff --git a/media/githubsecret.png b/media/githubsecret.png new file mode 100644 index 0000000..89f9f33 Binary files /dev/null and b/media/githubsecret.png differ diff --git a/media/image13.png b/media/image13.png new file mode 100644 index 0000000..0242ce6 Binary files /dev/null and b/media/image13.png differ diff --git a/media/image14.png b/media/image14.png new file mode 100644 index 0000000..de8bd89 Binary files /dev/null and b/media/image14.png differ diff --git a/media/image15-1 (1).png b/media/image15-1 (1).png new file mode 100644 index 0000000..1ffbcd7 Binary files /dev/null and b/media/image15-1 (1).png differ diff --git a/media/image15-1.png b/media/image15-1.png new file mode 100644 index 0000000..1ffbcd7 Binary files /dev/null and b/media/image15-1.png differ diff --git a/media/image17.png b/media/image17.png new file mode 100644 index 0000000..c723407 Binary files /dev/null and b/media/image17.png differ diff --git a/media/image18.png b/media/image18.png new file mode 100644 index 0000000..be07fb4 Binary files /dev/null and b/media/image18.png differ diff --git a/media/image19.png b/media/image19.png new file mode 100644 index 0000000..c5cc9d0 Binary files /dev/null and b/media/image19.png differ diff --git a/media/image36.png b/media/image36.png new file mode 100644 index 0000000..3448317 Binary files /dev/null and b/media/image36.png differ diff --git a/media/install (1).png b/media/install (1).png new file mode 100644 index 0000000..ca6a7d2 Binary files /dev/null and b/media/install (1).png differ diff --git a/media/install-azurepipelines.png b/media/install-azurepipelines.png new file mode 100644 index 0000000..656c7c0 Binary files /dev/null and b/media/install-azurepipelines.png differ diff --git a/media/install.png b/media/install.png new file mode 100644 index 0000000..ca6a7d2 Binary files /dev/null and b/media/install.png differ diff --git a/media/javacommandforwebapp.png b/media/javacommandforwebapp.png new file mode 100644 index 0000000..eddb966 Binary files /dev/null and b/media/javacommandforwebapp.png differ diff --git a/media/manage-resource-groups-add-group-go-to-resource-group.png b/media/manage-resource-groups-add-group-go-to-resource-group.png new file mode 100644 index 0000000..907522c Binary files /dev/null and b/media/manage-resource-groups-add-group-go-to-resource-group.png differ diff --git a/media/manage-resource-groups-add-group.png b/media/manage-resource-groups-add-group.png new file mode 100644 index 0000000..56ea636 Binary files /dev/null and b/media/manage-resource-groups-add-group.png differ diff --git a/media/manage-resource-groups-create-group.png b/media/manage-resource-groups-create-group.png new file mode 100644 index 0000000..35aa71b Binary files /dev/null and b/media/manage-resource-groups-create-group.png differ diff --git a/media/open-approvers.png b/media/open-approvers.png new file mode 100644 index 0000000..3a4e09b Binary files /dev/null and b/media/open-approvers.png differ diff --git a/media/open-ui.png b/media/open-ui.png new file mode 100644 index 0000000..a9d2613 Binary files /dev/null and b/media/open-ui.png differ diff --git a/media/overview.png b/media/overview.png new file mode 100644 index 0000000..af77eec Binary files /dev/null and b/media/overview.png differ diff --git a/media/qgaddnewdeploymentslot.png b/media/qgaddnewdeploymentslot.png new file mode 100644 index 0000000..25dbe1a Binary files /dev/null and b/media/qgaddnewdeploymentslot.png differ diff --git a/media/save-definition.png b/media/save-definition.png new file mode 100644 index 0000000..2a7c16b Binary files /dev/null and b/media/save-definition.png differ diff --git a/media/select-approvers.png b/media/select-approvers.png new file mode 100644 index 0000000..c7bf8c3 Binary files /dev/null and b/media/select-approvers.png differ diff --git a/media/select-forkedrepo.png b/media/select-forkedrepo.png new file mode 100644 index 0000000..2fe256d Binary files /dev/null and b/media/select-forkedrepo.png differ diff --git a/media/setup-azurepipelines.png b/media/setup-azurepipelines.png new file mode 100644 index 0000000..beda562 Binary files /dev/null and b/media/setup-azurepipelines.png differ diff --git a/media/stagingtitle.png b/media/stagingtitle.png new file mode 100644 index 0000000..be07f27 Binary files /dev/null and b/media/stagingtitle.png differ diff --git a/media/switch-account.png b/media/switch-account.png new file mode 100644 index 0000000..071eb41 Binary files /dev/null and b/media/switch-account.png differ diff --git a/media/webappconfiguration.png b/media/webappconfiguration.png new file mode 100644 index 0000000..a9d2613 Binary files /dev/null and b/media/webappconfiguration.png differ