mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 06:16:37 +01:00
Merge pull request #877 from CitrixDevOps/master
Production build script changes
This commit is contained in:
commit
98392e6229
@ -55,7 +55,7 @@ fi
|
||||
|
||||
#update local xenadmin-ref.hg repository
|
||||
cp ${OUTPUT_DIR}/{manifest,latest-*-build,xcversion} ${ROOT}/xenadmin-ref.hg
|
||||
cd ${ROOT}/xenadmin-ref.hg && hg commit -m "Latest successful build ${get_BUILD_ID}"
|
||||
cd ${ROOT}/xenadmin-ref.hg && hg commit -u Jenkins -m "Latest successful build ${get_BUILD_ID}"
|
||||
|
||||
if [ ${XS_BRANCH} = "trunk" ]
|
||||
then
|
||||
|
30
mk/build.sh
30
mk/build.sh
@ -37,18 +37,26 @@
|
||||
# way that it will continue to work even if it's executed manually by a developer
|
||||
# or from a build automation system.
|
||||
|
||||
|
||||
FATAL=""
|
||||
for DEP in nunit-console.exe zip unzip mkisofs wget curl hg git patch mt.exe signtool.exe candle.exe light.exe
|
||||
do
|
||||
which $DEP >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
FATAL="$DEP $FATAL"
|
||||
function check_deps ()
|
||||
{
|
||||
local -a MISSING=()
|
||||
for DEP in "$@"
|
||||
do
|
||||
which $DEP >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
MISSING[${#MISSING}]=${DEP}
|
||||
fi
|
||||
done
|
||||
if [ ${#MISSING} -gt 0 ]; then
|
||||
echo "FATAL: One or more build tools were not found in PATH: ${MISSING[@]}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [ -n "${FATAL}" ]; then
|
||||
echo "FATAL: One or more build tools were not found in PATH: $FATAL"
|
||||
exit 1
|
||||
}
|
||||
|
||||
check_deps nunit-console.exe zip unzip mkisofs wget curl hg git patch mt.exe candle.exe light.exe
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" != production ]
|
||||
then
|
||||
check_deps signtool.exe
|
||||
fi
|
||||
|
||||
|
||||
|
@ -37,25 +37,18 @@ fi
|
||||
|
||||
source "$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/declarations.sh"
|
||||
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
JENKINS_SERVER=http://tizon-1.xs.cbg.ccsi.eng.citrite.net:8080
|
||||
else
|
||||
JENKINS_SERVER=http://tocco.do.citrite.net:8080
|
||||
fi
|
||||
|
||||
url="${JENKINS_SERVER}/job/${get_JOB_NAME}/"
|
||||
if curl -n -s --fail "${url}" -o out.tmp ; then
|
||||
if curl -n -s -k --fail "${url}" -o out.tmp ; then
|
||||
echo "INFO: URL exists: ${url}"
|
||||
else
|
||||
echo "ERROR: URL does not exist: ${url}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEXT_BN=$(curl -s -n "http://hg.uk.xensource.com/cgi/next-xenadmin?job=$get_JOB_NAME&number=$get_BUILD_NUMBER&rev=$get_REVISION")
|
||||
NEXT_BN=$(curl -s -n -k "http://hg.uk.xensource.com/cgi/next-xenadmin?job=$get_JOB_NAME&number=$get_BUILD_NUMBER&rev=$get_REVISION")
|
||||
|
||||
echo "INFO: NEXT_BN=${NEXT_BN}"
|
||||
|
||||
curl -s -n --data "nextBuildNumber=${NEXT_BN}" --header "Content-Type: application/x-www-form-urlencoded" ${JENKINS_SERVER}/job/${get_JOB_NAME}/nextbuildnumber/submit
|
||||
curl -s -n -k --data "nextBuildNumber=${NEXT_BN}" --header "Content-Type: application/x-www-form-urlencoded" ${JENKINS_SERVER}/job/${get_JOB_NAME}/nextbuildnumber/submit
|
||||
|
||||
set +u
|
||||
|
@ -142,7 +142,7 @@ OUTPUT_DIR=${ROOT}/output
|
||||
TEST_DIR=${ROOT}/tmp
|
||||
mkdir -p ${TEST_DIR}
|
||||
BUILD_ARCHIVE=${ROOT}/../builds/${get_BUILD_ID}/archive
|
||||
SECURE_BUILD_ARCHIVE_UNC=//10.80.13.10/distfiles/distfiles/windowsbuilds/WindowsBuilds/$get_JOB_NAME/$BUILD_NUMBER/
|
||||
SECURE_BUILD_ARCHIVE_UNC=//10.80.13.10/distfiles/distfiles/WindowsBuilds
|
||||
XENCENTER_LOGDIR="${ROOT}/log"
|
||||
mkdir -p ${XENCENTER_LOGDIR}
|
||||
|
||||
@ -150,30 +150,42 @@ mkdir -p ${XENCENTER_LOGDIR}
|
||||
#WEB_LATEST_BUILD is where the current build will retrieve some of its dependendencies,
|
||||
#i.e. XenCenterOvf, version number, branding info and XenServer.NET;
|
||||
#use xe-phase-2-latest to ensure we use a build where phases 1 and 2 have succeeded
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
WEB_LIB="http://admin/linux/distfiles/windows-build"
|
||||
WEB_LATEST_BUILD="http://admin/builds/carbon/${XS_BRANCH}/xe-phase-2-latest"
|
||||
REBRANDING_WEB_LATEST_BUILD="http://admin/builds/carbon/${XS_BRANCH}/xe-phase-rebrand-latest"
|
||||
else
|
||||
WEB_LIB="http://files.uk.xensource.com/linux/distfiles/windows-build"
|
||||
WEB_LATEST_BUILD="http://www.uk.xensource.com/carbon/${XS_BRANCH}/xe-phase-2-latest"
|
||||
REBRANDING_WEB_LATEST_BUILD="http://www.uk.xensource.com/carbon/${XS_BRANCH}/xe-phase-rebrand-latest"
|
||||
fi
|
||||
WEB_HOST="http://www.uk.xensource.com"
|
||||
WEB_LIB="${WEB_HOST}/linux/distfiles/windows-build"
|
||||
WEB_LATEST_BUILD="${WEB_HOST}/carbon/${XS_BRANCH}/xe-phase-2-latest"
|
||||
REBRANDING_WEB_LATEST_BUILD="${WEB_HOST}/carbon/${XS_BRANCH}/xe-phase-rebrand-latest"
|
||||
WEB_XE_PHASE_1=${WEB_LATEST_BUILD}/xe-phase-1
|
||||
WEB_XE_PHASE_2=${WEB_LATEST_BUILD}/xe-phase-2
|
||||
GLOBALS=${WEB_XE_PHASE_1}/globals
|
||||
WEB_TRUNK_LATEST_BUILD="${WEB_HOST}/carbon/trunk/xe-phase-2-latest"
|
||||
WEB_TRUNK_XE_PHASE_1=${WEB_TRUNK_LATEST_BUILD}/xe-phase-1
|
||||
TRUNK_GLOBALS=${WEB_TRUNK_XE_PHASE_1}/globals
|
||||
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
JENKINS_SERVER=https://jenkins-dev.xs.cbg.ccsi.eng.citrite.net
|
||||
else
|
||||
JENKINS_SERVER=http://tocco.do.citrite.net:8080
|
||||
fi
|
||||
|
||||
#this is where the build will find stuff from the latest dotnet-packages build
|
||||
WEB_DOTNET="http://tocco.do.citrite.net:8080/job/carbon_${XS_BRANCH}_dotnet-packages/lastSuccessfulBuild/artifact"
|
||||
WEB_DOTNET="${JENKINS_SERVER}/job/carbon_${XS_BRANCH}_dotnet-packages/lastSuccessfulBuild/artifact"
|
||||
DOTNET_BASE=${SECURE_BUILD_ARCHIVE_UNC}/carbon_${XS_BRANCH}_dotnet-packages
|
||||
DOTNET_LOC=$DOTNET_BASE/$(ls $DOTNET_BASE | /usr/bin/sort -n | tail -n 1)
|
||||
|
||||
# used to copy results out of the secure build enclave
|
||||
BUILD_TOOLS_REPO=git://admin/git/closed/windows/buildtools.git
|
||||
BUILD_TOOLS_REPO=git://hg.uk.xensource.com/closed/windows/buildtools.git
|
||||
BUILD_TOOLS=${SCRATCH_DIR}/buildtools.git
|
||||
STORE_FILES=${BUILD_TOOLS}/scripts/storefiles.py
|
||||
|
||||
# this is where the build will find the RPU hotfixes
|
||||
WEB_HOTFIXES=https://repo.citrite.net/builds/xs/hotfixes/${XS_BRANCH}
|
||||
WEB_HOTFIXES_ROOT=https://repo.citrite.net/builds/xs/hotfixes
|
||||
WEB_HOTFIXES=${WEB_HOTFIXES_ROOT}/${XS_BRANCH}
|
||||
WEB_HOTFIXES_TRUNK=${WEB_HOTFIXES_ROOT}/trunk
|
||||
|
||||
WGET_OPT="-T 10 -N -q"
|
||||
WGET () { wget ${WGET_OPT} "${@}"; }
|
||||
|
||||
#check there are xenserver builds on this branch before proceeding
|
||||
wget -T 10 -N -q --spider ${WEB_XE_PHASE_1}/globals || { echo 'FATAL: Unable to locate globals, xenadmin cannot be built if there is no succesfull build of xenserver published for the same branch.' ; exit 1; }
|
||||
WGET --spider ${GLOBALS} || WGET --spider ${TRUNK_GLOBALS} || { echo 'FATAL: Unable to locate globals, xenadmin cannot be built if there is no succesfull build of xenserver published for the same branch.' ; exit 1; }
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
#POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
echo Entered re-branding.sh
|
||||
|
||||
ROOT_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
|
||||
XENADMIN_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
|
||||
@ -189,7 +190,8 @@ rebranding_global ${REPO}/XenAdminTests/TestResources/state1.treeview.orgview.xm
|
||||
rebranding_global ${REPO}/XenAdminTests/TestResources/searchresults.xml
|
||||
rebranding_global ${REPO}/XenAdminTests/TestResources/state3.xml
|
||||
rebranding_global ${REPO}/XenAdminTests/XenAdminTests.csproj
|
||||
mv ${REPO}/XenAdminTests/TestResources/succeed.[xsupdate] ${REPO}/XenAdminTests/TestResources/succeed.${BRANDING_UPDATE}
|
||||
echo cp ${REPO}/XenAdminTests/TestResources/succeed.[xsupdate] ${REPO}/XenAdminTests/TestResources/succeed.${BRANDING_UPDATE}
|
||||
cp ${REPO}/XenAdminTests/TestResources/succeed.[xsupdate] ${REPO}/XenAdminTests/TestResources/succeed.${BRANDING_UPDATE}
|
||||
|
||||
#XenServerHealthCheck
|
||||
rebranding_global ${REPO}/XenServerHealthCheck/Branding.cs
|
||||
|
@ -34,7 +34,7 @@ set -eu
|
||||
|
||||
source "$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/declarations.sh"
|
||||
|
||||
WGET_OPT="-q -N --timestamp"
|
||||
_WGET () { WGET --timestamp "${@}"; }
|
||||
UNZIP="unzip -q -o"
|
||||
|
||||
mkdir_clean()
|
||||
@ -50,7 +50,7 @@ rm -rf ${TEST_DIR}/* ${XENCENTER_LOGDIR}/*.log || true
|
||||
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
git clone ${BUILD_TOOLS_REPO} ${BUILD_TOOLS}
|
||||
( mkdir -p ${BUILD_TOOLS%/*} && cd ${BUILD_TOOLS%/*} && git clone ${BUILD_TOOLS_REPO} ${BUILD_TOOLS##*/} )
|
||||
chmod +x ${BUILD_TOOLS}/scripts/storefiles.py
|
||||
fi
|
||||
|
||||
@ -69,42 +69,81 @@ DISCUTILS_DIR=${REPO}/DiscUtils/src/bin/Release
|
||||
MICROSOFT_DOTNET_FRAMEWORK_INSTALLER_DIR=${REPO}/dotNetFx452_web_setup
|
||||
PUTTY_DIR=${REPO}/putty
|
||||
|
||||
wget ${WGET_OPT} -O "${SCRATCH_DIR}/dotnet-packages-manifest" "${WEB_DOTNET}/manifest"
|
||||
mkdir_clean ${XMLRPC_DIR} && wget ${WGET_OPT} -P ${XMLRPC_DIR} ${WEB_DOTNET}/UNSIGNED/CookComputing.XmlRpcV2.dll
|
||||
mkdir_clean ${LOG4NET_DIR} && wget ${WGET_OPT} -P ${LOG4NET_DIR} ${WEB_DOTNET}/UNSIGNED/log4net.dll
|
||||
mkdir_clean ${SHARPZIPLIB_DIR} && wget ${WGET_OPT} -P ${SHARPZIPLIB_DIR} ${WEB_DOTNET}/UNSIGNED/ICSharpCode.SharpZipLib.dll
|
||||
mkdir_clean ${DOTNETZIP_DIR} && wget ${WGET_OPT} -P ${DOTNETZIP_DIR} ${WEB_DOTNET}/UNSIGNED/Ionic.Zip.dll
|
||||
mkdir_clean ${DISCUTILS_DIR} && wget ${WGET_OPT} -P ${DISCUTILS_DIR} ${WEB_DOTNET}/UNSIGNED/DiscUtils.dll
|
||||
mkdir_clean ${MICROSOFT_DOTNET_FRAMEWORK_INSTALLER_DIR} && wget ${WGET_OPT} -P "${MICROSOFT_DOTNET_FRAMEWORK_INSTALLER_DIR}" "${WEB_DOTNET}/NDP452-KB2901954-Web.exe"
|
||||
mkdir_clean ${PUTTY_DIR} && wget ${WGET_OPT} -P "${PUTTY_DIR}" "${WEB_DOTNET}/UNSIGNED/putty.exe"
|
||||
mkdir_clean ${XMLRPC_DIR}
|
||||
mkdir_clean ${LOG4NET_DIR}
|
||||
mkdir_clean ${SHARPZIPLIB_DIR}
|
||||
mkdir_clean ${DOTNETZIP_DIR}
|
||||
mkdir_clean ${DISCUTILS_DIR}
|
||||
mkdir_clean ${MICROSOFT_DOTNET_FRAMEWORK_INSTALLER_DIR}
|
||||
mkdir_clean ${PUTTY_DIR}
|
||||
|
||||
wget ${WGET_OPT} -P "${REPO}" "${WEB_DOTNET}/sign.bat" && chmod a+x ${REPO}/sign.bat
|
||||
dotnet_cp_to_dir ()
|
||||
{
|
||||
local -r destdir="${1}"; shift
|
||||
local -r src="${1}"; shift
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
cp "${DOTNET_LOC}/${src}" "${destdir}/"
|
||||
else
|
||||
_WGET -P "${destdir}" "${WEB_DOTNET}/${src}"
|
||||
fi
|
||||
}
|
||||
|
||||
dotnet_cp_file ()
|
||||
{
|
||||
local -r src="${1}"; shift
|
||||
local -r dest="${1}"; shift
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
cp "${DOTNET_LOC}/${src}" "${dest}"
|
||||
else
|
||||
_WGET -O "${dest}" "${WEB_DOTNET}/${src}"
|
||||
fi
|
||||
}
|
||||
|
||||
dotnet_cp_file "manifest" "${SCRATCH_DIR}/dotnet-packages-manifest"
|
||||
dotnet_cp_to_dir "${XMLRPC_DIR}" "UNSIGNED/CookComputing.XmlRpcV2.dll"
|
||||
dotnet_cp_to_dir "${LOG4NET_DIR}" "UNSIGNED/log4net.dll"
|
||||
dotnet_cp_to_dir "${SHARPZIPLIB_DIR}" "UNSIGNED/ICSharpCode.SharpZipLib.dll"
|
||||
dotnet_cp_to_dir "${DOTNETZIP_DIR}" "UNSIGNED/Ionic.Zip.dll"
|
||||
dotnet_cp_to_dir "${DISCUTILS_DIR}" "UNSIGNED/DiscUtils.dll"
|
||||
dotnet_cp_to_dir "${MICROSOFT_DOTNET_FRAMEWORK_INSTALLER_DIR}" "NDP452-KB2901954-Web.exe"
|
||||
dotnet_cp_to_dir "${PUTTY_DIR}" "UNSIGNED/putty.exe"
|
||||
dotnet_cp_to_dir "${REPO}" "sign.bat" && chmod a+x "${REPO}/sign.bat"
|
||||
|
||||
#bring in stuff from xencenter-ovf latest xe-phase-1
|
||||
wget ${WGET_OPT} -P "${SCRATCH_DIR}" "${WEB_XE_PHASE_1}/XenCenterOVF.zip"
|
||||
_WGET -P "${SCRATCH_DIR}" "${WEB_XE_PHASE_1}/XenCenterOVF.zip"
|
||||
${UNZIP} -d ${REPO}/XenOvfApi ${SCRATCH_DIR}/XenCenterOVF.zip
|
||||
|
||||
#bring manifest from latest xe-phase-1
|
||||
wget ${WGET_OPT} -O ${SCRATCH_DIR}/xe-phase-1-manifest "${WEB_XE_PHASE_1}/manifest"
|
||||
_WGET -O ${SCRATCH_DIR}/xe-phase-1-manifest "${WEB_XE_PHASE_1}/manifest"
|
||||
|
||||
#bring XenServer.NET from latest xe-phase-2
|
||||
wget ${WGET_OPT} -P "${REPO}" "${WEB_XE_PHASE_2}/XenServer-SDK.zip" && ${UNZIP} -j ${REPO}/XenServer-SDK.zip XenServer-SDK/XenServer.NET/bin/XenServer.dll XenServer-SDK/XenServer.NET/bin/CookComputing.XmlRpcV2.dll -d ${REPO}/XenServer.NET
|
||||
_WGET -P "${REPO}" "${WEB_XE_PHASE_2}/XenServer-SDK.zip" && ${UNZIP} -j ${REPO}/XenServer-SDK.zip XenServer-SDK/XenServer.NET/bin/XenServer.dll XenServer-SDK/XenServer.NET/bin/CookComputing.XmlRpcV2.dll -d ${REPO}/XenServer.NET
|
||||
|
||||
#bring in some more libraries
|
||||
mkdir_clean ${REPO}/NUnit
|
||||
wget ${WGET_OPT} -P ${REPO}/NUnit ${WEB_LIB}/nunit.framework.dll
|
||||
wget ${WGET_OPT} -O ${REPO}/NUnit/Moq.dll ${WEB_LIB}/Moq_dotnet4.dll
|
||||
wget ${WGET_OPT} -P ${SCRATCH_DIR} ${WEB_LIB}/{wix39-sources-debug.zip,wix39-binaries.zip}
|
||||
_WGET -P ${REPO}/NUnit ${WEB_LIB}/nunit.framework.dll
|
||||
_WGET -O ${REPO}/NUnit/Moq.dll ${WEB_LIB}/Moq_dotnet4.dll
|
||||
_WGET -P ${SCRATCH_DIR} ${WEB_LIB}/{wix39-sources-debug.zip,wix39-binaries.zip}
|
||||
|
||||
source ${REPO}/Branding/branding.sh
|
||||
source ${REPO}/mk/re-branding.sh
|
||||
|
||||
|
||||
function get_hotfix ()
|
||||
{
|
||||
local -r hotfix="$1"
|
||||
local -r p=${REPO}/Branding/Hotfixes
|
||||
_WGET -P ${p} ${WEB_HOTFIXES}/${hotfix} || _WGET -P ${p} ${WEB_HOTFIXES_TRUNK}/${hotfix}
|
||||
}
|
||||
|
||||
#bring RPU hotfixes
|
||||
if [ "${BRANDING_UPDATE}" = "xsupdate" ]
|
||||
then
|
||||
wget ${WGET_OPT} -P ${REPO}/Branding/Hotfixes ${WEB_HOTFIXES}/RPU001/1.0/RPU001.xsupdate
|
||||
wget ${WGET_OPT} -P ${REPO}/Branding/Hotfixes ${WEB_HOTFIXES}/RPU001/1.0/RPU001-src-pkgs.tar && cd ${REPO}/Branding/Hotfixes && gzip RPU001-src-pkgs.tar
|
||||
wget ${WGET_OPT} -P ${REPO}/Branding/Hotfixes ${WEB_HOTFIXES}/RPU002/1.0/RPU002.xsupdate
|
||||
get_hotfix RPU001/1.0/RPU001.xsupdate
|
||||
get_hotfix RPU001/1.0/RPU001-src-pkgs.tar && cd ${REPO}/Branding/Hotfixes && rm -f RPU001-src-pkgs.tar.gz && gzip RPU001-src-pkgs.tar
|
||||
get_hotfix RPU002/1.0/RPU002.xsupdate
|
||||
fi
|
||||
|
||||
#build
|
||||
@ -252,7 +291,7 @@ rm -rf ${OUTPUT_DIR}/PACKAGES.main/opt
|
||||
#bring in the pdbs from dotnet-packages latest build
|
||||
for pdb in CookComputing.XmlRpcV2.pdb DiscUtils.pdb ICSharpCode.SharpZipLib.pdb Ionic.Zip.pdb log4net.pdb
|
||||
do
|
||||
wget ${WGET_OPT} -P "${OUTPUT_DIR}" "${WEB_DOTNET}/${pdb}"
|
||||
dotnet_cp_to_dir "${OUTPUT_DIR}" "${pdb}"
|
||||
done
|
||||
|
||||
#create manifest
|
||||
@ -262,11 +301,13 @@ cat ${SCRATCH_DIR}/xe-phase-1-manifest | grep xencenter-ovf >> ${OUTPUT_DIR}/man
|
||||
cat ${SCRATCH_DIR}/xe-phase-1-manifest | grep chroot-lenny >> ${OUTPUT_DIR}/manifest
|
||||
cat ${SCRATCH_DIR}/xe-phase-1-manifest | grep branding >> ${OUTPUT_DIR}/manifest
|
||||
cat ${SCRATCH_DIR}/dotnet-packages-manifest >> ${OUTPUT_DIR}/manifest
|
||||
get_BUILD_PATH=/usr/groups/xen/carbon/windowsbuilds/WindowsBuilds/${get_JOB_NAME}/${BUILD_NUMBER}
|
||||
if [ "${BUILD_KIND:+$BUILD_KIND}" = production ]
|
||||
then
|
||||
echo ${get_BUILD_URL} >> ${OUTPUT_DIR}/latest-secure-build
|
||||
echo ${get_BUILD_URL} > ${OUTPUT_DIR}/latest-secure-build
|
||||
echo ${get_BUILD_PATH} > ${OUTPUT_DIR}/latest-successful-build
|
||||
else
|
||||
echo ${get_BUILD_URL} >> ${OUTPUT_DIR}/latest-successful-build
|
||||
echo ${get_BUILD_URL} > ${OUTPUT_DIR}/latest-successful-build
|
||||
fi
|
||||
|
||||
# Write out version information
|
||||
|
Loading…
Reference in New Issue
Block a user