diff --git a/.github/workflows/convert.sh b/.github/workflows/convert.sh new file mode 100755 index 000000000..14145778c --- /dev/null +++ b/.github/workflows/convert.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# convert.sh +# +# Perform the conversion from Chromium to ungoogled-chromium +# + +set -e + +test -n "$DOWNLOAD_DIR" +test -n "$OUTPUT_DIR" +test -n "$STATE_DIR" +test -n "$WORK_DIR" +test -d "$GITHUB_WORKSPACE" + +uc_git=$GITHUB_WORKSPACE/ungoogled-chromium + +wrap= + +tab=' ' + +run() +{ + echo "+ $*" + env "$@" + echo ' ' +} + +do_conversion() +{ + local codename="$1" deb_version="$2" uc_tag="$3" + local conv_dir=$WORK_DIR/convert/$codename + + echo "Using ungoogled-chromium Git tag $uc_tag ..." + (cd $uc_git && run git switch --detach $uc_tag) + + rm -rf $conv_dir + mkdir -p $conv_dir + + echo 'Unpacking source package ...' + run dpkg-source \ + --no-copy \ + --require-valid-signature \ + --skip-patches \ + --extract \ + $DOWNLOAD_DIR/chromium_$deb_version.dsc \ + $conv_dir/chromium-src + + local uc_rev="${uc_tag##*-}" + local ucd_convert=$GITHUB_WORKSPACE/convert + + local ups_version="${deb_version%-*}" + + # NOTE: Nested output groups are not yet supported + # https://github.com/actions/toolkit/issues/1001 + #echo '::group::Ungoogling Chromium' + + (cd $conv_dir && run $wrap make -f $ucd_convert/Makefile \ + convert ug-tarball clean \ + VERSION=$ups_version \ + ORIG_SOURCE=chromium-src \ + ORIG_TARBALL=$DOWNLOAD_DIR/chromium_$ups_version.orig.tar.xz \ + UNGOOGLED=$uc_git \ + DEBIAN_CONVERT=$ucd_convert \ + ADD_VERSION_SUFFIX=.$uc_rev \ + DISTRIBUTION= \ + INPLACE=1 + ) + + #echo '::endgroup::' + + echo 'Building new source package ...' + (cd $conv_dir && run time -p dpkg-source --no-preparation --no-generate-diff --build chromium-src 2>&1) + + local uc_version=$deb_version.$uc_rev + + local files= + files="$codename/ungoogled-chromium_$uc_version.dsc" + files+=" $codename/ungoogled-chromium_$uc_version.debian.tar.xz" + ofiles=" $codename/ungoogled-chromium_$ups_version.orig.tar.xz" + + mkdir -p $OUTPUT_DIR/$codename + + (cd $conv_dir/.. + ls -LUl $files $ofiles + echo ' '; echo 'SHA-256 sums:' + sha256sum $files $ofiles + cp -np $files $OUTPUT_DIR/$codename/ + ) + + # Note: Do NOT save the .orig tarball as an artifact! + # It's enormous, and we do not modify it. + + rm -rf $conv_dir +} + +for todo in $WORK_DIR/todo.*.chromium.txt +do + test -f "$todo" || continue + IFS="$tab" read codename deb_version uc_tag < $todo + + echo "::group::Build DEB($codename, $deb_version) + UC($uc_tag)" + + do_conversion "$codename" "$deb_version" "$uc_tag" + + echo '::endgroup::' + + case "$codename" in + debian-sid | debian-unstable) + # do Ubuntu conversions here if desired + ;; + esac + + cat $todo >> $STATE_DIR/done.chromium.txt + rm -f $todo + echo ' ' +done + +# end convert.sh diff --git a/.github/workflows/dpkg-source-build.patch b/.github/workflows/dpkg-source-build.patch new file mode 100644 index 000000000..b829399c9 --- /dev/null +++ b/.github/workflows/dpkg-source-build.patch @@ -0,0 +1,99 @@ +This patch greatly speeds up the "dpkg-source --build" operation when the +--no-generate-diff option is used. It has been submitted to the upstream +project, but discussion on it remains unresolved: + + https://lists.debian.org/debian-dpkg/2023/09/msg00013.html + +This patch specifically targets the version of dpkg in Ubuntu 22.04. + +--- /usr/share/perl5/Dpkg/Source/Package/V2.pm.orig ++++ /usr/share/perl5/Dpkg/Source/Package/V2.pm +@@ -60,6 +60,7 @@ + $self->{options}{unapply_patches} //= 'auto'; + $self->{options}{skip_debianization} //= 0; + $self->{options}{create_empty_orig} //= 0; ++ $self->{options}{generate_diff} //= 1; + $self->{options}{auto_commit} //= 0; + $self->{options}{ignore_bad_version} //= 0; + } +@@ -94,6 +95,10 @@ + help => N_('create an empty original tarball if missing'), + when => 'build', + }, { ++ name => '--no-generate-diff', ++ help => N_('do not generate diff against upstream sources'), ++ when => 'build', ++ }, { + name => '--abort-on-upstream-changes', + help => N_('abort if generated diff has upstream files changes'), + when => 'build', +@@ -145,6 +150,9 @@ + } elsif ($opt eq '--create-empty-orig') { + $self->{options}{create_empty_orig} = 1; + return 1; ++ } elsif ($opt eq '--no-generate-diff') { ++ $self->{options}{generate_diff} = 0; ++ return 1; + } elsif ($opt eq '--abort-on-upstream-changes') { + $self->{options}{auto_commit} = 0; + return 1; +@@ -448,6 +456,8 @@ + } + } + ++ return if !$opts{do_diff}; ++ + # Unpack a second copy for comparison + my $tmp = tempdir("$dirname.orig.XXXXXX", DIR => $updir); + push_exit_handler(sub { erasedir($tmp) }); +@@ -516,6 +526,21 @@ + usageerr(g_("-b takes only one parameter with format '%s'"), + $self->{fields}{'Format'}); + } ++ if (!$self->{options}{generate_diff} && ++ ($self->{options}{include_removal} || ++ $self->{options}{include_timestamp} || ++ $self->{options}{include_binaries} || ++ $self->{options}{create_empty_orig} || ++ $self->{options}{auto_commit})) { ++ my @incompat = ( ++ "--include-removal", ++ "--include-timestamp", ++ "--include-binaries", ++ "--create-empty-orig", ++ "--auto-commit" ++ ); ++ usageerr(g_("--no-generate-diff is incompatible with the following options: %s"), join(", ", @incompat)); ++ } + $self->prepare_build($dir); + + my $include_binaries = $self->{options}{include_binaries}; +@@ -555,8 +580,9 @@ + header_from => $autopatch, + handle_binary => $handle_binary, + skip_auto => $self->{options}{auto_commit}, ++ do_diff => $self->{options}{generate_diff}, + usage => 'build'); +- unless (-z $tmpdiff or $self->{options}{auto_commit}) { ++ unless (!$tmpdiff or -z $tmpdiff or $self->{options}{auto_commit}) { + info(g_('Hint: make sure the version in debian/changelog matches ' . + 'the unpacked source tree')); + info(g_('you can integrate the local changes with %s'), +@@ -564,7 +590,7 @@ + error(g_('aborting due to unexpected upstream changes, see %s'), + $tmpdiff); + } +- push_exit_handler(sub { unlink($tmpdiff) }); ++ push_exit_handler(sub { !$tmpdiff or unlink($tmpdiff) }); + $binaryfiles->update_debian_source_include_binaries() if $include_binaries; + + # Install the diff as the new autopatch +@@ -576,7 +602,7 @@ + $autopatch) if -e $autopatch; + rmdir(File::Spec->catdir($dir, 'debian', 'patches')); # No check on purpose + } +- unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff); ++ !$tmpdiff or unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff); + pop_exit_handler(); + + # Create the debian.tar diff --git a/.github/workflows/get-latest.sh b/.github/workflows/get-latest.sh new file mode 100755 index 000000000..5e05b1b11 --- /dev/null +++ b/.github/workflows/get-latest.sh @@ -0,0 +1,213 @@ +#!/bin/bash +# get-latest.sh +# +# Determine the latest version(s) of the "chromium" package in the Debian +# repositories, download the corresponding source package(s), and look for +# matching ungoogled-chromium Git release tags. +# + +set -e + +test -n "$DOWNLOAD_DIR" +test -n "$STATE_DIR" +test -n "$WORK_DIR" +test -d "$GITHUB_WORKSPACE" + +debian_codename_list='bookworm sid' + +package=chromium + +obsolete_list=$WORK_DIR/obsolete.$package.txt + +debian_incoming_url=https://incoming.debian.org/debian-buildd +debian_security_url=https://security.debian.org/debian-security + +chdist_dir=$STATE_DIR/chdist-data +chdist="chdist --data-dir=$chdist_dir" +uc_git=$GITHUB_WORKSPACE/ungoogled-chromium + +tab=' ' + +do_update=yes +do_download=yes +do_status=no + +todo_flag= # Note: "false" is interpreted by GitHub as true >_< + +export LC_COLLATE=C + +while [ -n "$1" ] +do + case "$1" in + --skip-update) do_update=no ;; + --skip-download) do_download=no ;; + --exit-status) do_status=yes ;; + '') ;; + -*) echo "$0: error: unrecognized option \"$1\""; exit 1 ;; + *) echo "$0: error: unrecognized argument \"$1\""; exit 1 ;; + esac + shift +done + +if [ ! -d $uc_git ] +then + echo 'Error: ungoogled-chromium Git repository is not present' + exit 1 +fi + +run() +{ + echo "+ $*" + env "$@" + echo ' ' +} + +check_debian_release() +{ + local deb_codename="debian-$1" + + # Latest version of the package in the APT repo + # (for the specified release, e.g. "unstable" or "bullseye") + local deb_version=$($chdist apt-get $deb_codename --print-uris source $package 2>/dev/null \ + | awk '/\.dsc /{print $2}' \ + | sed -r 's/^[^_]+_//; s/\.dsc$//') + + if [ -n "$deb_version" ] + then + echo "$deb_codename/$package: current package version $deb_version" + else + # Note that Debian's incoming repo doesn't always have + # a given package available; this is not an error + echo "$deb_codename/$package: no version available" + echo ' ' + return + fi + + # Upstream project version (remove the package-revision suffix) + local ups_version="${deb_version%-*}" + if [ -z "$ups_version" ] + then + echo "error: package version string is bogus" + exit 1 + fi + + # Latest matching ungoogled-chromium tag + local uc_tag=$(cd $uc_git && git tag --list --sort=-version:refname "$ups_version-*" | head -n1) + + if [ -n "$uc_tag" ] + then + echo "ungoogled-chromium: latest matching tag $uc_tag" + else + echo "ungoogled-chromium: no matching tag for $ups_version" + echo ' ' + return + fi + + local combo_line="$deb_codename$tab$deb_version$tab$uc_tag" + + # Have we built this combination before? + if grep -Fqx "$combo_line" $STATE_DIR/done.$package.txt 2>/dev/null + then + echo "Already built DEB($deb_codename, $deb_version) + UC($uc_tag)" + echo ' ' + return + else + echo "Will build DEB($deb_codename, $deb_version) + UC($uc_tag)" + fi + + if [ $do_download = yes ] + then + echo ' ' + echo "$deb_codename/$package: downloading source package files" + + (cd $DOWNLOAD_DIR && run $chdist apt-get $deb_codename --quiet --only-source --download-only source $package) + fi + + echo ' ' + + echo "$combo_line" > $WORK_DIR/todo.$deb_codename.$package.txt + todo_flag=true +} + +find_obsolete_files() +{ + : > $obsolete_list + + local keep_count=$(wc -w <<<$debian_codename_list) + local orig_file + + # We should not need to hang on to more orig source tarballs than + # the number of codenames we are monitoring + + (cd $DOWNLOAD_DIR && ls -1t ${package}_*.orig.tar.* 2>/dev/null) \ + | tail -n +$((keep_count + 1)) \ + | while read orig_file + do + local prefix=${orig_file%.orig.tar.*} + + (cd $DOWNLOAD_DIR && ls -1 $orig_file $prefix-*.dsc $prefix-*.debian.tar.*) \ + >> $obsolete_list + done +} + +# +# First-time setup +# + +mkdir -p $DOWNLOAD_DIR $STATE_DIR $chdist_dir +new_apt=no + +for codename in $debian_codename_list +do + deb_codename=debian-$codename + test ! -d $chdist_dir/$deb_codename || continue + echo "Initializing APT index for $deb_codename ..." + + case "$deb_codename" in + debian-sid | debian-unstable) + run $chdist create $deb_codename $debian_incoming_url buildd-$codename main + ;; + + *) + run $chdist create $deb_codename $debian_security_url $codename-security main + ;; + esac + + new_apt=yes +done + +if [ $new_apt = yes ] +then + # We only need deb-src lines, no binary packages + find $chdist_dir -type f -name sources.list \ + -exec sed -i '/^deb /s/^/#/' {} + +fi + +# +# Do version checks +# + +for codename in $debian_codename_list +do + deb_codename=debian-$codename + + if [ $do_update = yes ] + then + echo "Updating APT index for $deb_codename ..." + run $chdist apt-get $deb_codename update --error-on=any + fi + + check_debian_release $codename +done + +find_obsolete_files + +if [ -n "$GITHUB_OUTPUT" ] +then + echo todo=$todo_flag >> $GITHUB_OUTPUT +fi + +test $do_status = no || test $todo_flag = true || exit 1 +exit 0 + +# end get-latest.sh diff --git a/.github/workflows/obs-upload.sh b/.github/workflows/obs-upload.sh index 880268ffc..18190ed6d 100755 --- a/.github/workflows/obs-upload.sh +++ b/.github/workflows/obs-upload.sh @@ -1,136 +1,199 @@ -#!/bin/sh +#!/bin/bash +# obs-upload.sh +# +# Upload Debian source package files to the openSUSE Build Service +# (https://build.opensuse.org/) +# + set -e -RT_DIR="$PWD" -DB_DIR="$RT_DIR/debian" -UC_DIR="$DB_DIR/submodules/ungoogled-chromium" +test -n "$DOWNLOAD_DIR" +test -n "$OUTPUT_DIR" +test -n "$WORK_DIR" + +upload_dir=$WORK_DIR/upload -for i in OBS_API_USERNAME OBS_API_PASSWORD +for var in OSC_USERNAME OSC_PASSWORD do - if test -z "$(eval echo \$$i)" - then - echo "$i is not in the environment. Aborting." - exit 1 - fi + if test -z "$(eval echo \$$var)" + then + echo "$var is not set in the environment. Aborting." + exit 1 + fi done -PROJECT="${OBS_API_PROJECT:-home:$OBS_API_USERNAME}" +test -n "$OSC" || OSC=osc +test -n "$OBS_PROJECT" || export OBS_PROJECT="home:$OSC_USERNAME" + +# Do NOT use a config file, just rely on the env vars +# +export OSC_CONFIG=/dev/null -case "$GITHUB_EVENT_NAME" in - workflow_dispatch) REPOSITORY="$PROJECT:testing" ;; - push) REPOSITORY="$PROJECT" ;; - *) echo "Not running as part of a GitHub workflow. Aborting."; exit 1 ;; -esac +if ! $OSC --help > /dev/null 2>&1 +then + echo 'osc(1) is not available. Aborting.' + exit 1 +fi -curl() +# API reference: https://api.opensuse.org/apidocs/ + +osc_add_file() { - for i in `seq 1 5` - do - { - command curl -sS -K - "$@" << EOF -user="$OBS_API_USERNAME:$OBS_API_PASSWORD" -EOF - } && return 0 || sleep 30s - done - return 1 + local project="$1" package="$2" local_file="$3" remote_file="$4" + test -n "$remote_file" || remote_file="$local_file" + + $OSC api -T "$local_file" "/source/$project/$package/$remote_file" > /dev/null } -debian/rules changelog control +osc_delete_file() +{ + local project="$1" package="$2" file="$3" + + $OSC api -X DELETE "/source/$project/$package/$file" > /dev/null +} -read UC_VERSION < $UC_DIR/chromium_version.txt -AUTHOR=`grep 'AUTHOR *:=' $DB_DIR/rules | cut -f 2 -d '=' | sed -r 's;^ *| *$;;g'` -NODE_VERSION=`grep 'NODE_VERSION *:=' $DB_DIR/rules | cut -f 2 -d '=' | sed -r 's;^ *| *$;;g'` +osc_commit() +{ + local project="$1" package="$2" comment="$3" + local comment_enc=$(printf '%s' "$comment" | jq -Rrs @uri) + + # Note: The regular "osc commit" command requires a checked-out + # package directory, and is thus not suitable for our use here + + $OSC api -m POST "/source/$project/$package?cmd=commit&comment=$comment_enc" > /dev/null +} + +obs_sync_files() +{ + local codename="$1" dir="$2" commit_message="$3" + local remote_list=$WORK_DIR/remote-files.txt + + echo "Syncing files to OBS project/package: $OBS_PROJECT/$codename" + + $OSC list -l $OBS_PROJECT $codename > $remote_list + + (cd $dir + + do_commit=false + + while read md5 rev size d1 d2 d3 remote_file + do + if [ ! -f "$remote_file" ] + then + echo "D $codename/$remote_file ..." + osc_delete_file $OBS_PROJECT $codename "$remote_file" + do_commit=true + fi + done < $remote_list + + for local_file in * + do + do_upload=false + + if awk -v file="$local_file" \ + '$7 == file {print "found"}' $remote_list \ + | grep -q . + then + # File present on OBS, check MD5 sum + md5=$(md5sum "$local_file" | awk '{print $1}') + awk \ + -v md5="$md5" \ + -v file="$local_file" \ + '$1 == md5 && $7 == file {print "found"}' \ + $remote_list \ + | grep -q . || do_upload=true + else + # File not present on OBS + do_upload=true + fi + + if $do_upload + then + echo "A $codename/$local_file ..." + osc_add_file $OBS_PROJECT $codename "$local_file" + do_commit=true + fi + done + + if $do_commit + then + echo 'Committing update ...' + osc_commit $OBS_PROJECT $codename "$commit_message" + else + echo 'No changes to commit.' + fi + + ) # return to previous dir + + rm -f $remote_list +} + +for dsc_file in $OUTPUT_DIR/*/*.dsc +do + dir=$(dirname $dsc_file) + codename=$(basename $dir) -cat > _service << EOF + package=$(sed -n 's/^Source: //p' $dsc_file) + version=$(sed -n 's/^Version: //p' $dsc_file) + + sums=$(grep -E '^ [0-9a-f]{64} ' $dsc_file) + + orig_src=$(echo "$sums" | awk '/\.orig\.tar\./ {print $3}') + debian_src=$(echo "$sums" | awk '/\.debian\.tar\./ {print $3}') + + dsc_sha256=$(sha256sum $dsc_file | awk '{print $1}') + + orig_src_sha256=$(echo "$sums" | awk '/\.orig\.tar\./ {print $1}') + debian_src_sha256=$(echo "$sums" | awk '/\.debian\.tar\./ {print $1}') + + chromium_orig_src=$DOWNLOAD_DIR/${orig_src#ungoogled-} + test -s $chromium_orig_src + + run_url= + test -z "$GITHUB_RUN_ID" || run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" + + if [ -n "$run_url" ] + then + comment="Origin: $run_url" + else + comment="Origin: manual upload" + fi + + rm -rf $upload_dir + mkdir -p $upload_dir + + ln $dsc_file $dir/$debian_src $upload_dir/ + ln $chromium_orig_src $upload_dir/$orig_src + + # Reference: https://en.opensuse.org/openSUSE:Build_Service_Concept_SourceService + # + cat > $upload_dir/_service << END + - - https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$UC_VERSION.tar.xz - - - https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$UC_VERSION.tar.xz.hashes - - - https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.xz - - - https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-armv7l.tar.xz - - - https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-arm64.tar.xz - - - https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt - node-$NODE_VERSION.sha256sum - + + $orig_src + sha256 + $orig_src_sha256 + + + $debian_src + sha256 + $debian_src_sha256 + + + $(basename $dsc_file) + sha256 + $dsc_sha256 + -EOF - -tar -c -T/dev/null | xz -9 > ungoogled-chromium_$UC_VERSION.orig.tar.xz -tar -c -T/dev/null | xz -9 > ungoogled-chromium_$UC_VERSION.debian.tar.xz -tar -c --exclude-vcs --exclude='download_cache/*' -C $RT_DIR debian/ | xz -9 > ungoogled-chromium.tar.xz - -cat > ungoogled-chromium.dsc << EOF -Format: 3.0 (quilt) -Source: ungoogled-chromium -Binary: ungoogled-chromium -Architecture: any -Version: $UC_VERSION -Maintainer: $AUTHOR -Homepage: https://github.com/Eloston/ungoogled-chromium -Standards-Version: 4.5.0 -Build-Depends: $(sed -n '/^Build-Depends:/,/^$/p' < $DB_DIR/control | tr -d '\n' | cut -f 2 -d : | sed -r 's;^ *| *$;;g') -Package-List: - ungoogled-chromium deb web optional arch=any -Checksums-Sha1: - $(sha1sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz - $(sha1sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz -Checksums-Sha256: - $(sha256sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz - $(sha256sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz -Files: - $(md5sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz - $(md5sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz -EOF - -cat > build.script << EOF -export LANG=C.UTF-8 - -JOBS="\${DEB_BUILD_OPTIONS#*=}" -case "\$(uname -m)" in -aarch64) DEB_BUILD_OPTIONS="parallel=\$(("\$JOBS" / 2))" ;; -esac -JOBS= - -tar -x -f ../SOURCES/ungoogled-chromium.tar.xz -mkdir -p debian/download_cache -ln -s ../../../SOURCES/chromium-$UC_VERSION.tar.xz debian/download_cache/chromium-$UC_VERSION.tar.xz -ln -s ../../../SOURCES/chromium-$UC_VERSION.tar.xz.hashes debian/download_cache/chromium-$UC_VERSION.tar.xz.hashes -ln -s ../../../SOURCES/node-$NODE_VERSION-linux-x64.tar.xz debian/download_cache/node-$NODE_VERSION-linux-x64.tar.xz -ln -s ../../../SOURCES/node-$NODE_VERSION-linux-armv7l.tar.xz debian/download_cache/node-$NODE_VERSION-linux-armv7l.tar.xz -ln -s ../../../SOURCES/node-$NODE_VERSION-linux-arm64.tar.xz debian/download_cache/node-$NODE_VERSION-linux-arm64.tar.xz -ln -s ../../../SOURCES/node-$NODE_VERSION.sha256sum debian/download_cache/node-$NODE_VERSION.sha256sum - -debian/rules setup - -dpkg-buildpackage -b -uc -EOF - -PACKAGE="ungoogled-chromium-debian" - -curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" -F 'cmd=deleteuploadrev' - -curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" > directory.xml - -xmlstarlet sel -t -v '//entry/@name' < directory.xml | while read FILENAME -do - curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE/$FILENAME?rev=upload" -X DELETE -done +END -for FILENAME in _service ungoogled-chromium_$UC_VERSION.orig.tar.xz ungoogled-chromium_$UC_VERSION.debian.tar.xz ungoogled-chromium.tar.xz ungoogled-chromium.dsc build.script -do - curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE/$FILENAME?rev=upload" -T "$FILENAME" -done + commit_message="$package $version -curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" -F 'cmd=commit' +$comment" + + obs_sync_files $codename $upload_dir "$commit_message" + echo ' ' +done -rm -f _service ungoogled-chromium_$UC_VERSION.orig.tar.xz ungoogled-chromium_$UC_VERSION.debian.tar.xz ungoogled-chromium.tar.xz ungoogled-chromium.dsc build.script directory.xml +# end obs-upload.sh diff --git a/.github/workflows/obs-upload.yml b/.github/workflows/obs-upload.yml deleted file mode 100644 index 484537858..000000000 --- a/.github/workflows/obs-upload.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: OBS Upload - -on: - workflow_dispatch: - push: - tags: - - '*' - -jobs: - obs-upload: - runs-on: ubuntu-latest - steps: - - uses: styfle/cancel-workflow-action@0.10.0 - with: - access_token: ${{ github.token }} - - uses: actions/checkout@v3 - - name: Convert from shallow repository to full repository - run: git fetch --unshallow - - name: Initialize submodules - run: git submodule update --init --recursive - - name: Install extra packages - run: sudo apt install -y xmlstarlet - - name: Run OBS Upload Script - env: - OBS_API_USERNAME: ${{ secrets.OBS_API_USERNAME }} - OBS_API_PASSWORD: ${{ secrets.OBS_API_PASSWORD }} - OBS_API_PROJECT: ${{ secrets.OBS_API_PROJECT }} - run: .github/workflows/obs-upload.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..a426ba826 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,144 @@ +--- +name: Release cycle + +on: + repository_dispatch: + types: [new-debian-version, new-uc-version] + workflow_dispatch: + +concurrency: + group: __ungoogled-chromium_singleton__ + +jobs: + main: + runs-on: ubuntu-latest + permissions: + # needed by "gh cache delete" + actions: write + env: + DOWNLOAD_DIR: /home/runner/download + OUTPUT_DIR: /home/runner/output + STATE_DIR: /home/runner/state + WORK_DIR: /home/runner/work + steps: + - name: Clone u-c-d Git repository + uses: actions/checkout@v4 + + - name: Clone u-c Git repository + uses: actions/checkout@v4 + with: + repository: ungoogled-software/ungoogled-chromium + fetch-depth: 20 + fetch-tags: true + path: ungoogled-chromium + + - name: Tweak Dpkg config to elide progress indicators + run: echo 'Dpkg::Use-Pty "false";' | sudo tee /etc/apt/apt.conf.d/55no-use-pty + + - name: Install packages required for upstream check + run: sudo apt-get -y --no-install-recommends install debian-archive-keyring devscripts + + - name: Restore persistent state + id: restore-state + uses: actions/cache/restore@v4 + # https://github.com/actions/runner/discussions/871 + with: + key: state-v${{github.run_id}} + restore-keys: state + path: ${{env.STATE_DIR}} + + - name: Check if new upstream versions are available + id: check + run: .github/workflows/get-latest.sh --skip-download + + - name: Restore download cache + id: restore-download + if: ${{steps.check.outputs.todo}} + uses: actions/cache/restore@v4 + # https://github.com/actions/runner/discussions/871 + with: + key: download-v${{github.run_id}} + restore-keys: download + path: ${{env.DOWNLOAD_DIR}} + + - name: Download latest upstream versions + if: ${{steps.check.outputs.todo}} + run: .github/workflows/get-latest.sh --skip-update + + - name: Remove obsolete files from download cache + if: ${{steps.check.outputs.todo}} + run: | + del_files=$(cat $WORK_DIR/obsolete.chromium.txt) + cd $DOWNLOAD_DIR + rm -fv $del_files + echo 'Download cache contents:' + ls -l + + - name: Save download cache + if: ${{steps.check.outputs.todo}} + uses: actions/cache/save@v4 + with: + key: download-v${{github.run_id}} + path: ${{env.DOWNLOAD_DIR}} + + - name: Delete previous version of download cache + if: ${{steps.check.outputs.todo && steps.restore-download.outputs.cache-matched-key}} + env: + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + run: gh cache delete ${{steps.restore-download.outputs.cache-matched-key}} + + - name: Install packages required for conversion + if: ${{steps.check.outputs.todo}} + run: sudo apt-get -y --no-install-recommends install debian-keyring dpkg-dev quilt + + - name: Patch Dpkg to speed up source package builds + if: ${{steps.check.outputs.todo}} + run: (cd / && sudo patch -p1) < .github/workflows/dpkg-source-build.patch + + - name: Clone osc Git repository + # Needed because the version of osc(1) in ubuntu-22.04 is too old + if: ${{steps.check.outputs.todo}} + uses: actions/checkout@v4 + with: + repository: openSUSE/osc + ref: 21c9828cd1fc51b8d03f0f1aa01c41df38a3630b # 1.8.3 + path: osc + + - name: Convert chromium to ungoogled-chromium + if: ${{steps.check.outputs.todo}} + env: + DEBFULLNAME: ${{vars.DEBFULLNAME}} + DEBEMAIL: ${{vars.DEBEMAIL}} + run: .github/workflows/convert.sh + + - name: Upload u-c packages to OBS + if: ${{steps.check.outputs.todo}} + env: + OSC: ${{github.workspace}}/osc/osc-wrapper.py + OSC_USERNAME: ${{secrets.OSC_USERNAME || vars.OSC_USERNAME}} + OSC_PASSWORD: ${{secrets.OSC_PASSWORD}} + OBS_PROJECT: ${{vars.OBS_PROJECT}} + run: .github/workflows/obs-upload.sh + + - name: Save persistent state + uses: actions/cache/save@v4 + with: + key: state-v${{github.run_id}} + path: ${{env.STATE_DIR}} + + - name: Delete previous version of persistent state + if: ${{steps.restore-state.outputs.cache-matched-key}} + env: + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + run: gh cache delete ${{steps.restore-state.outputs.cache-matched-key}} + + - name: Save converted source package files as artifacts + if: ${{steps.check.outputs.todo}} + uses: actions/upload-artifact@v4 + with: + name: releases + compression-level: 1 + if-no-files-found: ignore + path: ${{env.OUTPUT_DIR}}/* + +# EOF diff --git a/.github/workflows/remote-check.sh b/.github/workflows/remote-check.sh new file mode 100755 index 000000000..b9bfc6288 --- /dev/null +++ b/.github/workflows/remote-check.sh @@ -0,0 +1,200 @@ +#!/bin/bash +# +# Check for new "chromium" package(s) on Debian without all the overhead of +# the GitHub workflow. This script can be invoked from cron(8), from a mail +# delivery agent (e.g. maildrop(1)), or directly. +# +# Recommended crontab entry: +# +# 15 */4 * * * /path/to/remote-check.sh --cron +# +# Mail invocation is intended for use with the Debian package tracker at +# https://tracker.debian.org/ . Create an account with your e-mail address, +# and subscribe to the "chromium" source package, with the "upload-source" +# keyword. Configure your MDA to match on messages with the following +# header fields: +# +# From: Debian FTP Masters +# Subject: Accepted chromium *** (source) into *** +# +# (where "***" is a short string match, like a /.+/ regex. You can see past +# instances of these messages under the "news" section at the tracker's +# Chromium page: https://tracker.debian.org/pkg/chromium) +# +# Then, have it execute this script as +# +# /path/to/remote-check.sh --mail +# +# To invoke the GitHub workflow, you'll need to create a "fine-grained +# personal access token" here: +# +# https://github.com/settings/tokens?type=beta +# +# Under "Repository access", specify the ungoogled-chromium-debian repo, +# and under "Repository permissions -> Contents", grant "read and write" +# access. Then place the token string in a file token.txt in the state +# directory (see below). +# +# You can invoke the workflow directly with "remote-check.sh --start". +# + +state_dir=$HOME/.cache/uc-remote-check +github_repo=ungoogled-software/ungoogled-chromium-debian + +debian_incoming_url=https://incoming.debian.org/debian-buildd +debian_security_url=https://security.debian.org/debian-security + +common_curl_args="--hsts $state_dir/curl-hsts.txt --max-time 30 --no-progress-meter" + +log() +{ + local message="$1" + local dt=$(date --rfc-3339=sec) + echo "[$dt]${message:+ $message}" +} + +start_workflow() +{ + local github_token=$(cat $state_dir/token.txt 2>/dev/null) + + case "$github_token" in + github_pat_*) ;; + '') echo 'Cannot start workflow, no GitHub token present'; return 0 ;; + *) echo 'Error: Invalid GitHub token'; return 2 ;; + esac + + log "Starting release workflow at $github_repo" + + local headers_file=$state_dir/tmp.headers.txt + + (umask 077; cat > $headers_file) << END +Accept: application/vnd.github+json +Authorization: token $github_token +END + + curl \ + --header @$headers_file \ + --data '{"event_type": "new-debian-version"}' \ + --fail-with-body \ + $common_curl_args \ + https://api.github.com/repos/$github_repo/dispatches +} + +do_check() +{ + local hash_dsc_file=$state_dir/debian-hash-dsc.txt + local seen_dsc_file=$state_dir/debian-seen-dsc.txt + + local index=$state_dir/tmp.index-1.txt + local index_concat=$state_dir/tmp.index-2.txt + local new_dsc_file=$state_dir/tmp.new-dsc.txt + + log 'Checking Debian servers ...' + + : > $index_concat + : > $new_dsc_file + + local url + for url in \ + $debian_incoming_url \ + $debian_security_url + do + curl \ + --output $index \ + --compressed \ + --fail \ + $common_curl_args \ + $url/pool/main/c/chromium/ + + # Note: The "incoming" server may return a 404 when no + # recent package release is available + + cat $index >> $index_concat 2>/dev/null + done + + # First-level check + + local dsc_hash=$(grep -F .dsc $index_concat | md5sum | awk '{print $1}') + local prev_dsc_hash=$(cat $hash_dsc_file 2>/dev/null) + + if [ "_$dsc_hash" = "_$prev_dsc_hash" ] + then + echo 'No change in available .dsc files' + return 1 + fi + + # Second-level check + + grep -Eo ' href="[^ "]+\.dsc"' $index_concat \ + | cut -d'"' -f2 \ + | while read dsc + do + if ! grep -Fqx "$dsc" $seen_dsc_file 2>/dev/null + then + echo "Found new .dsc file: $dsc" + echo "$dsc" >> $new_dsc_file + fi + done + + if [ ! -s $new_dsc_file ] + then + echo 'No new .dsc file(s) found' + rm -f $new_dsc_file + return 1 + fi + + # New release found + + if [ -f $seen_dsc_file ] + then + start_workflow || return + else + echo 'Initial run, not starting workflow' + fi + + cat $new_dsc_file >> $seen_dsc_file + echo $dsc_hash > $hash_dsc_file + + rm -f $new_dsc_file +} + +from_cron=false +from_mail=false +start=false + +case "$1" in + --cron) from_cron=true ;; + --mail) from_mail=true ;; + --start) start=true ;; +esac + +mkdir -p $state_dir || exit +tty -s || exec >> $state_dir/log.txt 2>&1 + +if $from_cron +then + sleep_time=$((RANDOM % 300)) + log "Started from cron, waiting $sleep_time seconds ..." + sleep $sleep_time + do_check +elif $from_mail +then + log 'Started by mail message' + for try in $(seq 1 20) + do + ! do_check || break + sleep_time=$((90 + RANDOM % 30)) + log "Waiting $sleep_time seconds ..." + sleep $sleep_time + done +elif $start +then + start_workflow +else + do_check +fi + +rm -f $state_dir/tmp.* +echo + +# EOF